Wysyłanie danych do serwera lub proxy Zabbix
zabbix_utils umożliwia wysyłanie wartości pozycji do pozycji trapper na serwer lub proxy Zabbix (podobnie jak Zabbix sender).
Możesz wysłać pojedynczą wartość, wiele wartości, a nawet kierować dane do wielu klastrów Zabbix.
Dane mogą być wysyłane w trybie synchronicznym lub asynchronicznym:
- W trybie synchronicznym skrypt Python wysyła wartości i czeka na odpowiedź przed kontynuowaniem działania; jest to odpowiednie rozwiązanie dla prostych, sekwencyjnych i przewidywalnych operacji.
- W trybie asynchronicznym skrypt wysyła wartości bez oczekiwania na każdą odpowiedź, umożliwiając równoległe wykonywanie innych operacji; jest to bardziej efektywne w przypadku wolnych żądań lub dużych partii danych.
Przykłady na tej stronie koncentrują się na trybie synchronicznym, chociaż tryb asynchroniczny opiera się na podobnych wzorcach. Dodatkowe przykłady są dostępne w repozytorium GitHub zabbix_utils.
Import
Aby używać zabbix_utils do wysyłania wartości pozycji, zaimportuj klasę Sender w swoim skrypcie:
from zabbix_utils import Sender
Aby wysyłać wiele wartości, możesz również zaimportować klasę ItemValue:
from zabbix_utils import Sender, ItemValue
Wyślij pojedynczą wartość
Aby wysłać wartość pozycji:
- Utwórz instancję
Sender, podając adres IP i port swojego serwera lub proxy Zabbix. - Wywołaj metodę
send_value()na instancjiSender, używając następującego formatu:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
Na przykład, aby wysłać 1 do pozycji trapper service.status na hoście Linux server:
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
Używanie niestandardowego adresu IP
Jeśli serwer uruchamiający skrypt ma wiele adresów IP, możesz określić source_ip, którego Sender ma używać podczas wysyłania wartości do serwera Zabbix lub proxy:
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
Używanie timeout
Możesz ustawić timeout odpowiedzi dla Sender, aby kontrolować, jak długo skrypt powinien czekać na odpowiedź z serwera Zabbix lub proxy, zanim zrezygnuje:
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
Używanie pliku konfiguracyjnego agent
Możesz pozwolić, aby zabbix_utils odczytywał parametry Server lub ServerActive z lokalnego pliku konfiguracyjnego Zabbix agent lub agent 2.
W takich przypadkach nie musisz określać parametrów połączenia podczas tworzenia instancji Sender:
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
Jeśli ServerActive zawiera jeden lub więcej klastrów Zabbix z wieloma instancjami serwer, Sender wysyła dane do pierwszego dostępnego serwer w każdym klastrze.
Jeśli ServerActive nie jest ustawiony, używany jest adres z Server z domyślnym portem (10051).
Używanie szyfrowania
Sender nie zawiera wbudowanej obsługi szyfrowania, ale można ją zapewnić, tworząc opakowanie przy użyciu bibliotek zewnętrznych:
def psk_wrapper(sock, tls):
# ...
# Implementacja opakowania TLS PSK dla gniazda
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
Odpowiedź dla pojedynczej wartości
Odpowiedź zwrócona przez serwer Zabbix lub proxy jest przetwarzana przez bibliotekę i zwracana jako obiekt 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
Tryb asynchroniczny
Tryb asynchroniczny pozwala skryptowi Python wysyłać wartości bez oczekiwania na odpowiedź z serwera Zabbix lub proxy. Może to zwiększyć wydajność skryptu, gdy musi on wysłać wiele wartości albo gdy wysłanie niektórych wartości zajmuje dużo czasu.
Podczas korzystania z trybu asynchronicznego występuje kilka istotnych różnic w porównaniu z trybem synchronicznym:
- Zaimportuj moduł
asynciojęzyka Python (najpierw należy zainstalować wymagane zależności). - Zaimportuj
AsyncSenderzamiastSender. - Napisz kod wewnątrz funkcji
async. - Użyj
awaitpodczas wywoływania metodysend_value().
Na przykład, aby wysłać pojedynczą wartość w trybie asynchronicznym:
# 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())
Wysyłanie wielu wartości
Aby wysłać wiele wartości:
- Przygotuj tablicę obiektów
ItemValue, z których każdy używa tego samego formatu co metodasend_value(). - Utwórz instancję
Sender, podając adres IP i port serwera lub proxy Zabbix. - Wywołaj metodę
send()(zamiastsend_value()) na instancjiSender, przekazując tablicę obiektów z wartościami do wysłania.
Na przykład, aby wysłać pięć wartości do różnych hostów:
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)
Używanie niestandardowego rozmiaru fragmentu
Jeśli chcesz wysłać więcej wartości, niż pozycja trapper może przyjąć w pojedynczym żądaniu, możesz podzielić je na fragmenty.
Domyślnie rozmiar fragmentu wynosi 250 wartości.
Możesz go zmienić, ustawiając parametr chunk_size podczas tworzenia instancji Sender.
Na przykład, aby wysłać pięć wartości w trzech fragmentach (2-2-1), ustaw parametr chunk_size na 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)
Wysyłanie wartości do wielu klastrów Zabbix
Aby wysyłać wartości do wielu klastrów Zabbix:
- Przygotuj tablicę klastrów Zabbix. Jeśli klaster ma wiele węzłów, wartość zostanie wysłana do pierwszego dostępnego węzła każdego klastra.
- Utwórz obiekt
Sender, podając tablicę klastrów Zabbix. - Wywołaj metodę
send_value()na instancjiSender, używając tego samego formatu jak w metodziesend_value().
Na przykład, aby wysłać wartość do pierwszego dostępnego węzła w każdym klastrze:
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)
Odpowiedź dla wielu wartości
Domyślnie Sender zwraca zagregowany wynik wysyłania wartości dla wszystkich hostów lub klastrów:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
Jeśli potrzebujesz bardziej szczegółowych informacji, możesz sprawdzić wyniki dla każdego klastra i każdego fragmentu za pomocą atrybutu response.details:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
if response.failed == 0:
print(f"Wartość została wysłana pomyślnie w {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"Przetworzono {resp.processed} z {resp.total} na {node.address}:{node.port}")
# Przetworzono 1 z 1 na 127.0.0.1:10051
# Przetworzono 1 z 1 na zabbix.example.local:10051