feat(docker): the service and container pages say each fact once (#5310)
Service page: - The header carries the verdict, mode, stack, image and when it was reported. 'In trouble since' shows only while the service is in trouble; once recovered, 'Last failed X ago · its logs'. - The failure card shows only while the service is down, degraded or crash-looping. - The tile strip and the kv card are gone. - One Tasks table: running tasks first with CPU, memory and since when, then Swarm's record. The node is named as its Steward host throughout, and 'N failed in 24h' sits in the caption. Container page: - Same shape: header verdict, a 'Last exit' card only while it is stopped after a failing exit, set-up and I/O in one kv card, and lifecycle as a table. - A swarm task's breadcrumb goes through its service. Both pages: - Resource history is the one fragment (_usage_history.html): now and peak in cores and bytes, drawn with a floor of 1 core / 1 GiB (sparkline_svg floor=), so idle noise draws flat. - The container page's old % sparklines, its private _sparkline and the unused bucket()/container_history() helpers are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -213,38 +213,6 @@ async def host_capacity(db, host_ids) -> dict[str, tuple[int | None, int | None]
|
||||
return out
|
||||
|
||||
|
||||
def bucket(values: list[float], target: int = 40) -> list[float]:
|
||||
"""Bucket-average a series down to ~target points (DB-agnostic, in Python).
|
||||
|
||||
Replaces the old SQL strftime() bucketing, which was SQLite-only and broke
|
||||
on Postgres. Agent cadence is dense, so a multi-hour window is hundreds of
|
||||
rows — averaging into a readable point count keeps the sparkline's shape.
|
||||
"""
|
||||
n = len(values)
|
||||
if n <= target:
|
||||
return values
|
||||
size = (n + target - 1) // target
|
||||
out: list[float] = []
|
||||
for i in range(0, n, size):
|
||||
chunk = values[i:i + size]
|
||||
out.append(sum(chunk) / len(chunk))
|
||||
return out
|
||||
|
||||
|
||||
async def container_history(db, host_id: str, name: str, since) -> tuple[list, list]:
|
||||
"""Return (cpu_series, mem_series) sparkline-ready for one host's container."""
|
||||
rows = (await db.execute(
|
||||
select(DockerMetric.cpu_pct, DockerMetric.mem_pct)
|
||||
.where(DockerMetric.host_id == host_id)
|
||||
.where(DockerMetric.container_name == name)
|
||||
.where(DockerMetric.scraped_at >= since)
|
||||
.order_by(DockerMetric.scraped_at)
|
||||
)).all()
|
||||
cpu = bucket([r.cpu_pct or 0.0 for r in rows])
|
||||
mem = bucket([r.mem_pct or 0.0 for r in rows])
|
||||
return cpu, mem
|
||||
|
||||
|
||||
async def host_map(db, host_ids: set[str]) -> dict[str, Host]:
|
||||
if not host_ids:
|
||||
return {}
|
||||
|
||||
Reference in New Issue
Block a user