Enviar dades al servidor o proxy de Zabbix

zabbix_utils us permet enviar valors d'element a element de trapper al servidor o proxy de Zabbix (similarment a l'emissor de Zabbix.

Podeu enviar un únic valor, diversos valors o fins i tot orientar diversos clústers de Zabbix.

Les dades es poden enviar en mode síncron o asíncron:

  • En mode síncron, el vostre script Python envia valors i espera una resposta abans de continuar; això és adequat per a operacions senzilles, seqüencials i predictibles.
  • En mode asíncron, l'script envia valors sense esperar cada resposta, permetent que altres operacions procedeixin en paral·lel; això és més eficient per a peticions lentes o grans lots de dades.

Els exemples d'aquesta pàgina se centren en el mode síncron, encara que mode asíncron segueix patrons similars. Exemples addicionals estan disponibles al repositori zabbix_utils GitHub.

Importar

Per utilitzar zabbix_utils per enviar valors d'element, importa la classe Sender de l'script:

from zabbix_utils import Sender

Per a l'enviament de diversos valors, també podeu importar la classe ItemValue:

from zabbix_utils import Sender, ItemValue

Enviar un únic valor

Per enviar un valor d'element:

  1. Creeu una instància Remitent, especificant l'adreça IP i el port del vostre servidor o proxy de Zabbix.
  2. Crideu el mètode send_value() a la instància Sender utilitzant el següent format:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, opcional_nanoseconds)

Per exemple, per enviar 1 a l'element service.status trapper a l'equip Servidor Linux:

sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Emprant adreces IP que no són per defecte IP

Si el servidor que executa l'script té diverses adreces IP, podeu especificar un source_ip perquè el remetent s'empri en enviar valors al servidor o proxy de Zabbix:

sender = Sender(
    server='127.0.0.1',
    port=10051,
    source_ip='10.10.7.1'
)
Ús de temps d'espera

Podeu establir una resposta temps d'espera per al Remitent per controlar quant de temps ha d'esperar el vostre script per a una resposta del servidor o proxy de Zabbix abans de renunciar:

sender = Sender(
    server='127.0.0.1',
    port=10051,
    timeout=30
)
Ús del fitxer de configuració de l'agent

Podeu deixar que zabbix_utils llegeixi els paràmetres Server o [ServerActive]/manual/appendix/config/zabbix_agentd#serveractive) des d'un fitxer de configuració local de Zabbix o agent 2. En aquests casos, no cal especificar els paràmetres de connexió quan creeu una instància Remitent:

sender= Sender(
    use_config=True,
    config_path='/etc/zabbix/zabbix_agent2.conf'
)

::: nota important Si ServerActive conté un o més clústers de Zabbix amb múltiples instàncies de servidor, Sender envia dades al primer servidor disponible a cada clúster. Si ServerActive no és pas establert, s'empra l'adreça de Server amb el port per defecte (10051). :::

Ús del xifrat

El Sender no inclou compatibilitat amb el xifrat integrat, però podeu proporcionar-la creant un contenidor utilitzant biblioteques de tercers:

Implementació del contenidor TLS PSK per al sòcol

def psk_wrapper(sock, tls):
    # ...
    # Implementació del contenidor TLS PSK per al socket
    # ...

sender= Sender(
    server='127.0.0.1',
    port=10051,
    socket_wrapper=psk_wrapper
)
Resposta per a un valor únic

La resposta retornada pel servidor o proxy de Zabbix és processada per la biblioteca i retornada com a objecte TrapperResponse:

print(response)
# {"processat": 1, "fallit": 0, "total": 1, "temps": "0.000123", "chunk": 1}

print(response.processed)
# 1

print(response.failed)
# 0

print(response.total)
# 1
Mode asíncron

El mode asíncron permet que el vostre script Python enviï valors sense esperar una resposta del servidor o del proxy de Zabbix. Això pot fer que el vostre script sigui més eficient quan necessita enviar molts valors o quan alguns valors triguen molt a enviar-los.

Quan s'utilitza el mode asíncron, hi ha algunes diferències importants en comparació amb el mode síncron:

  • Importar el mòdul asyncio de Python (primer heu de instal·lar les dependències requerides).
  • Importació AsyncSender en lloc de Remitent.
  • Escriu el teu codi dins d'una funció async.
  • Utilitzeu await quan crideu el mètode send_value().

Per exemple, per enviar un únic valor utilitzant el mode asíncron:

# 1. Importa asyncio per al mode asíncron, i AsyncSender de zabbix_utils:
import asyncio
from zabbix_utils import AsyncSender

# 2. Definir la funció principal async on s'executaran totes les operacions d'enviament de dades (s'ha d'esperar):
async def main():
    sender = AsyncSender(server='127.0.0.1', port=10051)
    response = await sender.send_value('Linux server', 'service.status', 1)

    # 3. Imprimeix la resposta retornada pel servidor Zabbix o proxy:
    print(response)

# 4. Executeu la funció async main() utilitzant el bucle d'esdeveniments d'asyncio:
asyncio.run(main()))
Envia diversos valors

Per enviar diversos valors:

  1. Prepareu una matriu d'objectes ItemValue, cadascun utilitzant el mateix format que el mètode send_value().
  2. Creeu una instància Remitent, especificant l'adreça IP i el port del vostre servidor o proxy de Zabbix.
  3. Crida el mètode send() (en lloc de send_value()) a la instància Sender, especificant l'array d'objectes amb valors a enviar.

Per exemple, per enviar cinc valors a diferents equips:

items = [
    ItemValue('server-de', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-fr', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-uk', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-nl', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-pl', 'service.status', 'up', 1770887205, 100),
]

sender = Sender(servidor='127.0.0.1', port=10051)
response = sender.send(elements)
Ús de la mida del tros personalitzat

Si necessiteu enviar més valors que un element de caçador pot acceptar en una sola petició, podeu dividir-los en trossos.

Per defecte, la mida del tros és de 250 valors. Podeu canviar-lo establint el paràmetre chunk_size quan creeu una instància Sender.

Per exemple, per enviar cinc valors en tres trossos (2-2-1), establiu el paràmetre chunk_size a 2:

items = [
    ItemValue('server-de', 'service.status', 'up'),
    ItemValue('server-fr', 'service.status', 'up'),
    ItemValue('server-uk', 'service.status', 'up'),
    ItemValue('server-nl', 'service.status', 'up'),
    ItemValue('server-pl', 'service.status', 'up'),
]

sender = Sender(servidor='127.0.0.1', port=10051, chunk_size=2)
response = sender.send(elements)
Envia valors a múltiples clústers de Zabbix

Per enviar valors a diversos clústers de Zabbix:

  1. Prepareu una sèrie de clústers de Zabbix. Si un clúster té múltiples nodes, el valor s'enviarà al primer node disponible de cada clúster.
  2. Creeu un 'Sender', especificant la vostra matriu de clústers de Zabbix.
  3. Crida el mètode send_value() a la instància Sender utilitzant el mateix format que el mètode send_value().

Per exemple, per enviar un valor al primer node disponible en cada clúster:

zabbix_clusters = [
    ['zabbix.cluster1.node1', 'zabbix.cluster1.node2:10051'],
    ['zabbix.cluster2.node1:10051', 'zabbix.cluster2.node2', 'zabbix.cluster2.node3']
]

sender = Sender(clusters=zabbix_clusters)
response = sender.send_value('Linux server', 'service.status', 1)
Response for multiple values

By default, Sender returns an aggregated result of sending values across all hosts or clusters:

print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}

If you need more detailed information, you can inspect the results for each cluster and each chunk using the response.details attribute:

print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}

if response.failed == 0:
    print(f"Value sent successfully in {response.time}")
else:
    print(response.details)
    # {
    #     127.0.0.1:10051: [
    #         {
    #             "processed": 1,
    #             "failed": 0,
    #             "total": 1,
    #             "time": "0.000051",
    #             "chunk": 1
    #         }
    #     ],
    #     zabbix.example.local:10051: [
    #         {
    #             "processed": 1,
    #             "failed": 0,
    #             "total": 1,
    #             "time": "0.000057",
    #             "chunk": 1
    #         }
    #     ]
    # }

    for node, chunks in response.details.items():
        for resp in chunks:
            print(f"Processed {resp.processed} of {resp.total} at {node.address}:{node.port}")
            # Processed 1 of 1 at 127.0.0.1:10051
            # Processed 1 of 1 at zabbix.example.local:10051