feat(docker): Docker disk is recorded over time per host, the Disk page shows each host's growth and folds images under their repository, and the overview has one disk line per host (#5304–#5306)
- #5304 "Docker disk totals recorded over time per host, with a growth chart and alertable metrics" - #5305 "Disk page: images grouped by repository, versions folded under it" - #5306 "Docker overview: one disk line per host linking to the Disk page" Each `docker system df` report is now also recorded as metrics, with the host as the resource: disk_total_bytes, its parts, and disk_reclaimable_bytes. An alert rule can watch them. The Disk page starts with the hosts side by side, showing how much each grew over the selected range with a line of it, then gives each host its own section. An image's versions fold under its repository, which is charged only for the layers its versions don't share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -683,3 +683,25 @@ def stale_after_seconds(config) -> int:
|
||||
"""How old a container's last report may be before the page calls it
|
||||
stale: the host agent's own staleness window, since the agent reports it."""
|
||||
return int(((config.get("PLUGINS") or {}).get("host_agent") or {}).get("stale_after_seconds", 180))
|
||||
|
||||
|
||||
async def disk_hosts(db, since: datetime, *, points: int = 60) -> list[dict]:
|
||||
"""Each Docker host's disk as `docker system df` last said, most space
|
||||
first, with its recorded total since `since` (#5304): the points, oldest
|
||||
first, and the growth over them (disk_view.growth; None until there are
|
||||
two). Hosts are named by their Steward host."""
|
||||
from steward.core import metric_series
|
||||
from .disk_view import DISK_PARTS, growth
|
||||
from .models import DockerDiskUsage
|
||||
summaries = list((await db.execute(select(DockerDiskUsage))).scalars())
|
||||
hosts = await host_map(db, {s.host_id for s in summaries})
|
||||
out = []
|
||||
for s in summaries:
|
||||
name = hosts[s.host_id].name if s.host_id in hosts else s.host_id
|
||||
parts = {m: int(getattr(s, f) or 0) for m, f in DISK_PARTS.items()}
|
||||
series = await metric_series.points(db, "docker", name, "disk_total_bytes", since, target=points)
|
||||
out.append({"host_id": s.host_id, "host_name": name, "as_of": s.updated_at,
|
||||
"total": sum(parts.values()), "parts": parts,
|
||||
"reclaimable": int(s.images_reclaimable or 0), "points": series,
|
||||
"growth": growth(series)})
|
||||
return sorted(out, key=lambda h: (-h["total"], h["host_name"].lower()))
|
||||
|
||||
Reference in New Issue
Block a user