1- from loguru import logger as loguru_logger
2- from logging import Logger
1+ import time
32from http import HTTPStatus
43from typing import Callable , List , Optional
4+
55from fastapi import FastAPI , Request , Response
6+ from loguru ._logger import Logger
7+ from loguru import logger
68from starlette .middleware .base import BaseHTTPMiddleware
7- import time
8- import sys
9+
10+
11+ def get_request_response_logger ():
12+ fmt : str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <level>{message}</level>"
13+ logger .add (sink = sys .stdout , level = "INFO" , format = fmt )
14+ return logger
915
1016
1117class RequestResponseLoggerMiddleware (BaseHTTPMiddleware ):
12- def __init__ (self , app : FastAPI , * , logger : Optional [Logger ] = None , skip_routes : Optional [List ] = []):
13- self ._skip_routes = skip_routes
14- self .logger = logger
15- if not self .logger :
16- self .logger = loguru_logger
17- fmt = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <level>{message}</level>"
18- self .logger .add (sys .stdout , level = "INFO" , format = fmt )
18+ def __init__ (self , app : FastAPI , * , logger : Optional [Logger ] = None , skip_routes : List [str ] = []):
19+ self ._skip_routes : List [str ] = skip_routes
20+ self .logger : Logger = logger if logger else get_request_response_logger ()
1921 super ().__init__ (app )
2022
2123 async def dispatch (self , request : Request , call_next : Callable ) -> Response :
@@ -31,12 +33,17 @@ def _should_skip_route(self, request: Request) -> bool:
3133
3234 async def _log_it (self , * , request : Request , call_next : Callable ) -> Response :
3335 begin = time .perf_counter ()
34- response = await call_next (request )
36+ try :
37+ response = await call_next (request )
38+ except Exception :
39+ self .logger .exception (f"Request failed at { request .method } { request .url .path } " )
40+ raise
3541 end = time .perf_counter ()
3642 self .logger .info (self ._generate_log (request = request , response = response , response_time = end - begin ))
3743 return response
3844
3945 def _generate_log (self , * , request : Request , response : Response , response_time : float ) -> str :
4046 status = response .status_code
4147 response_time *= 1000
42- return f"{ request .method } { request .url .path } { status } { HTTPStatus (status ).name } { int (response_time )} ms"
48+ http_status_name = HTTPStatus (status ).name # pylint: disable=no-member
49+ return f"{ request .method } { request .url .path } { status } { http_status_name } { int (response_time )} ms"
0 commit comments