fix(alerts): краш при restart-политике, гистерезис закрытия, редкие правки
CI / ruff · mypy · pytest (pull_request) Successful in 24m47s
CI / ruff · mypy · pytest (pull_request) Successful in 24m47s
Найдено смоуком на живых контейнерах (examples/, #19): - контейнер с restart: on-failure поднимается за секунду — между раундами его не видно в exited; краш теперь распознаётся и по росту RestartCount (сравнение со снапшотами до текущего раунда), повторы — счётчик - алерт закрывается, только когда условия нет resolve_after (60 с): иначе флапающий сервис получал бы «✅ восстановлено» после каждого раунда - правки сообщений со счётчиком — не чаще раза в минуту на алерт Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ Old rows are removed by `app.db.maintenance`.
|
||||
import asyncio
|
||||
import logging
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import select
|
||||
@@ -62,6 +62,7 @@ class Observation:
|
||||
|
||||
details: Details
|
||||
stats: Stats | None # None when not running or stats failed
|
||||
at: datetime | None = None # the round's time; its own snapshot row carries the same `at`
|
||||
|
||||
|
||||
async def _observe(docker: DockerClient, container_id: str) -> Observation | None:
|
||||
@@ -76,7 +77,7 @@ async def _observe(docker: DockerClient, container_id: str) -> Observation | Non
|
||||
stats = await docker.stats(container_id)
|
||||
except DockerError as e:
|
||||
log.warning("stats %s: %s", container_id[:12], e)
|
||||
return Observation(details, stats)
|
||||
return Observation(details, stats) # `at` is set by collect_once
|
||||
|
||||
|
||||
def _row(o: Observation, at: datetime) -> ContainerSnapshot | None:
|
||||
@@ -96,7 +97,7 @@ async def collect_once(docker: DockerClient, store: SnapshotStore, now: datetime
|
||||
"""Inspect every managed container, stats for the running ones; a snapshot row per running container."""
|
||||
at = now or utcnow()
|
||||
found = await asyncio.gather(*(_observe(docker, c.id) for c in await docker.containers()))
|
||||
observations = [o for o in found if o is not None]
|
||||
observations = [replace(o, at=at) for o in found if o is not None]
|
||||
await store.add([row for o in observations if (row := _row(o, at)) is not None])
|
||||
return observations
|
||||
|
||||
|
||||
Reference in New Issue
Block a user