| from __future__ import annotations | |
| import logging | |
| import time | |
| import uuid | |
| from collections.abc import Awaitable, Callable | |
| from fastapi import Request, Response | |
| logger = logging.getLogger("nexus.request") | |
| async def request_context_middleware( | |
| request: Request, | |
| call_next: Callable[[Request], Awaitable[Response]], | |
| ) -> Response: | |
| request_id = request.headers.get("x-request-id") or str(uuid.uuid4()) | |
| started = time.perf_counter() | |
| response: Response | None = None | |
| try: | |
| response = await call_next(request) | |
| return response | |
| finally: | |
| duration_ms = int((time.perf_counter() - started) * 1000) | |
| status_code = response.status_code if response else 500 | |
| if response: | |
| response.headers["x-request-id"] = request_id | |
| logger.info( | |
| "request completed", | |
| extra={ | |
| "request_id": request_id, | |
| "method": request.method, | |
| "path": request.url.path, | |
| "status_code": status_code, | |
| "duration_ms": duration_ms, | |
| }, | |
| ) | |