I have this middleware
import logging request_logger = logging.getLogger('api.request.logger') class LoggingMiddleware(object): def process_response(self, request, response): request_logger.log(logging.DEBUG, "GET: {}. POST: {} response code: {}. response " "content: {}".format(request.GET, request.DATA, response.status_code, response.content)) return response
The problem is that request in process_response method has no .POST nor .DATA nor .body. I am using django-rest-framework and my requests has Content-Type: application/json
Note, that if I put logging to process_request method - it has .body and everything I need. However, I need both request and response in a single log entry.
Morgan — HTTP logging middleware for express. It provides the ability to log incoming requests by specifying the formatting of log instance based on different request related information. For example: :method :url :status :response-time ms - :res[content-length]
Here is complete solution I made
""" Api middleware module """ import logging request_logger = logging.getLogger('api.request.logger') class LoggingMiddleware(object): """ Provides full logging of requests and responses """ _initial_http_body = None def process_request(self, request): self._initial_http_body = request.body # this requires because for some reasons there is no way to access request.body in the 'process_response' method. def process_response(self, request, response): """ Adding request and response logging """ if request.path.startswith('/api/') and \ (request.method == "POST" and request.META.get('CONTENT_TYPE') == 'application/json' or request.method == "GET"): request_logger.log(logging.DEBUG, "GET: {}. body: {} response code: {}. " "response " "content: {}" .format(request.GET, self._initial_http_body, response.status_code, response.content), extra={ 'tags': { 'url': request.build_absolute_uri() } }) return response
Note, this
'tags': { 'url': request.build_absolute_uri() }
will allow you to filter by url in sentry.
Andrey's solution will break on concurrent requests. You'd need to store the body somewhere in the request scope and fetch it in the process_response().
class RequestLoggerMiddleware(object): def process_request(self, request): request._body_to_log = request.body def process_response(self, request, response): if not hasattr(request, '_body_to_log'): return response msg = "method=%s path=%s status=%s request.body=%s response.body=%s" args = (request.method, request.path, response.status_code, request._body_to_log, response.content) request_logger.info(msg, *args) return response
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With