Java 使用自定义rollingFileAppender和自定义JsonLayout记录异常stacktrace
我已经编写了一个自定义记录器,它有自己的滚动文件追加器。我使用其中一条日志消息(例如,info()、debug()等)记录异常,我不希望它打印异常的整个堆栈跟踪,但它只打印消息Java 使用自定义rollingFileAppender和自定义JsonLayout记录异常stacktrace,java,log4j,logback,slf4j,slf4java,Java,Log4j,Logback,Slf4j,Slf4java,我已经编写了一个自定义记录器,它有自己的滚动文件追加器。我使用其中一条日志消息(例如,info()、debug()等)记录异常,我不希望它打印异常的整个堆栈跟踪,但它只打印消息 public class Logger { private static ConcurrentHashMap<String, Logger> loggerMap = new ConcurrentHashMap<String, Logger>(); private static C
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);
}
}
查看源代码时,它使用一个
ThrowableProxyConverter
来控制JSON中的最终内容-因此,即使调用setIncludeException
(as),它的功能将取决于选择了哪个转换器(没有花足够长的时间来了解如何使用)。您可能希望包含类似的内容。我找到了解决方法。添加了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);
出于测试目的,我尝试了“HTMLLayout”和“XMLLayout”,它们显示了完整的堆栈跟踪。只有“JsonLayout”有这个问题。它就是这样写的——不管是不是bug,还是设计——代码中没有足够的内容来说明这一点。我在下面发布了一个答案。谢谢你的帮助!有时,仅异常的类/行就足以为您提供问题所在的充分线索(尽管在重试的情况下,根本原因也很有用)。。。在我的一个应用程序(已经使用了10多年)的日志中,完整的堆栈跟踪往往不会提供太多额外的信息。。。
JsonLayout jsonLayout = new JsonLayout();
jsonLayout.setThrowableProxyConverter(new CustomThrowableProxyConverter());
jsonEncoder.setLayout(jsonLayout);