feat: traefik scrape task (delta tracking, DB write, record_metric)

This commit is contained in:
2026-03-18 18:38:54 -04:00
parent 8ea2b09d05
commit aacfcd420e
+97
View File
@@ -0,0 +1,97 @@
# plugins/traefik/scheduler.py
from __future__ import annotations
import logging
import time
from typing import TYPE_CHECKING
from fablednetmon.core.scheduler import ScheduledTask
if TYPE_CHECKING:
from quart import Quart
logger = logging.getLogger(__name__)
# Module-level state: previous scrape data for delta computation
_prev_metrics: dict = {}
_prev_time: float = 0.0
def make_scrape_task(app: "Quart") -> ScheduledTask:
"""Return a ScheduledTask that scrapes Traefik metrics on the configured interval."""
interval = app.config["PLUGINS"]["traefik"]["scrape_interval_seconds"]
async def scrape() -> None:
await _do_scrape(app)
return ScheduledTask(
name="traefik_scrape",
coro_factory=scrape,
interval_seconds=int(interval),
run_on_startup=True,
)
async def _do_scrape(app: "Quart") -> None:
"""Fetch Traefik metrics, write to DB, and emit plugin_metrics."""
global _prev_metrics, _prev_time
from datetime import datetime, timezone
from plugins.traefik.models import TraefikMetric
from plugins.traefik.scraper import fetch_metrics, compute_router_metrics
from fablednetmon.core.alerts import record_metric
metrics_url: str = app.config["PLUGINS"]["traefik"]["metrics_url"]
try:
current = await fetch_metrics(metrics_url)
except Exception:
logger.exception("Traefik scrape failed (url=%s)", metrics_url)
return
now = time.monotonic()
elapsed = now - _prev_time if _prev_time else 60.0
router_metrics = compute_router_metrics(current, _prev_metrics or None, elapsed)
_prev_metrics = current
_prev_time = now
if not router_metrics:
logger.debug("Traefik scrape: no router metrics found")
return
scraped_at = datetime.now(timezone.utc)
async with app.db_sessionmaker() as session:
async with session.begin():
for router_name, metrics in router_metrics.items():
# Write to traefik_metrics history table
row = TraefikMetric(
router_name=router_name,
scraped_at=scraped_at,
request_rate=metrics["request_rate"],
error_rate_4xx_pct=metrics["error_rate_4xx_pct"],
error_rate_5xx_pct=metrics["error_rate_5xx_pct"],
latency_p50_ms=metrics["latency_p50_ms"],
latency_p95_ms=metrics["latency_p95_ms"],
latency_p99_ms=metrics["latency_p99_ms"],
)
session.add(row)
# Emit plugin_metrics for alert rules
for metric_name, value in [
("request_rate", metrics["request_rate"]),
("error_rate_4xx_pct", metrics["error_rate_4xx_pct"]),
("error_rate_5xx_pct", metrics["error_rate_5xx_pct"]),
("latency_p50_ms", metrics["latency_p50_ms"]),
("latency_p95_ms", metrics["latency_p95_ms"]),
("latency_p99_ms", metrics["latency_p99_ms"]),
]:
await record_metric(
session=session,
source_module="traefik",
resource_name=router_name,
metric_name=metric_name,
value=value,
)
logger.debug("Traefik scrape: wrote metrics for %d router(s)", len(router_metrics))