Files
checkbot/app/poller/loop.py
T

67 lines
2.3 KiB
Python

import asyncio
import logging
import time
from typing import Awaitable, Callable
from ..checkmk import CheckmkClient
from ..models import Event
from .events import compute_events
from .options import PollOptions, read_poll_options
from .state import StateStore
from .status import PollerStatus
log = logging.getLogger(__name__)
ERROR_MAX = 200
EventSink = Callable[[list[Event]], Awaitable[None]]
class Poller:
def __init__(self, store, state: StateStore, sink: EventSink, status: PollerStatus,
client_factory: Callable[[], CheckmkClient | None] | None = None,
clock: Callable[[], float] = time.time):
self._store = store
self._state = state
self._sink = sink
self.status = status
self._client_factory = client_factory or (lambda: CheckmkClient.from_settings(store))
self._clock = clock
async def run(self) -> None:
while True:
options = read_poll_options(self._store)
self.status.interval = options.interval
try:
await self.run_cycle(options)
except asyncio.CancelledError:
raise
except Exception:
log.exception("Poller-Zyklus fehlgeschlagen")
await asyncio.sleep(options.interval)
async def run_cycle(self, options: PollOptions | None = None) -> None:
options = options or read_poll_options(self._store)
client = self._client_factory()
if client is None:
return
try:
current = await client.problem_services()
except Exception as exc:
self.status.last_error = f"{type(exc).__name__}: {exc}"[:ERROR_MAX]
log.warning("Checkmk-Abfrage fehlgeschlagen: %s", self.status.last_error)
return
finally:
await client.aclose()
now = int(self._clock())
previous = await asyncio.to_thread(self._state.load)
events, rows = compute_events(previous, current, now, options.min_duration)
await asyncio.to_thread(self._state.apply, previous, rows, now)
self.status.last_success = self._clock()
self.status.last_error = None
if events:
try:
await self._sink(events)
except Exception:
log.exception("Verarbeitung der Events fehlgeschlagen")