UDHOV's picture
Sync from GitHub via hub-sync
bef3cc6 verified
Raw
History Blame Contribute Delete
2.17 kB
"""
Prometheus metrics middleware for production monitoring.
Exposes request counts, latency histograms, and RAGAS score gauges
at the GET /metrics endpoint.
"""
from __future__ import annotations
import time
from collections.abc import Awaitable, Callable
from prometheus_client import CONTENT_TYPE_LATEST, Counter, Gauge, Histogram, generate_latest
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
requests_total = Counter(
"rag_requests_total",
"Total HTTP requests by endpoint and status",
["endpoint", "status"],
)
latency_histogram = Histogram(
"rag_latency_seconds",
"Request latency in seconds by endpoint",
["endpoint"],
buckets=(0.1, 0.5, 1.0, 5.0, 30.0, 60.0, 120.0, 180.0),
)
ragas_gauge = Gauge(
"rag_ragas_score",
"Per-query RAGAS evaluation score by metric name",
["metric_name"],
)
def update_ragas_metrics(scores: dict[str, float] | None) -> None:
"""Update Prometheus gauges with latest RAGAS scores."""
if scores is None:
return
for metric_name, value in scores.items():
ragas_gauge.labels(metric_name=metric_name).set(value)
class MetricsMiddleware(BaseHTTPMiddleware):
"""Middleware that records request count and latency."""
async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response:
endpoint = request.url.path
start = time.time()
try:
response = await call_next(request)
status = str(response.status_code)
return response
except Exception:
status = "500"
raise
finally:
elapsed = time.time() - start
requests_total.labels(endpoint=endpoint, status=status).inc()
latency_histogram.labels(endpoint=endpoint).observe(elapsed)
async def metrics_endpoint(request: Request) -> Response:
"""Return Prometheus-formatted metrics."""
return Response(
content=generate_latest(),
media_type=CONTENT_TYPE_LATEST,
headers={"Cache-Control": "no-cache"},
)