Envoyer des données au serveur ou au proxy Zabbix
zabbix_utils vous permet d'envoyer des valeurs d'élément à un élément trapper sur le serveur ou le proxy Zabbix (de manière similaire à Zabbix sender).
Vous pouvez envoyer une seule valeur, plusieurs valeurs, ou même cibler plusieurs clusters Zabbix.
Les données peuvent être envoyées en mode synchrone ou asynchrone :
- En mode synchrone, votre script Python envoie des valeurs et attend une réponse avant de continuer ; cela convient aux opérations simples, séquentielles et prévisibles.
- En mode asynchrone, le script envoie des valeurs sans attendre chaque réponse, ce qui permet à d'autres opérations de se poursuivre en parallèle ; cela est plus efficace pour les requêtes lentes ou les lots de données volumineux.
Les exemples de cette page se concentrent sur le mode synchrone, bien que le mode asynchrone suive des principes similaires. Des exemples supplémentaires sont disponibles dans le dépôt GitHub zabbix_utils.
Importation
Pour utiliser zabbix_utils afin d’envoyer des valeurs d’élément, importez la classe Sender dans votre script :
from zabbix_utils import Sender
Pour envoyer plusieurs valeurs, vous pouvez également importer la classe ItemValue :
from zabbix_utils import Sender, ItemValue
Envoyer une valeur unique
Pour envoyer une valeur d’élément :
- Créez une instance de
Sender, en spécifiant l’adresse IP et le port de votre serveur ou proxy Zabbix. - Appelez la méthode
send_value()sur l’instanceSenderen utilisant le format suivant :
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
Par exemple, pour envoyer 1 à l’élément trapper service.status sur l’hôte Linux server :
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Utilisation d’une IP non par défaut
Si le serveur exécutant votre script possède plusieurs adresses IP, vous pouvez spécifier un source_ip que le Sender utilisera lors de l’envoi des valeurs au serveur Zabbix ou au proxy :
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
Utilisation du délai d’expiration
Vous pouvez définir un timeout de réponse pour le Sender afin de contrôler combien de temps votre script doit attendre une réponse du serveur Zabbix ou du proxy avant d’abandonner :
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
Utilisation du fichier de configuration de l'agent
Vous pouvez laisser zabbix_utils lire les paramètres Server ou ServerActive à partir d’un fichier de configuration local de l’agent Zabbix ou de l’agent 2.
Dans ce cas, vous n’avez pas besoin de spécifier les paramètres de connexion lors de la création d’une instance de Sender :
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
Si ServerActive contient un ou plusieurs clusters Zabbix avec plusieurs instances de serveur, Sender envoie les données au premier serveur disponible dans chaque cluster.
Si ServerActive n’est pas défini, l’adresse de Server avec le port par défaut (10051) est utilisée.
Utilisation du chiffrement
Le Sender n’inclut pas de prise en charge intégrée du chiffrement, mais vous pouvez l’ajouter en créant un wrapper à l’aide de bibliothèques tierces :
def psk_wrapper(sock, tls):
# ...
# Implémentation du wrapper TLS PSK pour le socket
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
Réponse pour une valeur unique
La réponse renvoyée par le serveur Zabbix ou le proxy est traitée par la bibliothèque et renvoyée sous la forme d’un objet 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
Mode asynchrone
Le mode asynchrone permet à votre script Python d'envoyer des valeurs sans attendre de réponse du serveur Zabbix ou du proxy. Cela peut rendre votre script plus efficace lorsqu'il doit envoyer de nombreuses valeurs ou lorsque certaines valeurs prennent beaucoup de temps à être envoyées.
Lors de l'utilisation du mode asynchrone, il existe quelques différences importantes par rapport au mode synchrone :
- Importez le module
asynciode Python (vous devez d'abord installer les dépendances requises). - Importez
AsyncSenderau lieu deSender. - Écrivez votre code dans une fonction
async. - Utilisez
awaitlors de l'appel de la méthodesend_value().
Par exemple, pour envoyer une seule valeur en utilisant le mode asynchrone :
# 1. Import asyncio for asynchronous mode, and AsyncSender from zabbix_utils:
import asyncio
from zabbix_utils import AsyncSender
# 2. Define the main async function where all data sending operations (must await) will be executed:
async def main():
sender = AsyncSender(server='127.0.0.1', port=10051)
response = await sender.send_value('Linux server', 'service.status', 1)
# 3. Print the response returned by Zabbix server or proxy:
print(response)
# 4. Run the async main() function using asyncio's event loop:
asyncio.run(main())
Envoyer plusieurs valeurs
Pour envoyer plusieurs valeurs :
- Préparez un tableau d’objets
ItemValue, chacun utilisant le même format que la méthodesend_value(). - Créez une instance de
Sender, en spécifiant l’adresse IP et le port de votre serveur Zabbix ou proxy. - Appelez la méthode
send()(au lieu desend_value()) sur l’instanceSender, en indiquant le tableau d’objets contenant les valeurs à envoyer.
Par exemple, pour envoyer cinq valeurs à différents hôtes :
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)
Utilisation d’une taille de bloc personnalisée
Si vous devez envoyer plus de valeurs qu’un élément collecteur ne peut en accepter dans une seule requête, vous pouvez les diviser en blocs.
Par défaut, la taille du bloc est de 250 valeurs.
Vous pouvez la modifier en définissant le paramètre chunk_size lors de la création d’une instance de Sender.
Par exemple, pour envoyer cinq valeurs en trois blocs (2-2-1), définissez le paramètre chunk_size sur 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)
Envoyer des valeurs à plusieurs clusters Zabbix
Pour envoyer des valeurs à plusieurs clusters Zabbix :
- Préparez un tableau de clusters Zabbix. Si un cluster comporte plusieurs nœuds, la valeur sera envoyée au premier nœud disponible de chaque cluster.
- Créez un
Senderen spécifiant votre tableau de clusters Zabbix. - Appelez la méthode
send_value()sur l’instanceSenderen utilisant le même format que la méthodesend_value().
Par exemple, pour envoyer une valeur au premier nœud disponible de chaque 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)
Réponse pour plusieurs valeurs
Par défaut, Sender renvoie un résultat agrégé de l’envoi des valeurs sur tous les hôtes ou clusters :
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
Si vous avez besoin d’informations plus détaillées, vous pouvez examiner les résultats pour chaque cluster et chaque bloc à l’aide de l’attribut response.details :
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
if response.failed == 0:
print(f"Valeur envoyée avec succès en {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"Traité {resp.processed} sur {resp.total} à {node.address}:{node.port}")
# Traité 1 sur 1 à 127.0.0.1:10051
# Traité 1 sur 1 à zabbix.example.local:10051