Source code for lalandre_core.http.middleware

"""Reusable HTTP instrumentation middleware factory for FastAPI services."""

import time
import uuid
from typing import Any, Callable

import structlog
from fastapi import Request, Response
from starlette.middleware.base import RequestResponseEndpoint


[docs] def make_http_instrumentation_middleware( observe_fn: Callable[..., None], ) -> Callable[[Request, RequestResponseEndpoint], Any]: """Build a middleware that records per-request latency and status metrics.""" async def instrument_http_requests( request: Request, call_next: RequestResponseEndpoint, ) -> Response: request_id = request.headers.get("x-request-id") or uuid.uuid4().hex[:12] structlog.contextvars.clear_contextvars() structlog.contextvars.bind_contextvars(request_id=request_id) started_at = time.perf_counter() status_code: int = 500 try: response: Response = await call_next(request) status_code = response.status_code response.headers["x-request-id"] = request_id return response finally: observe_fn( path=request.url.path, method=request.method, status_code=status_code, duration_seconds=time.perf_counter() - started_at, ) return instrument_http_requests