生产环境 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 中包含基础文件处理器(含轮转与格式):
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 gunicornWSGI 服务器层排查
如果使用 Gunicorn 或 Nginx,检查是否配置了访问日志和错误日志路径,避免 WSGI 层缓冲拦截了应用层日志。确保 WSGI 服务器的日志级别没有屏蔽 Django 输出的 ERROR 级别。
Gunicorn 启动示例(指定日志文件):
gunicorn myproject.wsgi:application \
`--error-logfile` /var/log/gunicorn/error.log \
`--access-logfile` /var/log/gunicorn/access.log \
`--log-level` errorNginx 配置示例(确保 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)