from __future__ import annotations import time from typing import Callable from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware from monitoring.metrics import observe_request from services.metrics import get_metrics_service class MetricsMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next: Callable[[Request], Response]) -> Response: start_time = time.time() response = await call_next(request) process_time = time.time() - start_time observe_request( method=request.method, endpoint=request.url.path, status=response.status_code, seconds=process_time, ) # Store in database asynchronously background_tasks = getattr(request.state, "background_tasks", None) if background_tasks: background_tasks.add_task( store_request_metric, method=request.method, endpoint=request.url.path, status_code=response.status_code, duration_seconds=process_time, ) return response async def store_request_metric( method: str, endpoint: str, status_code: int, duration_seconds: float ) -> None: """Store request metric in database.""" try: service = get_metrics_service() service.store_metric( metric_name="http_request", value=duration_seconds, labels={"method": method, "endpoint": endpoint, "status": status_code}, endpoint=endpoint, method=method, status_code=status_code, duration_seconds=duration_seconds, ) except Exception: # Log error but don't fail the request pass