from __future__ import annotations import itertools from typing import Any import httpx class ZabbixApiClient: def __init__( self, api_url: str, api_token: str, timeout_seconds: float = 10, verify_tls: bool = True, ) -> None: self.api_url = api_url self.api_token = api_token self._id_counter = itertools.count(1) self.client = httpx.AsyncClient( timeout=timeout_seconds, verify=verify_tls, headers={ "Authorization": f"Bearer {self.api_token}", "Content-Type": "application/json-rpc", }, ) async def close(self) -> None: await self.client.aclose() async def _call(self, method: str, params: dict[str, Any]) -> Any: payload = { "jsonrpc": "2.0", "method": method, "params": params, "id": next(self._id_counter), } response = await self.client.post(self.api_url, json=payload) response.raise_for_status() data = response.json() if "error" in data: error = data["error"] raise RuntimeError( f"Zabbix API error: method={method} " f"code={error.get('code')} message={error.get('message')} " f"data={error.get('data')}" ) return data.get("result") async def get_trigger(self, trigger_id: str) -> dict[str, Any] | None: result = await self._call( "trigger.get", { "output": [ "triggerid", "description", "comments", "opdata", "priority", "state", "status", "value", ], "triggerids": [trigger_id], "selectHosts": ["hostid", "host", "name"], "selectItems": ["itemid", "name", "key_", "lastvalue", "units", "value_type"], "selectTags": "extend", "limit": 1, }, ) return result[0] if result else None async def get_item(self, item_id: str) -> dict[str, Any] | None: result = await self._call( "item.get", { "output": [ "itemid", "name", "key_", "lastvalue", "units", "value_type", "status", ], "itemids": [item_id], "selectHosts": ["hostid", "host", "name"], "selectTags": "extend", "limit": 1, }, ) return result[0] if result else None async def get_event(self, event_id: str) -> dict[str, Any] | None: result = await self._call( "event.get", { "output": [ "eventid", "objectid", "clock", "name", "severity", "value", "acknowledged", ], "eventids": [event_id], "selectHosts": ["hostid", "host", "name"], "selectTags": "extend", "limit": 1, }, ) return result[0] if result else None async def get_host(self, host_id: str) -> dict[str, Any] | None: result = await self._call( "host.get", { "output": ["hostid", "host", "name"], "hostids": [host_id], "selectTags": "extend", "limit": 1, }, ) return result[0] if result else None async def get_history( self, item_id: str, value_type: int, time_from: int, time_till: int, limit: int = 500, ) -> list[dict[str, Any]]: result = await self._call( "history.get", { "output": ["clock", "value"], "history": value_type, "itemids": [item_id], "time_from": time_from, "time_till": time_till, "sortfield": "clock", "sortorder": "ASC", "limit": limit, }, ) return result or []