生产环境默认关闭 debug 级别,因其会泄露敏感信息、增大日志体积;仅排查问题时对特定模块临时启用,并限制输出目标与大小;info 表示正常执行,warning 表示潜在异常但未失败;error 是否带 traceback 需按定位需求权衡;应使用 dictconfig 实现模块级独立日志配置。

DEBUG 级别在生产环境该不该开
生产环境默认关掉 DEBUG,不是因为“它太慢”,而是因为它会暴露内部状态、敏感路径、SQL 原始参数、堆栈细节——这些本不该出现在线上日志里。
常见错误现象:logging.getLogger().setLevel(logging.DEBUG) 被误留在配置中,导致日志体积暴增、磁盘打满、甚至泄露数据库连接串或用户 token。
- 只在排查特定问题时,临时对某个模块(如
requests或自定义的auth_service)单独提级:logging.getLogger('auth_service').setLevel(logging.DEBUG) - 确保
DEBUG日志不进远程日志系统(如 ELK、Sentry),只写本地文件且带轮转和大小限制 - 用环境变量控制,而非硬编码:
os.getenv('LOG_LEVEL', 'INFO'),避免打包后改不了
INFO 和 WARNING 的边界怎么划
INFO 是“事情按预期发生了”,WARNING 是“事情没崩,但可能出问题了”——这个分界线最容易模糊,也是线上告警噪音的主要来源。
使用场景举例:
立即学习“Python免费学习笔记(深入)”;
- 用户登录成功 →
INFO;用户连续输错 3 次密码 →WARNING(触发风控但未封禁) - HTTP 请求返回 200 →
INFO;返回 404 且是上游 API 预期外的路径 →WARNING - 缓存命中 →
INFO;缓存未命中但降级读 DB 成功 →INFO;降级也超时 →WARNING
容易踩的坑:WARNING 被当成“轻量 ERROR”,结果监控系统一配 WARNING 告警,每天收 200+ 条,最后没人看。真正该告警的,得是 ERROR 或带特定 tag 的 WARNING(比如加 extra={'alert': True})。
ERROR 日志必须带 traceback 吗
不一定。捕获异常后记录 ERROR,是否调用 exc_info=True,取决于你是否需要定位到具体哪行代码抛出、上下文变量值是什么。
性能影响明显:每次 exc_info=True 都会调用 sys.exc_info() 并格式化完整 traceback,比纯字符串慢 3–5 倍(尤其在高频异常场景下)。
- 框架层全局异常处理器(如 Flask 的
@app.errorhandler(Exception))建议开exc_info=True,这是兜底入口 - 业务逻辑里明确知道异常类型且已处理(如
ValueError解析失败),只需记录关键字段:logger.error('parse failed for user_id=%s, raw=%r', user_id, raw_data) - 用
logger.exception()替代logger.error(..., exc_info=True),语义更清晰,但效果一样
如何让不同服务/模块的日志级别可独立配置
靠根 logger 统一设 level 不够用。微服务里,支付模块要 DEBUG,订单模块只 INFO,必须支持 per-logger 控制。
标准做法是用字典配置 + logging.config.dictConfig(),而不是逐个 setLevel()。
- 配置里写清楚每个 logger 名称和 level:
'loggers': {'payment.core': {'level': 'DEBUG'}, 'order.service': {'level': 'INFO'}} - logger 名称建议跟模块路径一致(如
logging.getLogger(__name__)),方便继承和覆盖 - 注意 propagate:子 logger 默认把日志往上传给父 logger,如果不想让
payment.core的 DEBUG 日志再被根 logger 以 INFO 级别重复输出,设'propagate': False
容易被忽略的一点:Docker 容器里,如果用 basicConfig 初始化过 logger,后续 dictConfig 可能不生效——得先调 logging.getLogger().handlers.clear()。










