Send data to Zabbix server or proxy
zabbix_utils lets you send item values to a trapper item on Zabbix server or proxy (similarly to Zabbix sender).
You can send a single value, multiple values, or even target multiple Zabbix clusters.
Data can be sent in synchronous or asynchronous mode:
- In synchronous mode, your Python script sends values and waits for a response before continuing; this is suitable for simple, sequential, and predictable operations.
- In asynchronous mode, the script sends values without waiting for each response, allowing other operations to proceed in parallel; this is more efficient for slow requests or large batches of data.
The examples on this page focus on synchronous mode, though asynchronous mode follows similar patterns. Additional examples are available in the zabbix_utils GitHub repository.
Import
To use zabbix_utils for sending item values, import the Sender class in your script:
from zabbix_utils import Sender
For sending multiple values, you may also import the ItemValue class:
from zabbix_utils import Sender, ItemValue
Send single value
To send an item value:
- Create a
Senderinstance, specifying the IP address and port of your Zabbix server or proxy. - Call the
send_value()method on theSenderinstance using the following format:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
For example, to send 1 to the service.status trapper item on the Linux server host:
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Using non-default IP
If the server running your script has multiple IP addresses, you can specify a source_ip for the Sender to use when sending values to Zabbix server or proxy:
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
Using timeout
You can set a response timeout for the Sender to control how long your script should wait for a response from Zabbix server or proxy before giving up:
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
Using agent configuration file
You can let zabbix_utils read the Server or ServerActive parameters from a local Zabbix agent or agent 2 configuration file.
In such cases, you don't need to specify connection parameters when creating a Sender instance:
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
If ServerActive contains one or more Zabbix clusters with multiple server instances, Sender sends data to the first available server in each cluster.
If ServerActive is not set, the address from Server with the default port (10051) is used.
Using encryption
The Sender does not include built-in encryption support, but you can provide it by creating a wrapper using third-party libraries:
def psk_wrapper(sock, tls):
# ...
# Implementation of TLS PSK wrapper for the socket
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
Response for single value
The response returned by Zabbix server or proxy is processed by the library and returned as a TrapperResponse object:
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
Asynchronous mode
Asynchronous mode lets your Python script send values without waiting for a response from Zabbix server or proxy. This can make your script more efficient when it needs to send many values or when some values take a long time send.
When using asynchronous mode, there are a few important differences compared to synchronous mode:
- Import Python's
asynciomodule (you must first install the required dependencies). - Import
AsyncSenderinstead ofSender. - Write your code inside an
asyncfunction. - Use
awaitwhen calling thesend_value()method.
For example, to send a single value using asynchronous mode:
# 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())
Send multiple values
To send multiple values:
- Prepare an array of
ItemValueobjects, each using the same format as thesend_value()method. - Create a
Senderinstance, specifying the IP address and port of your Zabbix server or proxy. - Call the
send()method (instead ofsend_value()) on theSenderinstance, specifying the array of objects with values to send.
For example, to send five values to different 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)
Using custom chunk size
If you need to send more values than a trapper item can accept in a single request, you can split them into chunks.
By default, the chunk size is 250 values.
You can change it by setting the chunk_size parameter when creating a Sender instance.
For example, to send five values in three chunks (2-2-1), set the chunk_size parameter to 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)
Send values to multiple Zabbix clusters
To send values to multiple Zabbix clusters:
- Prepare an array of Zabbix clusters. If a cluster has multiple nodes, the value will be sent to the first available node of each cluster.
- Create a
Sender, specifying your array of Zabbix clusters. - Call the
send_value()method on theSenderinstance using the same format as thesend_value()method.
For example, to send a value to the first available node in each 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)
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