system-prompts-and-models-o.../dealix/api/middleware.py
2026-05-01 14:03:52 +03:00

50 lines
1.4 KiB
Python

"""FastAPI middleware — request ID, structured logging, timing."""
from __future__ import annotations
import time
import uuid
from collections.abc import Awaitable, Callable
import structlog
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
from core.logging import get_logger
logger = get_logger(__name__)
class RequestIDMiddleware(BaseHTTPMiddleware):
"""Attach a unique request ID to each request and bind it to logs."""
async def dispatch(
self,
request: Request,
call_next: Callable[[Request], Awaitable[Response]],
) -> 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,
method=request.method,
path=request.url.path,
)
start = time.perf_counter()
try:
response = await call_next(request)
except Exception as e:
logger.exception("request_unhandled_error", error=str(e))
raise
duration_ms = (time.perf_counter() - start) * 1000
response.headers["X-Request-ID"] = request_id
logger.info(
"request_completed",
status_code=response.status_code,
duration_ms=round(duration_ms, 2),
)
return response