把 DEBUG 关掉之后,出错了去哪里看?这篇用真实的 gunicorn 对比有没有 LOGGING 配置时日志里到底有什么,再加上请求 ID,最后看错误追踪工具挂钩的信号。
状态码: {'/ok/': 200, '/boom/': 500, '/不存在/': 404, 'Host: evil.test': 400}
日志共 1 行,其中 Traceback 0 段。非 traceback 的行:
即将出错这是一个很容易被忽略的坑:本地开发时 DEBUG=True,console 处理器把错误打到终端;上线 DEBUG=False 之后,Django 默认只通过 mail_admins 发邮件(第 129 篇),没配邮件就什么也看不到。这里的结论只对这个最小项目与 gunicorn 的组合,实际现象还取决于你的 LOGGING。
状态码与响应头里的 X-Request-ID: {'/ok/': (200, '0ed598d4'), '/boom/': (500, '7bdfd75d'), '/不存在/': (404, 'f6801ccc'), 'Host: evil.test': (400, 'd15fc386')}
日志共 35 行,其中 Traceback 3 段。非 traceback 的行:
ERROR django.security.DisallowedHost rid=f3cb25b8 Invalid HTTP_HOST header: '127.0.0.1:9591'. You may need to add '127.0
INFO app rid=0ed598d4 处理 /ok/
WARNING app rid=7bdfd75d 即将出错
ERROR django.request rid=7bdfd75d Internal Server Error: /boom/
WARNING django.request rid=f6801ccc Not Found: /nope/
ERROR django.security.DisallowedHost rid=d15fc386 Invalid HTTP_HOST header: 'evil.test'. You may need to add 'evil.test'
用 X-Request-ID=7bdfd75d 过滤: ['WARNING app rid=7bdfd75d 即将出错', 'ERROR django.request rid=7bdfd75d Internal Server Error: /boom/']建议至少配置 django 与你自己的 logger,输出到 stderr / stdout,让 gunicorn、容器平台去收集。
用 contextvars 保存当前请求的 id,Filter 把它加到日志记录上。上一个区块的日志里每行都有 rid=…,同一个 id 的行属于同一个请求。本文只测了同步的 gunicorn;异步视图下 contextvar 的传播方式没有验证。
触发 got_request_exception 的请求: [('/boom/', 'RuntimeError')] (/nope/ 是 404,不触发;/boom/ 触发)Sentry 之类的 SDK 就是挂在这个信号(以及日志)上的。本文没有接入任何真实的错误追踪服务。