[Django]-Django logging set context globally per request?

8👍

There exists a ThreadLocal middleware on https://github.com/jedie/django-tools/blob/master/django_tools/middlewares/ThreadLocal.py which helps you with your issue in making the current request available everywhere.

So what you need to do is add the middleware to your MIDDLEWARE_CLASSES setting, and create a function somewhere like this:

 from django_tools.middlewares import ThreadLocal
 def log_something(levelname, module, funcname, message):
     user = ThreadLocal.get_current_user()
     # do your logging here. "user" is the user object and the user id is in user.pk

2👍

Here’s a possible approach without thread locals or middleware: in your views.py, say, have a dict mapping threads to requests, and a lock to serialise access to it:

from threading import RLock
shared_data_lock = RLock()
request_map = {}

def set_request(request):
    with shared_data_lock:
        request_map[threading.current_thread()] = request

Create the following filter and attach to the handlers which need to output request-specific info:

import logging
class RequestFilter(logging.Filter):
    def filter(self, record):
        with shared_data_lock:
            request = request_map.get(threading.current_thread())
        if request:
            # Set data from the request into the record, e.g.
            record.user_id = request.user.id
        return True

Then, as the first statement of each view, set the request in the map:

def my_view(request, ...):
    set_request(request)
    # do your other view stuff here

With this setup, you should find that your log output contains the relevant request-specific info.

1👍

I think you are looking for a custom log formatter. Taken in conjunction with mawimawi’s answer to include the threadlocal information, your format method could automatically take the information and add it to each logged message.

There are a couple of things to think about: First, threadlocal variables can be dangerous and, worse, leak information, if you deploy in a way that uses a threadpool. Second, you need to be cautious how you write your formatter in case it gets called in a context that doesn’t have the threadlocal information.

Leave a comment