root: fix request_id not being logged for actual asgi requests
This commit is contained in:
parent
7b60bca297
commit
5aabaebd96
|
@ -9,6 +9,7 @@ from django.http import HttpRequest, HttpResponse
|
|||
SESSION_IMPERSONATE_USER = "authentik_impersonate_user"
|
||||
SESSION_IMPERSONATE_ORIGINAL_USER = "authentik_impersonate_original_user"
|
||||
LOCAL = local()
|
||||
RESPONSE_HEADER_ID = "X-authentik-id"
|
||||
|
||||
|
||||
class ImpersonateMiddleware:
|
||||
|
@ -43,7 +44,7 @@ class RequestIDMiddleware:
|
|||
setattr(request, "request_id", request_id)
|
||||
LOCAL.authentik = {"request_id": request_id}
|
||||
response = self.get_response(request)
|
||||
response["X-authentik-id"] = request.request_id
|
||||
response[RESPONSE_HEADER_ID] = request.request_id
|
||||
del LOCAL.authentik["request_id"]
|
||||
return response
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ from django.core.asgi import get_asgi_application
|
|||
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.middleware import RESPONSE_HEADER_ID
|
||||
|
||||
# DJANGO_SETTINGS_MODULE is set in gunicorn.conf.py
|
||||
|
||||
defuse_stdlib()
|
||||
|
@ -67,6 +69,7 @@ class ASGILogger:
|
|||
status_code: int
|
||||
start: float
|
||||
content_length: int
|
||||
request_id: str
|
||||
|
||||
def __init__(self, app: ASGIApp):
|
||||
self.app = app
|
||||
|
@ -75,23 +78,29 @@ class ASGILogger:
|
|||
self.scope = scope
|
||||
self.content_length = 0
|
||||
self.headers = dict(scope.get("headers", []))
|
||||
self.request_id = ""
|
||||
|
||||
async def send_hooked(message: Message) -> None:
|
||||
"""Hooked send method, which records status code and content-length, and for the final
|
||||
requests logs it"""
|
||||
headers = dict(message.get("headers", []))
|
||||
|
||||
if "status" in message:
|
||||
self.status_code = message["status"]
|
||||
|
||||
if b"Content-Length" in headers:
|
||||
self.content_length += int(headers.get(b"Content-Length", b"0"))
|
||||
|
||||
if message["type"] == "http.response.start":
|
||||
response_headers = dict(message["headers"])
|
||||
self.request_id = response_headers.get(
|
||||
RESPONSE_HEADER_ID.encode(), b""
|
||||
).decode()
|
||||
|
||||
if message["type"] == "http.response.body" and not message.get(
|
||||
"more_body", None
|
||||
"more_body", True
|
||||
):
|
||||
runtime = int((time() - self.start) * 1000)
|
||||
self.log(runtime)
|
||||
self.log(runtime, request_id=self.request_id)
|
||||
await send(message)
|
||||
|
||||
self.start = time()
|
||||
|
@ -111,7 +120,7 @@ class ASGILogger:
|
|||
# Check if header has multiple values, and use the first one
|
||||
return client_ip.split(", ")[0]
|
||||
|
||||
def log(self, runtime: float):
|
||||
def log(self, runtime: float, **kwargs):
|
||||
"""Outpot access logs in a structured format"""
|
||||
host = self._get_ip()
|
||||
query_string = ""
|
||||
|
@ -125,6 +134,7 @@ class ASGILogger:
|
|||
status=self.status_code,
|
||||
size=self.content_length / 1000 if self.content_length > 0 else 0,
|
||||
runtime=runtime,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
|
|
Reference in a new issue