django 日志记录为每个请求全局设置上下文?

Posted

技术标签:

【中文标题】django 日志记录为每个请求全局设置上下文?【英文标题】:django logging set context globally per request? 【发布时间】:2013-04-19 01:45:23 【问题描述】:

假设我想像这样格式化字符串记录:

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

可以使用这种类型的日志记录命令来完成:

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

这会将当前用户 ID 添加到当前请求的日志消息中。

但是额外的字典需要添加到每个日志调用中。

有没有一种好方法可以在 django 的常用函数(例如中间件或视图的索引函数)中添加此上下文,以便设置具有用户 ID 的额外字典,并在当前请求中进一步记录调用同时记录当前用户。

【问题讨论】:

为什么mawimawi的回答不被接受?是因为线程本地使用,还是其他原因? Vinay Sajip,一些声望点会单独消失。这就是它在 *** 上的工作方式。 @VinaySajip ,是的,试图避免使用线程本地和额外的中间件。如果有办法通过扩展日志记录类,那就太好了。 我更新了我的答案以建议一种避免线程本地或中间件的方法。 解开它。 :p 更严重的是:github.com/jedie/django-tools/blob/master/django_tools/… 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

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

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

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

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

以上是关于django 日志记录为每个请求全局设置上下文?的主要内容,如果未能解决你的问题,请参考以下文章

Django 详细请求日志记录

记录对 django-rest-framework 的请求

Django 设置默认日志记录

为 Eclipse 项目设置日志记录配置文件

Flask-2

Django 1.3 日志记录:未记录 500 个错误