Django 日志配置后生产环境不输出 error 日志为什么?

文章导读
生产环境 Django 日志不记录错误,通常是因为日志配置字典结构有误、文件权限不足或被 WSGI 服务器缓冲拦截。优先检查 settings.py 中的 LOGGING 配置项、日志文件写入权限以及 WSGI 服务器的日志接管情况。
📋 目录
  1. 核心配置检查
  2. 权限与目录处理
  3. WSGI 服务器层排查
  4. 验证方法
  5. 常见陷阱
  6. 参考来源
A A

生产环境 Django 日志不记录错误,通常是因为日志配置字典结构有误、文件权限不足或被 WSGI 服务器缓冲拦截。优先检查 settings.py 中的 LOGGING 配置项、日志文件写入权限以及 WSGI 服务器的日志接管情况。

核心结论:重点排查配置层级与权限问题,确保日志处理器级别不低于错误级别,并启用日志轮转防止磁盘占满。

  • 确认 settings.py 中 LOGGING 字典已定义且 disable_existing_loggers 为 False
  • 确保日志文件路径存在且 Web 服务器用户有写入权限(需手动创建目录)
  • 验证触发真实错误,检查日志文件是否有新增内容且包含时间戳

核心配置检查

Django 内置了 Python 的 logging 模块,生产环境默认不会向控制台输出错误日志。如果配置中 disable_existing_loggers 被设为 True,可能会禁用根日志记录器;如果文件路径不存在或权限不足,FileHandler 会静默失败。

注意:当 DEBUG = False 且配置了 ADMINS 时,Django 默认会将 ERROR 级别消息发送邮件,但仍需显式配置文件处理器以记录本地日志。长期使用单文件处理器可能导致日志文件过大占用磁盘空间,建议配置 formatters 以确保日志包含时间戳和级别信息,并使用 RotatingFileHandler 进行日志轮转。

确保 settings.py 中包含基础文件处理器(含轮转与格式):

Django 日志配置后生产环境不输出 error 日志为什么?
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'file': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/var/log/django/error.log',
            'maxBytes': 1024*1024*5,
            'backupCount': 5,
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'ERROR',
            'propagate': True,
        },
    },
}

权限与目录处理

FileHandler 不会自动创建目录,如果目录不存在,日志写入会失败且通常不报错。登录服务器,先创建目录并设置权限。运行 Django 的进程用户(如 www-data、nginx 或 gunicorn 配置的用户)必须对该文件有写入权限。

快速修正文件归属(假设运行用户为 www-data,请根据实际用户调整):

sudo mkdir -p /var/log/django
sudo touch /var/log/django/error.log
sudo chown -R www-data:www-data /var/log/django/
# 请根据实际运行用户调整,如 www-data, nginx, 或自定义用户

验证文件权限:

ls -l /var/log/django/error.log
ps aux | grep gunicorn

WSGI 服务器层排查

如果使用 Gunicorn 或 Nginx,检查是否配置了访问日志和错误日志路径,避免 WSGI 层缓冲拦截了应用层日志。确保 WSGI 服务器的日志级别没有屏蔽 Django 输出的 ERROR 级别。

Gunicorn 启动示例(指定日志文件):

Django 日志配置后生产环境不输出 error 日志为什么?
gunicorn myproject.wsgi:application \
    `--error-logfile` /var/log/gunicorn/error.log \
    `--access-logfile` /var/log/gunicorn/access.log \
    `--log-level` error

Nginx 配置示例(确保 error_log 级别足够):

server {
    ...
    error_log /var/log/nginx/error.log warn;
    ...
}

验证方法

验收需触发真实错误,检查日志文件是否有新增内容且包含时间戳。可以在视图中故意引发异常:

raise Exception("Test log error")

然后使用 tail 命令观察日志文件:

tail -f /var/log/django/error.log

确认是否有包含时间戳、级别为 ERROR 的新日志行写入。

常见陷阱

  • disable_existing_loggers 设置不当:若设为 True,可能会覆盖 Django 默认日志器,导致内部日志丢失。
  • 路径不存在:FileHandler 不会自动创建目录,如果目录不存在,日志写入会失败且通常不报错。
  • Celery 任务日志隔离:Celery worker 是完全独立的进程,其日志流默认不接入 Django 的 logging 配置体系,需单独配置 Celery 日志处理器。
  • 日志级别不匹配:Handler 的 level 必须低于或等于 Logger 的 level,否则消息会被过滤器拦截。

参考来源

  • Django 官方文档 - 日志模块的配置 (https://docs.djangoproject.com/en/stable/topics/logging/)
  • Python logging.handlers - RotatingFileHandler (https://docs.python.org/3/library/logging.handlers.html)