异常日志打印得好不好,直接影响排查效率和系统可维护性。下面从原则、格式、示例、常见坑几个方面系统讲一下。
✅ 让人一眼能定位问题
✅ 能知道谁、在哪、为什么出错
✅ 不丢上下文、不泄露敏感信息
✅ 方便告警、聚合、追踪
[时间] [级别] [线程] [类名] - [业务描述] | context={} | exception=
log.error(
"创建订单失败 | orderId={}, userId={}",
orderId, userId, e
);
✅ 输出效果:
2026-01-21 10:32:11.221 ERROR [http-nio-8080-exec-3] c.x.OrderService - 创建订单失败 | orderId=123, userId=456
java.lang.NullPointerException: orderPrice is null
at com.xxx.OrderService.create(OrderService.java:88)
⚠️ 注意:
log.error("msg", e) ✅
log.error("msg" + e) ❌(会丢堆栈)
catch (OrderNotFoundException e) {
log.warn("订单不存在 | orderId={}", orderId, e);
}
✅ 用 warn
✅ 不需要告警
✅ 但要有上下文
catch (Exception e) {
log.error("系统异常 | orderId={}", orderId, e);
throw e;
}
✅ 用 error
✅ 保留堆栈
✅ 不要吞异常
log.error(
"调用支付服务失败 | orderId={}, payType={}, response={}",
orderId, payType, response, e
);
✅ 打印:
log.error("error: " + e.getMessage());
❌ 堆栈丢失,排查基本靠猜
try {
...
} catch (Exception e) {
log.error("error");
}
❌ 上层无法感知,问题被隐藏
log.error("支付失败");
throw new RuntimeException("系统异常");
❌ 日志和异常对不上
✅ 应该:
throw new RuntimeException("支付失败", e);
log.error("用户信息 | user={}", user);
❌ 密码、身份证、token 不能打
✅ 脱敏:
log.error("用户信息 | userId={}", user.getId());
[traceId=abc123] 创建订单失败
✅ 一个请求一条线
✅ 微服务必备
{
"time": "2026-01-21T10:32:11",
"level": "ERROR",
"service": "order-service",
"traceId": "abc123",
"msg": "创建订单失败",
"orderId": 123,
"exception": "NullPointerException"
}
✅ 适合 ELK / Loki / 日志平台
log.error("订单状态异常 | code={}, orderId={}", "ORDER_1001", orderId, e);
✅ 方便告警 & 定位
好的异常日志 = 能复现 + 能定位 + 不误报 + 不漏信息
如果你愿意,可以告诉我:
我可以直接给你一份可复制的最佳实践模板。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。