From f866cc1b2f9f73230312a645432a14253b8abe9f Mon Sep 17 00:00:00 2001 From: Martynov Maxim Date: Thu, 16 Nov 2023 12:26:05 +0300 Subject: [PATCH] Pass request info as log record extra fields --- uvicorn/logging.py | 16 +++++--------- uvicorn/protocols/http/h11_impl.py | 20 +++++++++++++---- uvicorn/protocols/http/httptools_impl.py | 28 +++++++++++++++++------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/uvicorn/logging.py b/uvicorn/logging.py index c88d5fe55..f72b32fff 100644 --- a/uvicorn/logging.py +++ b/uvicorn/logging.py @@ -96,20 +96,16 @@ def default(code: int) -> str: def formatMessage(self, record: logging.LogRecord) -> str: recordcopy = copy(record) - ( - client_addr, - method, - full_path, - http_version, - status_code, - ) = recordcopy.args # type: ignore[misc] - status_code = self.get_status_code(int(status_code)) # type: ignore[arg-type] - request_line = "%s %s HTTP/%s" % (method, full_path, http_version) + status_code = self.get_status_code(int(recordcopy.status)) # type: ignore[attr-defined] + request_line = "%s %s HTTP/%s" % ( + recordcopy.method, # type: ignore[attr-defined] + recordcopy.full_path, # type: ignore[attr-defined] + recordcopy.http_version, # type: ignore[attr-defined] + ) if self.use_colors: request_line = click.style(request_line, bold=True) recordcopy.__dict__.update( { - "client_addr": client_addr, "request_line": request_line, "status_code": status_code, } diff --git a/uvicorn/protocols/http/h11_impl.py b/uvicorn/protocols/http/h11_impl.py index 0c0efea0a..5093b9577 100644 --- a/uvicorn/protocols/http/h11_impl.py +++ b/uvicorn/protocols/http/h11_impl.py @@ -475,13 +475,25 @@ async def send(self, message: "ASGISendEvent") -> None: headers = headers + [CLOSE_HEADER] if self.access_log: + client_addr = get_client_addr(self.scope) + method = self.scope["method"] + http_version = self.scope["http_version"] + full_path = get_path_with_query_string(self.scope) + self.access_logger.info( '%s - "%s %s HTTP/%s" %d', - get_client_addr(self.scope), - self.scope["method"], - get_path_with_query_string(self.scope), - self.scope["http_version"], + client_addr, + method, + full_path, + http_version, status, + extra={ + "client_addr": client_addr, + "method": method, + "full_path": full_path, + "http_version": http_version, + "status": status, + }, ) # Write response status line and headers diff --git a/uvicorn/protocols/http/httptools_impl.py b/uvicorn/protocols/http/httptools_impl.py index 8d1a0543c..b38641f8b 100644 --- a/uvicorn/protocols/http/httptools_impl.py +++ b/uvicorn/protocols/http/httptools_impl.py @@ -486,24 +486,36 @@ async def send(self, message: "ASGISendEvent") -> None: self.response_started = True self.waiting_for_100_continue = False - status_code = message["status"] + status = message["status"] headers = self.default_headers + list(message.get("headers", [])) if CLOSE_HEADER in self.scope["headers"] and CLOSE_HEADER not in headers: headers = headers + [CLOSE_HEADER] if self.access_log: + client_addr = get_client_addr(self.scope) + method = self.scope["method"] + http_version = self.scope["http_version"] + full_path = get_path_with_query_string(self.scope) + self.access_logger.info( '%s - "%s %s HTTP/%s" %d', - get_client_addr(self.scope), - self.scope["method"], - get_path_with_query_string(self.scope), - self.scope["http_version"], - status_code, + client_addr, + method, + full_path, + http_version, + status, + extra={ + "client_addr": client_addr, + "method": method, + "full_path": full_path, + "http_version": http_version, + "status": status, + }, ) # Write response status line and headers - content = [STATUS_LINE[status_code]] + content = [STATUS_LINE[status]] for name, value in headers: if HEADER_RE.search(name): @@ -525,7 +537,7 @@ async def send(self, message: "ASGISendEvent") -> None: if ( self.chunked_encoding is None and self.scope["method"] != "HEAD" - and status_code not in (204, 304) + and status not in (204, 304) ): # Neither content-length nor transfer-encoding specified self.chunked_encoding = True