import time from collections.abc import Callable from typing import Any from fastapi import Request, Response from prometheus_client import Counter, Gauge, Histogram REQUEST_COUNT = Counter( "pip_http_requests_total", "Total HTTP requests", ["method", "endpoint", "status_code"], ) REQUEST_DURATION = Histogram( "pip_http_request_duration_seconds", "HTTP request duration in seconds", ["method", "endpoint"], buckets=[0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0], ) REQUESTS_IN_PROGRESS = Gauge( "pip_http_requests_in_progress", "HTTP requests currently in progress", ["method", "endpoint"], ) DB_QUERY_DURATION = Histogram( "pip_db_query_duration_seconds", "Database query duration in seconds", ["operation"], buckets=[0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0], ) CONNECTOR_OPERATIONS = Counter( "pip_connector_operations_total", "Total connector operations", ["connector_type", "operation", "status"], ) SYNC_JOBS = Counter( "pip_sync_jobs_total", "Total sync jobs", ["strategy", "status"], ) SYNC_DURATION = Histogram( "pip_sync_duration_seconds", "Sync job duration in seconds", ["strategy"], buckets=[1.0, 5.0, 10.0, 30.0, 60.0, 300.0, 600.0, 1800.0], ) ACTIVE_CONNECTIONS = Gauge( "pip_active_connections", "Active infrastructure connections", ["type"], ) CACHE_OPERATIONS = Counter( "pip_cache_operations_total", "Cache operations", ["operation", "result"], ) RESERVATION_OPERATIONS = Counter( "pip_reservation_operations_total", "Reservation operations", ["operation", "status"], ) async def metrics_middleware(request: Request, call_next: Callable) -> Response: if request.url.path == "/metrics" or request.url.path.startswith("/docs") or request.url.path.startswith("/openapi"): return await call_next(request) method = request.method endpoint = request.url.path REQUESTS_IN_PROGRESS.labels(method=method, endpoint=endpoint).inc() start_time = time.perf_counter() try: response = await call_next(request) status_code = response.status_code except Exception: status_code = 500 raise finally: duration = time.perf_counter() - start_time REQUEST_COUNT.labels(method=method, endpoint=endpoint, status_code=status_code).inc() REQUEST_DURATION.labels(method=method, endpoint=endpoint).observe(duration) REQUESTS_IN_PROGRESS.labels(method=method, endpoint=endpoint).dec() return response