You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SLF4J LOGGER如何记录异常栈轨迹?示例测试失败问题求解

解决方案:将SLF4J异常栈轨迹纳入日志检查的方法

问题根因

你当前断言失败的核心原因是:ch.qos.logback.classic.spi.ILoggingEvent 接口的 getFormattedMessage() 方法只会返回日志调用时传入的第一个字符串参数的格式化结果,也就是你示例中的problem here。你传入的异常对象的消息、栈轨迹是独立存储在事件的ThrowableProxy属性中的,不会包含在getFormattedMessage()的返回值里。控制台能看到异常栈是因为控制台默认的Appender配置了打印异常的规则,和日志事件本身的消息字段是分开的。

解决方法

方法1:直接从日志事件中读取异常信息(推荐,无需修改日志配置)

直接读取ILoggingEvent的ThrowableProxy属性做断言,不需要调整日志配置,性能更高:

// 替换原有的断言代码即可
ILoggingEvent errorEvent = listAppender.list.get(1);
// 校验日志事件确实携带了异常
Assertions.assertNotNull(errorEvent.getThrowableProxy());
// 校验异常的消息内容
Assertions.assertTrue(errorEvent.getThrowableProxy().getMessage().contains("Oops"));
// 如果需要校验完整栈轨迹,可调用getStackTraceElementProxyArray()遍历栈帧

方法2:将异常栈拼入格式化后的日志文本

如果你的业务场景需要把异常栈和日志消息合并为完整的文本内容,可以给ListAppender配置包含异常打印的布局,再读取格式化后的完整日志:

public static void main(String[] args) {
    final Logger LOGGER = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("TestException");
    final ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
    // 给ListAppender配置带异常打印的布局
    PatternLayout layout = new PatternLayout();
    // 布局规则里的%ex就是打印异常栈的占位符
    layout.setPattern("%msg%n%ex");
    layout.setContext(LOGGER.getLoggerContext());
    layout.start();
    listAppender.setLayout(layout);
    
    listAppender.start();
    LOGGER.addAppender(listAppender);

    NullPointerException testException =  new NullPointerException("Oops!");
    LOGGER.info("doing stuff");
    LOGGER.error("problem here", testException);

    // 用布局格式化事件,拿到包含异常栈的完整文本
    String fullLog = layout.doLayout(listAppender.list.get(1));
    Assertions.assertTrue(fullLog.contains("Oops"));
}

内容的提问来源于stack exchange,提问作者boardtc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:54:03