feat: traefik scrape task (delta tracking, DB write, record_metric)
This commit is contained in:
@@ -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))
|
||||
Reference in New Issue
Block a user