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