import logging
import time
logger = logging.getLogger(__name__)
class RequestLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.start_time = time.time()
response = self.get_response(request)
duration = time.time() - request.start_time
logger.info(
'request_completed',
extra={
'method': request.method,
'path': request.path,
'status': response.status_code,
'duration_ms': round(duration * 1000, 2),
'user': str(request.user) if request.user.is_authenticated else 'anonymous',
}
)
return response
Custom middleware lets me inspect or modify every request and response. I implement both __init__ (called once at startup) and __call__ (for each request). By storing start time in the request, I can measure total processing time including view and template rendering. I log requests to a structured logger with contextual data like user, path, and duration. Middleware order matters—I place this early in MIDDLEWARE to capture total time. For production, I sample or filter to avoid log spam on high-traffic endpoints.