feat(docker): per-container enrichment — health, restarts, exit code, I/O, grouping
First slice of milestone 77 (Docker monitoring depth). Surfaces real per-container
stats beyond basic state, all read-only on the existing push model.
- agent (→1.4.0): collect_docker now inspects each container (health, restart
count, exit code, OOM) and reads net + block I/O from the stats payload; pulls
compose project + swarm service/task/node from container labels. Per-container
inspect+stats calls run over a small bounded ThreadPool so the ~1s-per-stats
blocking doesn't stretch the sample on a busy host.
- schema (docker_003): additive columns on docker_containers — health, exit_code,
oom_killed, compose_project, service_name, task_id, node_id, and BigInteger
net/blk byte counters.
- ingest: persists the enrichment + restart_count (.get keeps older agents working).
- ui: Docker page rows now show health badge, uptime ("up 3d 4h"), restart count,
exit code (+OOM) for stopped containers, and compose/service grouping label.
- tests: agent helpers (grouping, inspect fields, net/IO sum) + collect_docker
assembly incl. inspect; integration asserts enrichment round-trips.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Jg27rgypiW2efULXJDtMC
This commit is contained in:
@@ -73,6 +73,20 @@ async def persist_host_docker(session, host, snapshots) -> None:
|
||||
existing.ports_json = json.dumps(c.get("ports") or [])
|
||||
existing.started_at = _parse_started_at(c.get("started_at"))
|
||||
existing.scraped_at = latest_at
|
||||
# Enrichment (agent ≥ 1.4.0; .get keeps older agents working — fields
|
||||
# stay None/0 when absent from the payload).
|
||||
existing.restart_count = c.get("restart_count", 0) or 0
|
||||
existing.health = c.get("health")
|
||||
existing.exit_code = c.get("exit_code")
|
||||
existing.oom_killed = bool(c.get("oom_killed", False))
|
||||
existing.compose_project = c.get("compose_project")
|
||||
existing.service_name = c.get("service_name")
|
||||
existing.task_id = c.get("task_id")
|
||||
existing.node_id = c.get("node_id")
|
||||
existing.net_rx_bytes = c.get("net_rx_bytes")
|
||||
existing.net_tx_bytes = c.get("net_tx_bytes")
|
||||
existing.blk_read_bytes = c.get("blk_read_bytes")
|
||||
existing.blk_write_bytes = c.get("blk_write_bytes")
|
||||
|
||||
# Alert pipeline — resource is host-scoped so containers of the same name
|
||||
# on different hosts don't collide in the metric/alert namespace.
|
||||
|
||||
Reference in New Issue
Block a user