Skip to content

Commit

Permalink
Pass request info as log record extra fields
Browse files Browse the repository at this point in the history
  • Loading branch information
dolfinus committed May 1, 2024
1 parent 0efd383 commit 745a8ac
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 22 deletions.
16 changes: 6 additions & 10 deletions uvicorn/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = f"{method} {full_path} HTTP/{http_version}"
status_code = self.get_status_code(int(recordcopy.status)) # type: ignore[attr-defined]
request_line = "{} {} HTTP/{}".format(
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,
}
Expand Down
20 changes: 16 additions & 4 deletions uvicorn/protocols/http/h11_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,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
Expand Down
32 changes: 24 additions & 8 deletions uvicorn/protocols/http/httptools_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,24 +467,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):
Expand All @@ -503,7 +515,11 @@ async def send(self, message: ASGISendEvent) -> None:
self.keep_alive = False
content.extend([name, b": ", value, b"\r\n"])

if self.chunked_encoding is None and self.scope["method"] != "HEAD" and status_code not in (204, 304):
if (
self.chunked_encoding is None
and self.scope["method"] != "HEAD"
and status not in (204, 304)
):
# Neither content-length nor transfer-encoding specified
self.chunked_encoding = True
content.append(b"transfer-encoding: chunked\r\n")
Expand Down

0 comments on commit 745a8ac

Please sign in to comment.