Enviar dados para o Zabbix server ou proxy
zabbix_utils permite enviar valores de item para um item trapper no Zabbix server ou proxy (de forma semelhante ao Zabbix sender).
Você pode enviar um único valor, múltiplos valores ou até mesmo direcionar múltiplos clusters Zabbix.
Os dados podem ser enviados em modo síncrono ou assíncrono:
- No modo síncrono, seu script Python envia valores e aguarda uma resposta antes de continuar; isso é adequado para operações simples, sequenciais e previsíveis.
- No modo assíncrono, o script envia valores sem esperar por cada resposta, permitindo que outras operações prossigam em paralelo; isso é mais eficiente para solicitações lentas ou grandes lotes de dados.
Os exemplos nesta página focam no modo síncrono, embora o modo assíncrono siga padrões semelhantes. Exemplos adicionais estão disponíveis no repositório GitHub do zabbix_utils.
Importação
Para usar o zabbix_utils para enviar valores de item, importe a classe Sender em seu script:
from zabbix_utils import Sender
Para enviar vários valores, você também pode importar a classe ItemValue:
from zabbix_utils import Sender, ItemValue
Enviar valor único
Para enviar o valor de um item:
- Crie uma instância de
Sender, especificando o endereço IP e a porta do seu Zabbix server ou proxy. - Chame o método
send_value()na instância deSenderusando o seguinte formato:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
Por exemplo, para enviar 1 para o item trapper service.status no host Linux server:
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Usando IP não padrão
Se o servidor que executa seu script tiver vários endereços IP, você pode especificar um source_ip para o Sender usar ao enviar valores para o server ou proxy do Zabbix:
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
Usando timeout
Você pode definir um timeout de resposta para o Sender para controlar quanto tempo seu script deve aguardar por uma resposta do Zabbix server ou proxy antes de desistir:
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
Usando o arquivo de configuração do agent
Você pode permitir que o zabbix_utils leia os parâmetros Server ou ServerActive de um arquivo de configuração local do Zabbix agent ou agent 2.
Nesses casos, você não precisa especificar os parâmetros de conexão ao criar uma instância do Sender:
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
Se ServerActive contiver um ou mais clusters Zabbix com múltiplas instâncias de server, o Sender enviará dados para o primeiro server disponível em cada cluster.
Se ServerActive não estiver definido, o endereço de Server com a porta padrão (10051) será usado.
Usando criptografia
O Sender não inclui suporte de criptografia embutido, mas você pode fornecê-lo criando um wrapper usando bibliotecas de terceiros:
def psk_wrapper(sock, tls):
# ...
# Implementação do wrapper TLS PSK para o socket
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
Resposta para valor único
A resposta retornada pelo Zabbix server ou proxy é processada pela biblioteca e retornada como um 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 assíncrono
O modo assíncrono permite que seu script Python envie valores sem esperar por uma resposta do Zabbix server ou proxy. Isso pode tornar seu script mais eficiente quando ele precisa enviar muitos valores ou quando alguns valores demoram muito para serem enviados.
Ao usar o modo assíncrono, há algumas diferenças importantes em relação ao modo síncrono:
- Importe o módulo
asynciodo Python (você deve primeiro instalar as dependências necessárias). - Importe
AsyncSenderem vez deSender. - Escreva seu código dentro de uma função
async. - Use
awaitao chamar o métodosend_value().
Por exemplo, para enviar um único valor usando o modo assíncrono:
# 1. Importe asyncio para o modo assíncrono e AsyncSender de zabbix_utils:
import asyncio
from zabbix_utils import AsyncSender
# 2. Defina a função principal async onde todas as operações de envio de dados (devem aguardar) serão executadas:
async def main():
sender = AsyncSender(server='127.0.0.1', port=10051)
response = await sender.send_value('Linux server', 'service.status', 1)
# 3. Imprima a resposta retornada pelo Zabbix server ou proxy:
print(response)
# 4. Execute a função async main() usando o event loop do asyncio:
asyncio.run(main())
Enviar múltiplos valores
Para enviar múltiplos valores:
- Prepare um array de objetos
ItemValue, cada um usando o mesmo formato do métodosend_value(). - Crie uma instância de
Sender, especificando o endereço IP e a porta do seu Zabbix server ou proxy. - Chame o método
send()(em vez desend_value()) na instância deSender, especificando o array de objetos com os valores a serem enviados.
Por exemplo, para enviar cinco valores para 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)
Usando tamanho de bloco personalizado
Se você precisar enviar mais valores do que um item trapper pode aceitar em uma única solicitação, poderá dividi-los em blocos.
Por padrão, o tamanho do bloco é de 250 valores.
Você pode alterá-lo definindo o parâmetro chunk_size ao criar uma instância de Sender.
Por exemplo, para enviar cinco valores em três blocos (2-2-1), defina o parâmetro chunk_size como 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 para vários clusters Zabbix
Para enviar valores para vários clusters Zabbix:
- Prepare um array de clusters Zabbix. Se um cluster tiver vários nós, o valor será enviado para o primeiro nó disponível de cada cluster.
- Crie um
Sender, especificando seu array de clusters Zabbix. - Chame o método
send_value()na instância doSenderusando o mesmo formato do métodosend_value().
Por exemplo, para enviar um valor para o primeiro nó disponível em cada cluster:
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)
Resposta para múltiplos valores
Por padrão, o Sender retorna um resultado agregado do envio de valores em todos os hosts ou clusters:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
Se você precisar de informações mais detalhadas, pode inspecionar os resultados de cada cluster e de cada chunk usando o 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