From 4e76203e275fc6392756925c08096d490a36979e Mon Sep 17 00:00:00 2001 From: Mahdi Bazrafshan Date: Mon, 27 Jul 2026 14:15:19 +0330 Subject: [PATCH] feat(api): add request logging middleware Why: - Need visibility into API usage and performance - Need to track request method, path, status, and duration - Helps debugging production issues Changes: - Added RequestLoggingMiddleware class - Logs at appropriate level (INFO/WARNING/ERROR) - Non-invasive, no logic changes --- src/main.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/main.py b/src/main.py index 49622d2..60bfc3d 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,10 @@ """FastAPI app factory. Composes all domain routers and middleware.""" import logging +import time +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.requests import Request +from starlette.responses import Response from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware @@ -23,6 +27,34 @@ logging.basicConfig( datefmt="%Y-%m-%d %H:%M:%S", ) +logger = logging.getLogger(__name__) + + +# ── Request Logging Middleware ───────────────────────────────────── + +class RequestLoggingMiddleware(BaseHTTPMiddleware): + """Log request method, path, status code, and duration.""" + + async def dispatch(self, request: Request, call_next) -> Response: + start = time.time() + method = request.method + path = request.url.path + + response = await call_next(request) + + duration = (time.time() - start) * 1000 # ms + status = response.status_code + + # Log at appropriate level + if status >= 500: + logger.error("%s %s -> %d (%.1fms)", method, path, status, duration) + elif status >= 400: + logger.warning("%s %s -> %d (%.1fms)", method, path, status, duration) + else: + logger.info("%s %s -> %d (%.1fms)", method, path, status, duration) + + return response + def create_app() -> FastAPI: """Create and configure the FastAPI application. @@ -48,6 +80,9 @@ def create_app() -> FastAPI: allow_headers=["*"], ) + # Request logging + app.add_middleware(RequestLoggingMiddleware) + # Register exception handlers app.add_exception_handler(ChunkingError, chunking_exception_handler) app.add_exception_handler(BenchmarkError, benchmark_exception_handler)