id,summary,reporter,owner,description,type,status,component,version,severity,resolution,keywords,cc,stage,has_patch,needs_docs,needs_tests,needs_better_patch,easy,ui_ux 29186,"""django.request"" logging breaks ""logging.handlers.SocketHandler""",direx,Anvesh Mishra,"When setting up logging with Python's default `SocketHandler` then the log messages produced by `django.request` cause an exception in the logging system. This happens everywhere where Django passes an `extra={'request': request}` dictionary to log messages. The reason for this is that the request object cannot be pickled. Steps to reproduce (example): 1. `./manage.py startproject` 1. Add this logging config in settings: {{{ LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'socket_handler': { 'class': 'logging.handlers.SocketHandler', 'host': '127.0.0.1', 'port': 9020, } }, 'loggers': { 'django.request': { 'handlers': ['socket_handler'], 'level': 'INFO', 'propagate': False, }, } } }}} 1. `./manage.py migrate` 1. `./manage.py runserver` 1. `wget http://127.0.0.1:8000/invalid -O /dev//null` The exception is this one: {{{ --- Logging error --- Traceback (most recent call last): File ""/usr/lib/python3.6/logging/handlers.py"", line 633, in emit s = self.makePickle(record) File ""/usr/lib/python3.6/logging/handlers.py"", line 605, in makePickle s = pickle.dumps(d, 1) File ""/usr/lib/python3.6/copyreg.py"", line 65, in _reduce_ex raise TypeError(""can't pickle %s objects"" % base.__name__) TypeError: can't pickle BufferedReader objects Call stack: File ""/usr/lib/python3.6/threading.py"", line 884, in _bootstrap self._bootstrap_inner() File ""/usr/lib/python3.6/threading.py"", line 916, in _bootstrap_inner self.run() File ""/usr/lib/python3.6/threading.py"", line 864, in run self._target(*self._args, **self._kwargs) File ""/usr/lib/python3.6/socketserver.py"", line 639, in process_request_thread self.finish_request(request, client_address) File ""/usr/lib/python3.6/socketserver.py"", line 361, in finish_request self.RequestHandlerClass(request, client_address, self) File ""/usr/lib/python3.6/socketserver.py"", line 696, in __init__ self.handle() File ""/home/direx/virtualenv/django-2.0/lib/python3.6/site-packages/django/core/servers/basehttp.py"", line 154, in handle handler.run(self.server.get_app()) File ""/usr/lib/python3.6/wsgiref/handlers.py"", line 137, in run self.result = application(self.environ, self.start_response) File ""/home/direx/virtualenv/django-2.0/lib/python3.6/site-packages/django/contrib/staticfiles/handlers.py"", line 66, in __call__ return self.application(environ, start_response) File ""/home/direx/virtualenv/django-2.0/lib/python3.6/site-packages/django/core/handlers/wsgi.py"", line 146, in __call__ response = self.get_response(request) File ""/home/direx/virtualenv/django-2.0/lib/python3.6/site-packages/django/core/handlers/base.py"", line 93, in get_response extra={'status_code': 404, 'request': request}, Message: 'Not Found: %s' Arguments: ('/invalid',) }}} Of course these steps are only an example. This bug does not only apply to 404 errors, but also to CSRF verfication errors for instance. In fact all places where the `request` object is passed in as an `extra` logger argument. I see a few possible solutions for this issue: 1. Remove the `request` object from the `extra` log message dict. Right now I am not even sure why this is required. 1. Make the entire `request` object pickleable (probably not an easy task) 1. Pass in a reduced (pickable) version of the request object in the `extra` dict 1. Ship a compatible version of `SocketHandler` BTW: socket logging is explicitly mentioned in the Django docs: > -> The handler is the engine that determines what happens to each message in a logger. It describes a particular logging behavior, such as writing a message to the screen, to a file, **or to a network socket**. This bug also applies to older Django versions.",Bug,new,Core (Other),2.0,Normal,,,Anvesh Mishra,Accepted,0,0,0,0,0,0