Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.
Middleware is a layer which has access to the request object before it is processed and response object after it is
processed.
Instead of logging requests and responses in resp.
views, its better to do at middleware layer which will
log every incoming request.
Why better?
this will log unhandled requests/views
one time job, no need to configure for every request/view
standardised logs for all requests/views
Here, we are using Django’s middleware semantics to construct a middleware which will log all requests and corresponding responses.
Create a middleware
Create middleware folder
Create a middleware folder in your project directory (directory in which settings.py exist).
1
2
mkdir middleware
touch middleware/__init__.py
Create middleware file
Create a RequestLogMiddleware class in /middleware/request_log.py, see below:
"""
Middleware to log `*/api/*` requests and responses.
"""importsocketimporttimeimportjsonimportloggingrequest_logger=logging.getLogger(__name__)classRequestLogMiddleware:"""Request Logging Middleware."""def__init__(self,get_response):self.get_response=get_responsedef__call__(self,request):start_time=time.monotonic()log_data={"remote_address":request.META["REMOTE_ADDR"],"server_hostname":socket.gethostname(),"request_method":request.method,"request_path":request.get_full_path(),}# Only logging "*/api/*" patternsif"/api/"instr(request.get_full_path()):req_body=json.loads(request.body.decode("utf-8"))ifrequest.bodyelse{}log_data["request_body"]=req_body# request passes on to controllerresponse=self.get_response(request)# add runtime to our log_dataifresponseandresponse["content-type"]=="application/json":response_body=json.loads(response.content.decode("utf-8"))log_data["response_body"]=response_bodylog_data["run_time"]=time.time()-start_timerequest_logger.info(msg=log_data)returnresponse# Log unhandled exceptions as welldefprocess_exception(self,request,exception):try:raiseexceptionexceptExceptionase:request_logger.exception("Unhandled Exception: "+str(e))returnexception
Django allows us to write pre and post api-processing logic via __call__ method. Here we are logging only requests with /api/ in its path.
Activate the middleware
Activate the middleware by
adding its path in MIDDLEWARE list in your Django’s application settings.py (below: last value in the
middleware list, if you have other custom middlewares see ordering middleware)):