feat(widgets): Routers and Hosts problem rows say since when (#5810)

Routers: a router in trouble reads 'started 2h ago' or 'all of the last
24 h', from problem_since over the day's history, read for the troubled
routers only (a certificate's problem carries its own date). Hosts: a
down host reads 'a monitor is down for 3h'; host_glance keeps the
down_since host_status already had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 10:08:38 -04:00
co-authored by Claude Opus 5.5
parent 423493e2bf
commit c113cadbdd
6 changed files with 47 additions and 5 deletions
+3 -2
View File
@@ -373,7 +373,7 @@ GLANCE_ORDER = {"down": 0, "crit": 1, "stale": 2, "warn": 3, "up": 4, "unknown":
def host_glance(hosts, status: dict, agent: dict, thresholds: dict) -> list[dict]:
"""The Hosts — Overview rows, worst first (#5251).
Each is {host, state, worst, agent}. State is "down" when a linked monitor
Each is {host, state, worst, agent, down_since}. State is "down" when a linked monitor
is down, "stale" when the agent has stopped reporting, else the grade of
the reading furthest past its cutoff ("crit" / "warn": CPU, memory, disk /
or load per core, against Settings → Thresholds; CPU, memory and load
@@ -406,5 +406,6 @@ def host_glance(hosts, status: dict, agent: dict, thresholds: dict) -> list[dict
state = "up"
else:
state = "unknown"
rows.append({"host": h, "state": state, "worst": worst, "agent": a or {}, "grades": grades})
rows.append({"host": h, "state": state, "worst": worst, "agent": a or {}, "grades": grades,
"down_since": st.get("down_since") if state == "down" else None})
return sorted(rows, key=lambda r: (GLANCE_ORDER[r["state"]], r["host"].name.lower()))
+1 -1
View File
@@ -27,7 +27,7 @@
<td class="w-name" title="{{ r.host.name }}">
{{- status_dot(r.state) -}}
{% if session.user_id %}<a href="/hosts/{{ r.host.id }}">{{ r.host.name }}</a>{% else %}{{ r.host.name }}{% endif %}
{%- if r.state == 'down' %}<span class="w-sub tone-crit">a monitor is down</span>
{%- if r.state == 'down' %}<span class="w-sub tone-crit">a monitor is down{% if r.down_since %} for {{ r.down_since|ago|replace(' ago', '') }}{% endif %}</span>
{%- elif r.state == 'stale' %}<span class="w-sub tone-warn">agent last reported {{ a.last_at|ago }}; figures are from then</span>
{%- elif not a %}<span class="w-sub">no agent</span>{% endif %}
</td>