fix(traefik): grade routers on their last 15 minutes; the Config tile reads Traefik's reload time (#5355)
The operator: problem cards "can disappear so quickly". Each router was graded on its latest scrape, so a 4xx share near the 1% cutoff crossed it on one scrape and fell back on the next. recent_window reads every router's last 15 minutes in one query, the error shares weighted by traffic; grade_routers uses it on the page and the dashboard widget, and the why says "over the last 15 min". traefik_config_last_reload_success is the Unix time of the last good reload, not a 0/1 flag, so the tile said "Reload failed" on every scrape. traefik_005 stores it as config_last_reload_at, and the tile reads "Config reloaded 3m ago". The router index also carries the 4xx share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -152,21 +152,21 @@ def compute_router_metrics(
|
||||
def compute_global_stats(
|
||||
current: ParsedMetrics,
|
||||
previous: ParsedMetrics | None,
|
||||
) -> dict[str, float | None]:
|
||||
) -> dict[str, float | datetime | None]:
|
||||
"""Extract process-level and config health metrics from a scrape.
|
||||
|
||||
Returns:
|
||||
{
|
||||
"open_conns_total": float | None,
|
||||
"config_reloads_total": float | None,
|
||||
"config_last_reload_success": float | None, # 1.0 = success, 0.0 = failure
|
||||
"config_last_reload_at": datetime | None, # last successful reload
|
||||
"process_memory_bytes": float | None,
|
||||
}
|
||||
"""
|
||||
stats: dict[str, float | None] = {
|
||||
stats: dict[str, float | datetime | None] = {
|
||||
"open_conns_total": None,
|
||||
"config_reloads_total": None,
|
||||
"config_last_reload_success": None,
|
||||
"config_last_reload_at": None,
|
||||
"process_memory_bytes": None,
|
||||
}
|
||||
|
||||
@@ -180,11 +180,15 @@ def compute_global_stats(
|
||||
if reloads:
|
||||
stats["config_reloads_total"] = sum(reloads.values())
|
||||
|
||||
# Last reload success gauge
|
||||
# The moment of the last successful reload, as a Unix timestamp: Traefik
|
||||
# names it "last_reload_success", but it is a time, not a 0/1 flag. Read
|
||||
# as a flag, every scrape said "Reload failed" (#5355).
|
||||
last_success = current.get("traefik_config_last_reload_success", {})
|
||||
if last_success:
|
||||
# Usually a single sample with no labels
|
||||
stats["config_last_reload_success"] = next(iter(last_success.values()))
|
||||
ts = next(iter(last_success.values()))
|
||||
if ts > 0:
|
||||
stats["config_last_reload_at"] = datetime.fromtimestamp(ts, timezone.utc)
|
||||
|
||||
# Process RSS memory
|
||||
mem = current.get("process_resident_memory_bytes", {})
|
||||
|
||||
Reference in New Issue
Block a user