import logging import uuid from django.utils.deprecation import MiddlewareMixin from .local_storage import set_current_trace_id, get_current_trace_id logger = logging.getLogger(__name__) class LoggingMiddleware(MiddlewareMixin): def process_request(self, request): trace_id = request.headers.get('X-Trace-ID', str(uuid.uuid4())) request.META['X-Trace-ID'] = trace_id set_current_trace_id(trace_id) request_body = "" content_type = request.headers.get("Content-Type", "") if request.method in ('POST', 'PUT', 'PATCH') and not content_type.startswith("multipart/form-data"): request_body = request.body.decode(encoding="utf-8", errors="ignore") logger.info(f"Request: {request.method} {request.path} | Trace ID: {trace_id} | " f"Body: {request_body} | Headers: {request.headers}") def process_response(self, request, response): trace_id = request.META.get('X-Trace-ID', str(uuid.uuid4())) try: response_body = response.content.decode("utf-8") if response.content else "" except Exception as e: logger.error(e) response_body = "" logger.info(f"Response: {request.method} {request.path} | Trace ID: {trace_id} | " f"Status: {response.status_code} | Body: {response_body}") response['X-Trace-ID'] = trace_id return response def process_exception(self, request, exception): trace_id = request.META.get('X-Trace-ID', str(uuid.uuid4())) logger.error(f"Exception: {request.method} {request.path} | Trace ID: {trace_id} | " f"Error: {exception}") class TraceIDLogFilter(logging.Filter): def filter(self, record): trace_id = get_current_trace_id() record.trace_id = trace_id return True