一、问题描述
因错误使用了logback的error日志实现中,format、可变参的重载方法,相当然的以为throwable异常作为可变参数也会打印出具体堆栈。
-
线上使用logback日志框架
-
调用了logback的format、可变参数的重载方法
public void error(Marker marker, String format, Object... argArray) {
filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null);
}
3.具体的调用代码如下,这样打印的日志,异常堆栈信息是出不来的。
log.error("参数信息{} 描述信息 {} 异常堆栈 {}","参数1","描述1",e);
二、问题定位
-
阅读public void error(String format, Object... argArray);方法的源码
-
会调用到logback的底层代码filterAndLog_0_Or3Plus方法
private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,
final Throwable t) {
final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t);
if (decision == FilterReply.NEUTRAL) {
if (effectiveLevelInt > level.levelInt) {
return;
}
} else if (decision == FilterReply.DENY) {
return;
}
// 这里会构造异步日志事件,和格式化日志信息
buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);
}
3.继续跟进buildLoggingEventAndAppend的实现
private void buildLoggingEventAndAppend(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,
final Throwable t) {
//具体构造日志事件,核心地方,这里代表了一条日志消息,异步日志框架会对该消息进行格式化输出
LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params);
le.setMarker(marker);
callAppenders(le);
}
4.看一下loggingEvent是如何构造的
public LoggingEvent(String fqcn, Logger logger, Level level,