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:
@@ -0,0 +1,41 @@
|
||||
"""Traefik's last good config reload is a moment; routers are graded on a window
|
||||
|
||||
- traefik_config_last_reload_success is the Unix time of the last successful
|
||||
reload. It was stored as a float and read as 1.0 = success, so the page said
|
||||
"Reload failed" on every scrape (#5355). The column becomes the moment; the
|
||||
old values were timestamps misread, so they go with it.
|
||||
- Routers are now graded on their last 15 minutes (routes.recent_window),
|
||||
which reads the 4xx share too: the covering router index carries it, so
|
||||
that read stays index-only.
|
||||
|
||||
Revision ID: traefik_005_reload_at
|
||||
Revises: traefik_004_covering_indexes
|
||||
Create Date: 2026-10-08
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision: str = "traefik_005_reload_at"
|
||||
down_revision: Union[str, None] = "traefik_004_covering_indexes"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
_CHARTED = ["request_rate", "latency_p95_ms", "error_rate_5xx_pct"]
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.drop_column("traefik_global_stats", "config_last_reload_success")
|
||||
op.add_column("traefik_global_stats",
|
||||
sa.Column("config_last_reload_at", sa.DateTime(timezone=True), nullable=True))
|
||||
op.drop_index("ix_traefik_metrics_router_scraped", "traefik_metrics")
|
||||
op.create_index("ix_traefik_metrics_router_scraped", "traefik_metrics", ["router_name", "scraped_at"],
|
||||
postgresql_include=_CHARTED + ["error_rate_4xx_pct"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("ix_traefik_metrics_router_scraped", "traefik_metrics")
|
||||
op.create_index("ix_traefik_metrics_router_scraped", "traefik_metrics", ["router_name", "scraped_at"],
|
||||
postgresql_include=_CHARTED)
|
||||
op.drop_column("traefik_global_stats", "config_last_reload_at")
|
||||
op.add_column("traefik_global_stats", sa.Column("config_last_reload_success", sa.Float, nullable=True))
|
||||
Reference in New Issue
Block a user