23

Lets say I want to log like this formatting string :

%(levelname)s %(asctime)s %(module)s %(funcName)s %(message)s %(user_id)

It can be done using this type of logging command :

logging.error('Error fetching information', extra = { 'user_id': 22 } )

This will add the current userid to logging messages for current request.

But the extra dict needs to be added to every logging call.

Is there a good way to add this context in a common function in django (eg Middleware, or index function of a view ), so that the extra dictionary with user id is set, and all further logging calls in the current request also log the current user.

4

3 回答 3

8

https://github.com/jedie/django-tools/blob/master/django_tools/middlewares/ThreadLocal.py上有一个 ThreadLocal 中间件,它可以帮助您解决问题,使当前请求随处可用。

所以你需要做的是将中间件添加到你的 MIDDLEWARE_CLASSES 设置中,并在这样的地方创建一个函数:

 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
于 2013-04-25T09:01:07.347 回答
2

这是一种没有线程本地或中间件的可能方法:views.py例如,在您的 dict 中有一个将线程映射到请求的方法,以及一个用于序列化访问它的锁:

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

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

创建以下过滤器并附加到需要输出特定于请求的信息的处理程序:

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

然后,作为每个视图的第一条语句,在地图中设置请求:

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

通过此设置,您应该会发现您的日志输出包含相关的特定于请求的信息。

于 2013-05-22T00:05:49.580 回答
1

我认为您正在寻找自定义日志格式化程序。结合 mawimawi 的回答以包含线程本地信息,您的格式方法可以自动获取信息并将其添加到每个记录的消息中。

有几件事需要考虑:首先,如果您以使用线程池的方式部署,线程局部变量可能很危险,更糟糕的是,还会泄漏信息。其次,您需要谨慎编写格式化程序,以防它在没有线程本地信息的上下文中被调用。

于 2013-05-27T01:15:36.203 回答