refactor(docker): container CPU and memory live in the one metric store (#5752)
CI / lint (push) Successful in 3s
CI / integration (push) Failing after 1m18s
CI / unit (push) Successful in 1m24s
CI / publish (push) Skipped

#5752 "Container CPU and memory history lives in the one metric store;
docker_metrics and docker_metrics_hourly are retired". Container cpu_pct and
mem_pct already went to plugin_metrics for alerting; now mem_usage_bytes does
too, and every snapshot in an ingest (backlog included) is recorded at its
own time. The container history chart, Busiest Containers, a service's
history and the MCP container tools read plugin_metrics under resource
"<host>/<container>", rolled up and pruned by the shared metric retention.

docker_012_drop_metrics drops both tables. Their history is not copied
(lesson #5221 "A data migration's cost is set by the live table"); the
store already holds 7 days of container CPU and memory %. Docker retention
now prunes only lifecycle events, and Settings -> Thresholds has one
"Metric retention" card for every source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 14:39:56 -04:00
co-authored by Claude Opus 5.5
parent b889584906
commit 5a0e150789
19 changed files with 242 additions and 430 deletions
+9 -5
View File
@@ -132,12 +132,16 @@ def test_docker_and_agent_tools_over_seeded_rows(app):
"VALUES (:id, :h, :n, :ts, :st, :line)"),
{"id": str(uuid.uuid4()), "h": hid, "n": web,
"ts": now - timedelta(minutes=5 - i), "st": stream, "line": line})
# Container series live in the one metric store (#5752).
for i, cpu in enumerate((10.0, 30.0, 50.0)):
await s.execute(text(
"INSERT INTO docker_metrics (id, host_id, container_name, scraped_at, "
"cpu_pct, mem_pct, mem_usage_bytes) VALUES (:id, :h, :n, :t, :c, 20.0, 1000)"),
{"id": str(uuid.uuid4()), "h": hid, "n": web,
"t": now - timedelta(minutes=30 - i * 10), "c": cpu})
for metric, value in (("cpu_pct", cpu), ("mem_pct", 20.0),
("mem_usage_bytes", 1000.0)):
await s.execute(text(
"INSERT INTO plugin_metrics (id, source_module, resource_name, "
"metric_name, value, recorded_at) "
"VALUES (:id, 'docker', :r, :m, :v, :t)"),
{"id": str(uuid.uuid4()), "r": f"{host_name}/{web}", "m": metric,
"v": value, "t": now - timedelta(minutes=30 - i * 10)})
await s.execute(text(
"INSERT INTO docker_swarm_services (host_id, service_name, mode, desired, running, "
"placement_json, tasks_json, updated_at) "