From 72bb40a7c43e52092f01576442bf02e54c3b8823 Mon Sep 17 00:00:00 2001 From: Batkhuu Date: Tue, 19 Sep 2023 15:11:05 +0900 Subject: [PATCH] :sparkles: Added flag for enable/disable HTTP debug log in . --- beans_logging/fastapi/_formats.py | 15 +++++++++++++- beans_logging/fastapi/_middlewares.py | 30 ++++++++++++++++++++------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/beans_logging/fastapi/_formats.py b/beans_logging/fastapi/_formats.py index a9c842e..aa15581 100644 --- a/beans_logging/fastapi/_formats.py +++ b/beans_logging/fastapi/_formats.py @@ -20,7 +20,20 @@ def http_file_format(record: dict) -> str: _http_info = record["extra"]["http_info"] if "datetime" not in _http_info: _http_info["datetime"] = record["time"].isoformat() - record["extra"]["http_info"] = _http_info + + if "content_length" not in _http_info: + _http_info["content_length"] = 0 + + if "h_referer" not in _http_info: + _http_info["h_referer"] = "-" + + if "h_user_agent" not in _http_info: + _http_info["h_user_agent"] = "-" + + if "response_time" not in _http_info: + _http_info["response_time"] = 0 + + record["extra"]["http_info"] = _http_info _msg = _MSG_FORMAT.format(**_http_info) record["http_message"] = _msg diff --git a/beans_logging/fastapi/_middlewares.py b/beans_logging/fastapi/_middlewares.py index 1a01729..fb525a4 100644 --- a/beans_logging/fastapi/_middlewares.py +++ b/beans_logging/fastapi/_middlewares.py @@ -25,6 +25,7 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware): has_cf_headers (bool): If True, use cloudflare headers to get http request info. Defaults to False. debug_format (str ): Http access log debug message format. Defaults to `HttpAccessLogMiddleware._DEBUG_FORMAT`. msg_format (str ): Http access log message format. Defaults to `HttpAccessLogMiddleware._MSG_FORMAT`. + use_debug_log (bool): If True, use debug log to log http access log. Defaults to True. """ _DEBUG_FORMAT = '[{request_id}] {client_host} {user_id} "{method} {url_path} HTTP/{http_version}"' @@ -37,12 +38,14 @@ def __init__( has_cf_headers: bool = False, debug_format: str = _DEBUG_FORMAT, msg_format: str = _MSG_FORMAT, + use_debug_log: bool = True, ): super().__init__(app) self.has_proxy_headers = has_proxy_headers self.has_cf_headers = has_cf_headers self.debug_format = debug_format self.msg_format = msg_format + self.use_debug_log = use_debug_log async def dispatch(self, request: Request, call_next) -> Response: _logger = logger.opt(colors=True, record=True) @@ -53,6 +56,8 @@ async def dispatch(self, request: Request, call_next) -> Response: _http_info["request_id"] = request.headers.get("X-Request-ID") elif "X-Correlation-ID" in request.headers: _http_info["request_id"] = request.headers.get("X-Correlation-ID") + + ## Set request_id to request state: request.state.request_id = _http_info["request_id"] _http_info["client_host"] = request.client.host @@ -161,16 +166,25 @@ async def dispatch(self, request: Request, call_next) -> Response: if hasattr(request.state, "user_id"): _http_info["user_id"] = str(request.state.user_id) - _debug_msg = self.debug_format.format(**_http_info) - # _logger.debug(_debug_msg) - await run_in_threadpool( - _logger.debug, - _debug_msg, - ) + ## Debug log: + if self.use_debug_log: + _debug_msg = self.debug_format.format(**_http_info) + # _logger.debug(_debug_msg) + await run_in_threadpool( + _logger.debug, + _debug_msg, + ) + ## Debug log + + ## Set http info to request state: + request.state.http_info = _http_info + ## Process request: _start_time = time.time() response = await call_next(request) _http_info["response_time"] = round((time.time() - _start_time) * 1000, 1) + ## Response processed + if "X-Process-Time" in response.headers: try: _http_info["response_time"] = float( @@ -208,6 +222,7 @@ async def dispatch(self, request: Request, call_next) -> Response: "Can not serialize `http_info` to json string in HttpAccessLogMiddleware!" ) + ## Http access log: _LEVEL = "INFO" _msg_format = self.msg_format if _http_info["status_code"] < 200: @@ -225,7 +240,7 @@ async def dispatch(self, request: Request, call_next) -> Response: elif 500 <= _http_info["status_code"]: _LEVEL = "ERROR" _msg_format = ( - f'{_msg_format.replace("{status_code}", "{status_code}")}' + f'{_msg_format.replace("{status_code}", "{status_code}")}' ) _msg = _msg_format.format(**_http_info) @@ -235,5 +250,6 @@ async def dispatch(self, request: Request, call_next) -> Response: _LEVEL, _msg, ) + ## Http access log return response