Отправка данных на сервер Zabbix или прокси
zabbix_utils позволяет отправлять значения элементов данных в trapper item на сервер Zabbix или прокси (аналогично Zabbix sender).
Вы можете отправить одно значение, несколько значений или даже данные сразу в несколько кластеров Zabbix.
Данные можно отправлять в синхронном или асинхронном режиме:
- В синхронном режиме ваш Python-скрипт отправляет значения и ожидает ответа перед продолжением; это подходит для простых, последовательных и предсказуемых операций.
- В асинхронном режиме скрипт отправляет значения, не ожидая каждого ответа, что позволяет параллельно выполнять другие операции; это более эффективно для медленных запросов или больших пакетов данных.
Примеры на этой странице сосредоточены на синхронном режиме, хотя асинхронный режим использует схожие подходы. Дополнительные примеры доступны в GitHub-репозитории zabbix_utils.
Импорт
Чтобы использовать zabbix_utils для отправки значений элементов данных, импортируйте класс Sender в ваш скрипт:
from zabbix_utils import Sender
Для отправки нескольких значений вы также можете импортировать класс ItemValue:
from zabbix_utils import Sender, ItemValue
Отправка одного значения
Чтобы отправить значение элемента данных:
- Создайте экземпляр
Sender, указав IP-адрес и порт вашего сервера или прокси Zabbix. - Вызовите метод
send_value()для экземпляраSender, используя следующий формат:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
Например, чтобы отправить 1 в элемент данных trapper service.status на узле сети Linux server:
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Использование нестандартного IP-адреса
Если сервер, на котором выполняется ваш скрипт, имеет несколько IP-адресов, вы можете указать source_ip, который Sender будет использовать при отправке значений на сервер Zabbix или прокси:
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
Использование timeout
Вы можете задать timeout ответа для Sender, чтобы определить, как долго ваш скрипт должен ожидать ответа от сервера Zabbix или прокси, прежде чем прекратить ожидание:
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
Использование файла конфигурации агента
Вы можете разрешить zabbix_utils считывать параметры Server или ServerActive из локального файла конфигурации Zabbix агента или агента 2.
В таких случаях вам не нужно указывать параметры подключения при создании экземпляра Sender:
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
Если ServerActive содержит один или несколько кластеров Zabbix с несколькими экземплярами сервера, Sender отправляет данные на первый доступный сервер в каждом кластере.
Если ServerActive не задан, используется адрес из Server с портом по умолчанию (10051).
Использование шифрования
Sender не включает встроенную поддержку шифрования, но вы можете обеспечить её, создав обёртку с использованием сторонних библиотек:
def psk_wrapper(sock, tls):
# ...
# Реализация обёртки TLS PSK для сокета
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
Ответ для одного значения
Ответ, возвращаемый сервером Zabbix или прокси, обрабатывается библиотекой и возвращается как объект 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
Асинхронный режим
Асинхронный режим позволяет вашему Python-скрипту отправлять значения без ожидания ответа от сервера Zabbix или прокси. Это может сделать ваш скрипт более эффективным, когда ему нужно отправить много значений или когда отправка некоторых значений занимает много времени.
При использовании асинхронного режима есть несколько важных отличий по сравнению с синхронным режимом:
- Импортируйте модуль Python
asyncio(сначала необходимо install требуемые зависимости). - Импортируйте
AsyncSenderвместоSender. - Пишите код внутри функции
async. - Используйте
awaitпри вызове методаsend_value().
Например, чтобы отправить одно значение в асинхронном режиме:
# 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())
Отправка нескольких значений
Чтобы отправить несколько значений:
- Подготовьте массив объектов
ItemValue, каждый из которых использует тот же формат, что и методsend_value(). - Создайте экземпляр
Sender, указав IP-адрес и порт вашего сервера Zabbix или прокси. - Вызовите метод
send()(вместоsend_value()) для экземпляраSender, указав массив объектов со значениями для отправки.
Например, чтобы отправить пять значений на разные узлы сети:
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)
Использование пользовательского размера чанка
Если вам нужно отправить больше значений, чем элемент данных trapper может принять в одном запросе, вы можете разделить их на чанки.
По умолчанию размер чанка составляет 250 значений.
Вы можете изменить его, задав параметр chunk_size при создании экземпляра Sender.
Например, чтобы отправить пять значений в трёх чанках (2-2-1), задайте параметр chunk_size равным 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)
Отправка значений в несколько кластеров Zabbix
Чтобы отправлять значения в несколько кластеров Zabbix:
- Подготовьте массив кластеров Zabbix. Если кластер содержит несколько узлов, значение будет отправлено на первый доступный узел каждого кластера.
- Создайте
Sender, указав ваш массив кластеров Zabbix. - Вызовите метод
send_value()экземпляраSender, используя тот же формат, что и для методаsend_value().
Например, чтобы отправить значение на первый доступный узел в каждом кластере:
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)
Ответ для нескольких значений
По умолчанию Sender возвращает агрегированный результат отправки значений по всем узлам сети или кластерам:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
Если вам нужна более подробная информация, вы можете просмотреть результаты для каждого кластера и каждого блока с помощью атрибута response.details:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
if response.failed == 0:
print(f"Значение успешно отправлено за {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"Обработано {resp.processed} из {resp.total} на {node.address}:{node.port}")
# Обработано 1 из 1 на 127.0.0.1:10051
# Обработано 1 из 1 на zabbix.example.local:10051