Enviar datos al servidor o proxy de Zabbix
zabbix_utils le permite enviar valores de item a un item trapper en el servidor o proxy de Zabbix (de manera similar a Zabbix sender).
Puede enviar un único valor, múltiples valores o incluso dirigirse a varios clústeres de Zabbix.
Los datos pueden enviarse en modo síncrono o asíncrono:
- En modo síncrono, su script de Python envía valores y espera una respuesta antes de continuar; esto es adecuado para operaciones simples, secuenciales y predecibles.
- En modo asíncrono, el script envía valores sin esperar cada respuesta, permitiendo que otras operaciones continúen en paralelo; esto es más eficiente para solicitudes lentas o grandes lotes de datos.
Los ejemplos de esta página se centran en el modo síncrono, aunque el modo asíncrono sigue patrones similares. Hay ejemplos adicionales disponibles en el repositorio de GitHub zabbix_utils.
Importar
Para usar zabbix_utils para enviar valores de item, importe la clase Sender en su script:
from zabbix_utils import Sender
Para enviar múltiples valores, también puede importar la clase ItemValue:
from zabbix_utils import Sender, ItemValue
Enviar un único valor
Para enviar el valor de un item:
- Cree una instancia de
Sender, especificando la dirección IP y el puerto de su Zabbix server o proxy. - Llame al método
send_value()en la instancia deSenderutilizando el siguiente formato:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
Por ejemplo, para enviar 1 al item trapper service.status en el host Linux server:
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Usar una IP no predeterminada
Si el servidor que ejecuta su script tiene varias direcciones IP, puede especificar una source_ip para que el Sender la utilice al enviar valores al servidor o proxy de Zabbix:
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
Usando timeout
Puede establecer un timeout de respuesta para el Sender para controlar cuánto tiempo debe esperar su script una respuesta del servidor o proxy de Zabbix antes de rendirse:
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
Usar el archivo de configuración del agent
Puede permitir que zabbix_utils lea los parámetros Server o ServerActive desde un archivo de configuración local de Zabbix agent o agent 2.
En tales casos, no es necesario especificar los parámetros de conexión al crear una instancia de Sender:
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
Si ServerActive contiene uno o más clústeres de Zabbix con varias instancias de server, Sender envía datos al primer server disponible en cada clúster.
Si ServerActive no está configurado, se utiliza la dirección de Server con el puerto predeterminado (10051).
Usando cifrado
El Sender no incluye soporte de cifrado incorporado, pero puede proporcionarlo creando un wrapper usando librerías de terceros:
def psk_wrapper(sock, tls):
# ...
# Implementación del wrapper TLS PSK para el socket
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
Respuesta para un solo valor
La respuesta devuelta por el server o proxy de Zabbix es procesada por la biblioteca y devuelta como un objeto TrapperResponse:
print(response)
# {"processed": 1, "failed": 0, "total": 1, "time": "0.000123", "chunk": 1}
print(response.processed)
# 1
print(response.failed)
# 0
print(response.total)
# 1
Modo asíncrono
El modo asíncrono permite que tu script de Python envíe valores sin esperar una respuesta del servidor o proxy de Zabbix. Esto puede hacer que tu script sea más eficiente cuando necesita enviar muchos valores o cuando algunos valores tardan mucho en enviarse.
Al utilizar el modo asíncrono, hay algunas diferencias importantes en comparación con el modo síncrono:
- Importa el módulo
asynciode Python (primero debes instalar las dependencias requeridas). - Importa
AsyncSenderen lugar deSender. - Escribe tu código dentro de una función
async. - Utiliza
awaital llamar al métodosend_value().
Por ejemplo, para enviar un solo valor utilizando el modo asíncrono:
# 1. Importa asyncio para el modo asíncrono y AsyncSender desde zabbix_utils:
import asyncio
from zabbix_utils import AsyncSender
# 2. Define la función principal async donde se ejecutarán todas las operaciones de envío de datos (deben usar await):
async def main():
sender = AsyncSender(server='127.0.0.1', port=10051)
response = await sender.send_value('Linux server', 'service.status', 1)
# 3. Imprime la respuesta devuelta por el servidor o proxy de Zabbix:
print(response)
# 4. Ejecuta la función async main() utilizando el bucle de eventos de asyncio:
asyncio.run(main())
Enviar múltiples valores
Para enviar múltiples valores:
- Prepare un array de objetos
ItemValue, cada uno usando el mismo formato que el métodosend_value(). - Cree una instancia de
Sender, especificando la dirección IP y el puerto de su Zabbix server o proxy. - Llame al método
send()(en lugar desend_value()) en la instancia deSender, especificando el array de objetos con los valores a enviar.
Por ejemplo, para enviar cinco valores a diferentes hosts:
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(server='127.0.0.1', port=10051)
response = sender.send(items)
Usar un tamaño de fragmento personalizado
Si necesita enviar más valores de los que un item trapper puede aceptar en una sola solicitud, puede dividirlos en fragmentos.
Por defecto, el tamaño del fragmento es de 250 valores.
Puede cambiarlo estableciendo el parámetro chunk_size al crear una instancia de Sender.
Por ejemplo, para enviar cinco valores en tres fragmentos (2-2-1), establezca el parámetro chunk_size en 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(server='127.0.0.1', port=10051, chunk_size=2)
response = sender.send(items)
Enviar valores a varios clústeres de Zabbix
Para enviar valores a varios clústeres de Zabbix:
- Prepare una matriz de clústeres de Zabbix. Si un clúster tiene varios nodos, el valor se enviará al primer nodo disponible de cada clúster.
- Cree un
Sender, especificando su matriz de clústeres de Zabbix. - Llame al método
send_value()en la instancia deSenderutilizando el mismo formato que el métodosend_value().
Por ejemplo, para enviar un valor al primer nodo 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)
Respuesta para múltiples valores
Por defecto, Sender devuelve un resultado agregado del envío de valores a todos los hosts o clústeres:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
Si necesita información más detallada, puede inspeccionar los resultados para cada clúster y cada fragmento utilizando el atributo response.details:
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