如何解决使用自定义rollingFileAppender 和自定义JsonLayout 记录异常堆栈跟踪
我编写了一个带有自己的滚动文件附加程序的自定义记录器。我正在使用其中一个日志消息(例如 info()、debug() 等)记录异常,我除外它会打印异常的整个堆栈跟踪,但它只打印消息。>
public class Logger {
private static ConcurrentHashMap<String,Logger> loggerMap = new ConcurrentHashMap<String,Logger>();
private static ConcurrentHashMap<String,FileAppender> appenderMap = new ConcurrentHashMap<String,FileAppender>();
private static LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
public static org.slf4j.Logger getLoggerWithRollingFileAppender(String appenderName,String loggerName,Level logLevel) {
RollingFileAppender rollingFileAppender;
// Check if the appender is already created.
if (! appenderMap.containsKey(appenderName)) {
LayoutWrappingEncoder jsonEncoder = new LayoutWrappingEncoder();
JsonFormatter jsonFormatter = new JacksonJsonFormatter();
((JacksonJsonFormatter) jsonFormatter).setPrettyPrint(false);
JsonLayout jsonLayout = new JsonLayout();
jsonLayout.setJsonFormatter(jsonFormatter);
jsonLayout.setTimestampFormat("yyyy-MM-dd HH:mm:ss.SSS");
jsonLayout.setContext(loggerContext);
jsonLayout.setAppendLineSeparator(true);
jsonLayout.setIncludeException(true);
jsonLayout.setIncludeMDC(true);
jsonEncoder.setLayout(jsonLayout);
jsonEncoder.setContext(loggerContext);
jsonEncoder.start();
rollingFileAppender = new RollingFileAppender();
rollingFileAppender.setContext(loggerContext);
rollingFileAppender.setName(appenderName);
rollingFileAppender.setEncoder(jsonEncoder);
rollingFileAppender.setAppend(true);
SizeAndTimeBasedRollingPolicy sizeAndTimeBasedRollingPolicy =
new SizeAndTimeBasedRollingPolicy();
sizeAndTimeBasedRollingPolicy.setContext(loggerContext);
sizeAndTimeBasedRollingPolicy.setParent(rollingFileAppender);
sizeAndTimeBasedRollingPolicy.setFileNamePattern(logBaseDir +
File.separator +
appenderName + "-" +
applnName + "-%d{yyyy-MM-dd}.%i.log");
sizeAndTimeBasedRollingPolicy.setMaxHistory(maxLogHistory);
sizeAndTimeBasedRollingPolicy.setMaxFileSize(FileSize.valueOf(maxLogFileSize));
sizeAndTimeBasedRollingPolicy.setTotalSizeCap(FileSize.valueOf(totalLogSizeCap));
sizeAndTimeBasedRollingPolicy.start();
rollingFileAppender.setRollingPolicy(sizeAndTimeBasedRollingPolicy);
rollingFileAppender.start();
appenderMap.put(appenderName,rollingFileAppender);
} else {
rollingFileAppender = (RollingFileAppender) appenderMap.get(appenderName);
}
// Return the logger
org.slf4j.Logger slf4jLogger = getLogger(loggerName);
Logger logger = (ch.qos.logback.classic.Logger) slf4jLogger;
logger.setAdditive(false);
logger.setLevel(logLevel);
logger.addAppender(rollingFileAppender);
return slf4jLogger;
}
}
@Test
void testExceptionWithLoggerWithRollingFileAppender() {
org.slf4j.Logger slf4jLogger = Logger.getLoggerWithRollingFileAppender
("testAppender","com.test7",Level.DEBUG);
try {
FileInputStream fis=new FileInputStream("dummyfile.txt");
} catch (FileNotFoundException e) {
slf4jLogger.info("Exception is",e);
}
Logger logger = (ch.qos.logback.classic.Logger) slf4jLogger;
logger.debug("This is a log message");
try {
FileInputStream fis=new FileInputStream("dummyfile.txt");
} catch (FileNotFoundException e) {
logger.info("Exception is",e);
}
}
但是日志文件不包含异常的完整堆栈跟踪。从调试的角度来看,这没有用。这里可能缺少什么?
{"timestamp":"2021-03-09 18:03:21.443","level":"INFO","thread":"main","logger":"com.test7","message":"Exception is","context":"default","exception":"java.io.FileNotFoundException: linessssss.txt (No such file or directory)\n"}
{"timestamp":"2021-03-09 18:03:21.476","level":"DEBUG","message":"This is a log message","context":"default"}
{"timestamp":"2021-03-09 18:03:21.477","exception":"java.io.FileNotFoundException: linessssss.txt (No such file or directory)\n"}
解决方法
查看 JsonLayout
的源代码,它使用 ThrowableProxyConverter
来控制以 JSON 结尾的内容 - 所以即使您调用 setIncludeException
(如 recommended by responses to other similar questions)它确实将取决于选择了哪个转换器(没有花足够长的时间来了解如何)。您可能希望涉及到 RootCauseFirstThrowableProxyConverter
之类的内容。
我找到了解决方法。添加了一个 CustomThrowableProxyConverter 并通过它处理堆栈跟踪处理。
public class CustomThrowableProxyConverter extends ThrowableHandlingConverter {
public CustomThrowableProxyConverter() {
}
@Override
public String convert(ILoggingEvent event) {
StringBuilder sb = new StringBuilder();
IThrowableProxy itp = event.getThrowableProxy();
if (itp instanceof ThrowableProxy) {
ThrowableProxy tp = (ThrowableProxy)itp;
sb.append(tp.getClassName() + ": " + tp.getMessage());
for (StackTraceElementProxy element : tp.getStackTraceElementProxyArray()) {
sb.append("\t\n");
sb.append(element.getSTEAsString());
}
return sb.toString();
}
return "";
}
}
然后将其设置为 jsonLayout 实例。
JsonLayout jsonLayout = new JsonLayout();
jsonLayout.setThrowableProxyConverter(new CustomThrowableProxyConverter());
jsonEncoder.setLayout(jsonLayout);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。