diff --git a/plugins/docker/routes.py b/plugins/docker/routes.py index c426459..d8c8bae 100644 --- a/plugins/docker/routes.py +++ b/plugins/docker/routes.py @@ -214,7 +214,6 @@ async def widget(): {c.host_id for c in all_containers} | {n.host_id for n in nodes} | {s.host_id for s in services}, ) - capacity = await docker_svc.host_capacity(db, {c.host_id for c in all_containers}) # Swarm tasks collapse into per-service rows (each replica tagged with its # host); non-swarm containers stay grouped by host. @@ -227,42 +226,41 @@ async def widget(): standalone = [c for c in all_containers if not c.service_name] running = [c for c in standalone if c.status == "running"] - display = standalone if show_stopped else running - def trouble(c) -> int: - if (c.status or "") == "restarting" or c.health == "unhealthy": - return 0 - if c.status != "running" and docker_svc.exit_is_failure(c.exit_code, c.oom_killed): - return 1 - return 2 if c.status == "running" else 3 + def troubled(c) -> bool: + return ((c.status or "") == "restarting" or c.health == "unhealthy" + or (c.status != "running" and docker_svc.exit_is_failure(c.exit_code, c.oom_killed))) - # Group for display so multi-host fleets read clearly; single-host stays flat. - groups: dict[str, dict] = {} - for c in sorted(display, key=lambda c: (trouble(c), c.name)): - g = groups.setdefault(c.host_id, { - "host_id": c.host_id, - "host_name": host_name.get(c.host_id, c.host_id), - "containers": [], - }) - g["containers"].append({"c": c, "usage": docker_svc.usage( - c, *capacity.get(c.host_id, (None, None))), - "exit_failed": docker_svc.exit_is_failure(c.exit_code, c.oom_killed)}) - host_groups = sorted(groups.values(), key=lambda g: g["host_name"].lower()) + # The widget-shape order (UI & Design ruling): what is wrong first, then + # the healthy rest one line each, collapsing past HEALTHY_SHOWN. + bad_containers = sorted((c for c in standalone if troubled(c)), key=lambda c: c.name) + healthy = ([{"kind": "service", "s": s} for s in swarm_services if s["state"] == "healthy"] + + [{"kind": "container", "c": c} for c in sorted(running, key=lambda c: c.name) + if not troubled(c)] + + ([{"kind": "stopped", "c": c} for c in sorted(standalone, key=lambda c: c.name) + if c.status != "running" and not troubled(c)] if show_stopped else [])) return await render_template( "docker/widget.html", - host_groups=host_groups, - multi_host=len(host_groups) > 1, - swarm_services=swarm_services, + bad_services=[s for s in swarm_services if s["state"] != "healthy"], + bad_containers=bad_containers, + healthy=healthy[:HEALTHY_SHOWN], healthy_more=max(0, len(healthy) - HEALTHY_SHOWN), + services_total=len(swarm_services), services_healthy=sum(s["state"] == "healthy" for s in swarm_services), running_count=len(running), failures=failures, + host_name=host_name, total_count=len(all_containers) + len(swarm_services), - show_stopped=show_stopped, widget_id=widget_id, ) +# Healthy services and containers listed on the dashboard widget before the +# rest collapse to "+N healthy"; the Docker page lists them all. +HEALTHY_SHOWN = 40 +FAILURES_SHOWN = 5 + + CPU_AVERAGE_MINUTES = 5 diff --git a/plugins/docker/templates/docker/widget.html b/plugins/docker/templates/docker/widget.html index 9d0ce9a..395ca89 100644 --- a/plugins/docker/templates/docker/widget.html +++ b/plugins/docker/templates/docker/widget.html @@ -1,80 +1,80 @@ -{# docker/widget.html — dashboard widget: what Docker is running and what has - failed. Swarm services first, troubled ones at the top with since-times; then - the containers outside any service, by host, problems first. The failed count - links to the Docker page's list of exactly what it counts. #} -{% from "docker/_usage.html" import cpu %} +{# docker/widget.html — the dashboard Docker widget (#5252), in the widget-shape + order: a verdict line; the services and containers in trouble; what failed + in the last 24h, by name; then everything healthy, one line each, packed + into as many columns as the widget is wide. Resource use is the Busiest + Containers widget's, so it isn't repeated here. #} +{% from "_macros.html" import status_dot %} {% if total_count == 0 %} -
No containers reported yet.
+