You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为django.server日志追加用户ID等请求元数据?

解决Django.server日志添加用户ID的问题

问题根源

django.server的日志由Django内置WSGI服务器(如runserver使用的WSGIRequestHandler)生成,这类日志的record对象仅包含socket层面信息,不携带Django的HttpRequest对象,因此你自定义的UserIdFilter无法通过record.request获取用户ID。

可行方案

方案一:自定义WSGIRequestHandler,注入用户ID到日志

通过替换runserver的请求处理器,在日志记录时主动获取用户ID并拼接格式:

  1. 创建自定义处理器类
# 项目/utils.py(或其他合适路径)
from django.core.servers.basehttp import WSGIRequestHandler
from django.contrib.auth.models import AnonymousUser

class CustomRequestHandler(WSGIRequestHandler):
    def log_message(self, format, *args):
        # 从WSGI环境中提取Django请求对象
        request = self.request.environ.get('django.request')
        user_id = "unknown"
        
        if request:
            if isinstance(request.user, AnonymousUser):
                user_id = "anon"
            else:
                user_id = request.user.id or "anon"
        
        # 拼接原日志格式与用户ID
        new_format = f"{format} user-id:{user_id}"
        super().log_message(new_format, *args)
  1. 修改manage.py指定自定义处理器
# manage.py
import os
import sys
from django.core.management.commands.runserver import Command as RunserverCommand
from myproject.utils import CustomRequestHandler  # 替换为你的实际路径

RunserverCommand.default_request_handler = CustomRequestHandler

def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)

if __name__ == '__main__':
    main()
  1. 简化日志配置(无需额外过滤器)
# settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.server': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

方案二:通过中间件自定义请求日志(替代django.server)

如果不需要严格依赖django.server的日志来源,用中间件实现更灵活的日志记录,直接获取HttpRequest对象:

  1. 创建日志中间件
# middleware.py
import logging
from datetime import datetime

request_logger = logging.getLogger('custom.request')

class RequestLogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        
        # 获取用户ID
        user_id = request.user.id if request.user.is_authenticated else "anon"
        
        # 构造匹配原django.server格式的日志内容
        asctime = datetime.now().strftime('%d/%b/%Y %H:%M:%S')
        log_msg = f'[{asctime}] "{request.method} {request.path} {request.META["SERVER_PROTOCOL"]}" {response.status_code} {response.content_length or 0} user-id:{user_id}'
        request_logger.info(log_msg)
        
        return response
  1. 注册中间件
# settings.py
MIDDLEWARE = [
    # 建议放在靠前位置,确保所有请求都被记录
    'myproject.middleware.RequestLogMiddleware',  # 替换为实际路径
    # ... 其他中间件
]
  1. 配置自定义日志记录器
# settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
        'null': {
            'class': 'logging.NullHandler',
        },
    },
    'loggers': {
        'custom.request': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        },
        # 关闭django.server日志避免重复输出
        'django.server': {
            'handlers': ['null'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

方案对比

  • 方案一:严格保留django.server日志来源,适合需要维持原有日志体系的场景,但仅对runserver生效(生产环境使用Gunicorn/uWSGI需单独调整)。
  • 方案二:通用性更强,生产环境可直接使用,日志格式完全可控,但需要替换原django.server的日志输出。

内容的提问来源于stack exchange,提问作者sajith.vim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 23:07:37