受检异常必须显式处理并完整记录堆栈、来源和业务上下文,禁用吞异常、空catch及重复日志;按业务影响分层设日志级别,敏感信息须脱敏,MDC绑定traceId等实现链路追踪。

受检异常(Checked Exception)必须被显式处理,日志记录不能只是“捕获后吞掉”,而要确保错误可追溯、上下文可还原。关键在于:记录时带堆栈、标明来源、补充业务参数,且避免敏感信息泄露。
必须记录完整堆栈和异常类型
受检异常如 IOException、SQLException 本身已携带明确语义,但仅记录 ex.getMessage() 会丢失调用链和根本原因。应始终使用日志框架的 exc_info=True(Python)或第三个参数传入异常对象(Java SLF4J/Logback)。
- ✅ 正确写法(Java):
logger.error("文件读取失败", ex); - ❌ 错误写法:
logger.error("文件读取失败: " + ex.getMessage());(丢失堆栈) - ⚠️ 注意:不要用
ex.toString()替代异常对象传递,否则 MDC 上下文可能丢失
绑定业务上下文,而非仅依赖堆栈
堆栈说明“哪里出错”,上下文说明“为什么出错”。对每个受检异常,至少补充1–2个关键业务变量,例如操作ID、用户ID、请求参数、资源路径。
- 使用 MDC(Mapped Diagnostic Context)在入口处注入 traceId、userId 等,确保整条链路日志可关联
- 在 catch 块中显式拼接上下文:
logger.error("订单支付回调失败[orderNo={}][channel={}]", orderNo, channel, ex); - 避免记录明文密码、身份证号、银行卡号等敏感字段;脱敏后再写入日志
按异常类型分层记录,不混用日志级别
受检异常代表预期内可能失败的外部交互,其严重性取决于业务影响,而非技术分类。同一类异常在不同场景下日志级别应动态调整:
- ERROR:导致主流程中断、数据不一致或用户无法继续(如支付扣款成功但通知失败)
- WARN:可降级处理、有备用路径(如短信发送失败但已切至邮件)
- INFO(极少):主动重试前的预期失败(如首次连接第三方服务超时,即将重试)
- 不使用 DEBUG 记录受检异常——它本就该被正式处理,不是调试线索
避免空 catch 或重复记录
受检异常强制要求处理,但常见反模式是“try-catch-忽略”或“多层重复打印同一异常”。
- 空 catch 块必须禁止:
catch (IOException e) { /* 什么也不做 */ } - 若在 service 层已记录异常,controller 层统一异常处理器不应再记一次 ERROR,可转为 INFO 或跳过
- 推荐做法:只在**首次捕获并决定如何响应**的位置记录日志(通常是业务逻辑最内层或适配层),外层做转换或包装时不重复打点

















