Flask 的日志该怎么配?默认的 app.logger 做了什么、为什么在 gunicorn 下 info 看不到、怎么输出结构化日志?这篇用真实的进程逐项验证(请求 ID 见第 182 篇,多进程日志重复见第 185 篇)。
[什么都不配(debug 关)] 输出的级别:['warning', 'error']
handlers on app.logger: ['StreamHandler'] | effective level: WARNING
[2026-10-02 15:51:31,487] WARNING in levels: warning message
[2026-10-02 15:51:31,487] ERROR in levels: error message
[app.debug = True] 输出的级别:['debug', 'info', 'warning', 'error']
handlers on app.logger: ['StreamHandler'] | effective level: DEBUG
[2026-10-02 15:51:31,591] DEBUG in levels: debug message
[2026-10-02 15:51:31,591] INFO in levels: info message
[2026-10-02 15:51:31,591] WARNING in levels: warning message
[2026-10-02 15:51:31,591] ERROR in levels: error message
[app.logger.setLevel(INFO)] 输出的级别:['info', 'warning', 'error']
handlers on app.logger: ['StreamHandler'] | effective level: INFO
[2026-10-02 15:51:31,694] INFO in levels: info message
[2026-10-02 15:51:31,694] WARNING in levels: warning message
[2026-10-02 15:51:31,694] ERROR in levels: error message
[先 logging.basicConfig(level=INFO)] 输出的级别:['info', 'warning', 'error']
handlers on app.logger: [] | effective level: INFO
INFO root-handler: info message
WARNING root-handler: warning message
ERROR root-handler: error message上一篇:优雅关闭;下一篇:请求 ID 链路追踪。
[什么都不配]
[2026-10-02 15:51:31,924] WARNING in gapp: warning from view
[2026-10-02 15:51:31,925] ERROR in app: Exception on /boom [GET]
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
ZeroDivisionError: division by zero
[把 gunicorn.error 的 handler 接到 app.logger]
[2026-10-02 15:51:32 +0800] [73296] [INFO] info from view
[2026-10-02 15:51:32 +0800] [73296] [WARNING] warning from view
[2026-10-02 15:51:32 +0800] [73296] [ERROR] Exception on /boom [GET]
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
ZeroDivisionError: division by zero {"level": "INFO", "msg": "handling hello", "logger": "japp", "method": "GET", "path": "/hello"}
{"level": "ERROR", "msg": "Exception on /boom [GET]", "logger": "japp", "method": "GET", "path": "/boom", "exc": "ZeroDivisionError: division by zero"}[默认] 访问日志行:['127.0.0.1 - - [02/Oct/2026 15:51:33] "GET / HTTP/1.1" 200 -'] [werkzeug 设为 WARNING] 访问日志行:[]