Django 上线后的日志方案:三个误区和一份最小配置

本地开发时日志这件事几乎不存在:runserver 一跑,所有输出滚在终端里,出了什么错一眼就能看到。上线那天换成了 Gunicorn + systemd,日志的去向一下变了三处——print 的输出不知去向,文件日志没人管轮转,500 错误用户看得见、你自己看不见。
日志是上线后才真正生效的安全网,但三个误区让这张网大多数时候是破的。这篇把三个误区拆开,最后给一份能直接抄走的最小配置。
print 写的是标准输出。开发时终端就是 stdout,一切可见;上了生产,进程由 systemd 接管,stdout 会被 journald 收走(journalctl -u 服务名 还能查),但用 nohup 挂后台、塞进 crontab 或某些容器场景下,这些输出要么混进别的文件,要么直接丢失。
print 更根本的问题是它分不出级别:没法在出事后按 ERROR 过滤,没法统一关闭,也没法和其他日志汇成一个体系。正确姿势就一句:用 logging.getLogger(__name__) 取日志器,Django 框架自身和整个 Python 生态的日志都汇在这一个体系里,级别、去向、格式统一在 settings 里管。
顺带记两个框架自带的记录器:django.request 把 5XX 响应记为 ERROR、4XX 记为 WARNING——后面告警链路就挂在它身上。
还有一个常被误解的点:Django 本身不记录访问日志。开发时终端里那一行行 [28/Sep/2026 ... 200 OK] 来自 runserver,上了生产这套没了,访问日志得靠 Gunicorn 自己开(--access-logfile / --access-logformat);走 systemd 的话它跟应用日志一样进 journal。访问日志和错误日志的用途不同——前者看流量和行为,后者看故障——混在一个文件里排查时反而碍事,分开更清楚。
Django 确实内置了一条 500 告警链路:默认日志配置里有个叫 mail_admins 的处理器(AdminEmailHandler),带 require_debug_false 过滤——只要 DEBUG=False,框架收到的 ERROR(包括未处理异常产生的 500)就会发邮件给 ADMINS 设置里的人。
但内置的只是链路,不是收件人。默认 ADMINS 是空的,邮件配置也没给,这条链路接好了却无处可发。更麻烦的是它失败得毫无声息,两个经典坑:
最小配置长这样(凭据走环境变量,别写死):
配完故意触发一个 500(临时路由里抛个异常即可),收到带完整 traceback 的邮件才算通。定位上邮件是兜底——它告诉你出事了,排查还得靠落盘日志;404 这类高噪音事件别往邮件里接,一晚上能把邮箱灌爆。
单进程下 RotatingFileHandler、TimedRotatingFileHandler 都没问题。但 Gunicorn 多 worker 是多进程:每个 worker 持有自己的处理器,各自判断该不该切割文件,切换瞬间互相踩踏。Python 的 logging 模块是线程安全的,不是进程安全的。有工程师实测过:多 worker 用 TimedRotatingFileHandler 按时间轮转,3000 条日志最后只剩不到 200 条。
两条正路,按需选:
| 方案 | 做法 | 适用 |
|---|---|---|
| 日志走 stdout,交给 journald | systemd 默认收集服务 stdout,把 journald 配成持久化后用 journalctl 查询 | 单机小项目,改动最小,推荐起点 |
| logrotate + WatchedFileHandler | logrotate 负责切割和重建文件,WatchedFileHandler 发现文件被换后自动重新打开句柄 | 必须落普通文件、要长期归档 |
| concurrent-log-handler | 第三方库,加锁轮转 | 不想引入 logrotate 时的折中 |
走 journald 这条路有个容易忽略的坑:多数发行版默认存储模式是 auto,/var/log/journal 目录不存在时日志只放在内存里(/run/log/journal),重启全部丢失。开机就排查不了上次崩溃的原因,等于白配。开持久化两条命令二选一:
磁盘占用可用 SystemMaxUse 限制上限,默认约为所在文件系统的一成。
日志方案的选型逻辑和小站的其他基础设施一样:先用最简单的(stdout + 持久化 journald)把「出事有人知道」这件事兜住,等真的需要归档和检索了,再上 logrotate 或集中式方案。如果你也在做 Django 上线,欢迎把这篇转给一起协作的人。
#Django #Python #日志 #运维部署 #后端开发 #服务器