生产环境禁用e.printstacktrace(),应使用logger.error("msg", e)交由日志框架处理;需确保异常为最后一个参数,配合%ex{3}控制堆栈深度、按业务分级记录,并通过mdc和异步appender优化日志性能。

生产环境中不能用 e.printStackTrace(),它直接写 System.err,不走日志系统,也无法控制格式、级别和落盘行为,容易造成日志混乱或磁盘爆满。真正优雅的做法是让日志框架接管异常,并配合配置做精准控制。
用 logger.error("msg", e) 正确传参
SLF4J + Logback 组合下,必须把异常对象作为最后一个参数传入,框架才能自动识别并展开堆栈:
- ✅ 正确:
logger.error("订单创建失败, orderId={}", orderId, e); - ❌ 错误:
logger.error("订单创建失败: " + e);或logger.error("订单创建失败", e.toString());—— 堆栈完全丢失 - ⚠️ 注意:如果第一个参数为
null,SLF4J 会退化为error(String, Throwable),导致异常被当消息拼接,堆栈消失
限制堆栈深度避免日志膨胀
深层嵌套异常(如 Spring 包装 SQLException → JDBCException → SQLTimeoutException)可能生成几十上百行堆栈。Logback 默认的 %ex 只展开第一层,需显式控制深度:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在
logback.xml的<pattern></pattern>中使用:%ex{3}表示最多展开 3 层(含 root cause) - 对特别长的异常链,可用
%ex{root:3}只取根因及其前两层调用 - 避免无限制的
%ex{full},尤其在高频接口中
按场景分级记录,关键路径才打完整堆栈
不是所有异常都要记全量堆栈。可结合业务重要性做区分:
- 核心流程(如支付、扣款)保留完整堆栈:
logger.error("支付回调处理失败", e); - 非关键路径(如通知推送失败)只记录简要信息:
logger.warn("短信发送失败,手机号={}", phone, e.getCause()); - 对已知可恢复异常(如网络抖动),用
logger.debug("重试第{}次,异常:", retryCount, e);并确保 debug 日志在生产关闭
结构化日志 + 上下文隔离更省空间
堆栈本身不可压缩,但通过上下文增强能减少重复记录:
- 用 MDC 注入 traceId、userId 等字段,单条日志自带定位线索,无需在每条 error 日志里重复拼接业务参数
- 配置异步 Appender(如
AsyncAppender),避免 I/O 阻塞主线程,也降低日志刷盘频率 - 对日志文件启用滚动策略(
TimeBasedRollingPolicy+SizeAndTimeBasedFNATP),按天+大小双维度切割,防止单个文件过大
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










