import logging import time from collections.abc import Awaitable, Callable from starlette.requests import Request from starlette.responses import Response request_logger = logging.getLogger("guidecity.http") def configure_logging(level: int = logging.INFO) -> None: logging.basicConfig( level=level, format="%(asctime)s %(levelname)s %(name)s %(message)s", ) async def log_requests( request: Request, call_next: Callable[[Request], Awaitable[Response]], ) -> Response: """Logs method/path/status/duration for every request handled by the app.""" start = time.perf_counter() try: response = await call_next(request) except Exception: duration_ms = (time.perf_counter() - start) * 1000 request_logger.exception( "%s %s -> unhandled exception (%.1fms)", request.method, request.url.path, duration_ms ) raise duration_ms = (time.perf_counter() - start) * 1000 request_logger.info( "%s %s -> %d (%.1fms)", request.method, request.url.path, response.status_code, duration_ms ) return response