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:
@@ -496,10 +496,21 @@ async def widget():
|
||||
r["cert"]["grade"] = grade
|
||||
if _GRADE_ORDER.get(grade, 2) < _GRADE_ORDER[r["state"]]:
|
||||
left = cert_left(r["cert"]["days"]) # "12 days", "expires today", "expired …"
|
||||
r["by_cert"] = True
|
||||
r["state"], r["why"] = grade, (
|
||||
f"certificate expires in {left}" if left[0].isdigit() else f"certificate {left}")
|
||||
problems, healthy = split_routers(current)
|
||||
healthy.sort(key=lambda r: -(r["latest"].request_rate or 0))
|
||||
# Since when, from the day's history, for problems the traffic shows (a
|
||||
# certificate's says its own date). Only the routers in trouble are read.
|
||||
traffic = [r for r in problems if not r.get("by_cert")]
|
||||
if traffic:
|
||||
since = now - WIDGET_SINCE
|
||||
async with current_app.db_sessionmaker() as db:
|
||||
history = await router_history(db, [r["name"] for r in traffic], since,
|
||||
bucket_seconds(since))
|
||||
for r in traffic:
|
||||
r["since"], r["since_before"] = problem_since(history[r["name"]], thresholds)
|
||||
# With no router domains to go on, certificates can't sit on their
|
||||
# routers: the expiring ones are listed after the routers instead.
|
||||
loose = [] if domains is not None else sorted(
|
||||
@@ -516,6 +527,8 @@ async def widget():
|
||||
|
||||
# Healthy routers on the dashboard widget (the busiest); the page lists all.
|
||||
ROUTERS_SHOWN = 6
|
||||
# How far back the widget looks for when a router's problem began.
|
||||
WIDGET_SINCE = timedelta(hours=24)
|
||||
|
||||
|
||||
@traefik_bp.get("/widget/access_log")
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
<td class="w-name" title="{{ r.name }}">
|
||||
{{- status_dot(r.state) -}}
|
||||
{{ r.name.split('@')[0] }}
|
||||
{%- if r.why and r.state != "ok" %}<span class="w-sub tone-{{ r.state }}">{{ r.why }}</span>{% endif %}
|
||||
{%- if r.why and r.state != "ok" %}<span class="w-sub tone-{{ r.state }}">{{ r.why }}
|
||||
{%- if r.since_before %}, all of the last 24 h{% elif r.since %}, started {{ r.since|ago }}{% endif %}</span>{% endif %}
|
||||
</td>
|
||||
<td>{% if m.request_rate is none %}—{% else %}{{ "%.2f"|format(m.request_rate) }}{% endif %}</td>
|
||||
<td class="w-wide-only">{% if m.response_bytes_rate is none %}—{% else %}{{ m.response_bytes_rate|rate }}{% endif %}</td>
|
||||
|
||||
Reference in New Issue
Block a user