在请求处理期间,记录了一堆调试日志。如果出现问题,有时可能会记录错误。想法:当整个请求处理过程中没有错误发生时,我想忽略所有调试,但如果发生错误,我想在日志中看到所有之前和之后的调试。
是否有任何开箱即用的解决方案(在 log4j、logback 或任何其他程序中),或者我必须为我的 Logger 实现某种包装器,它将“缓存”每个线程的调试,直到需要它们为止?
最佳答案
它不是一个内置的解决方案,但它是我的草稿实现,它可以是非常小的并且易于集成。它使用 log4j2,如果您已经在使用 log4j2 或 slf4j,则无需更改客户端代码。
于是对应的测试用例
@Test
public void no_error_so_no_log() throws Exception {
LogEventCollector.clean();
try {
log.debug("hello world");
log.debug("some debug again");
} finally {
LogEventCollector.clean();
}
}
@Test
public void error_so_log_from_the_beginning() throws Exception {
LogEventCollector.clean();
try {
log.debug("hello world");
log.error("some error", new RuntimeException("whatever"));
log.debug("some debug again");
} finally {
LogEventCollector.clean();
}
}
LogEventCollector
将负责对您的 Web 应用程序请求线程进行初始化和清理。它可以放入 servlet Filter
中。
我已经创建了我的自定义 Appender。 appender 的核心如下:
@Override
public void append(LogEvent event) {
if (Level.ERROR.isLessSpecificThan(event.getLevel()))
LogEventCollector.markError();
if (!LogEventCollector.hadError()) {
LogEventCollector.collect(event);
return;
}
for (LogEvent collected : LogEventCollector.events())
push_log_out(collected);
//and the current one
push_log_out(event);
}
方法push_log_event
才是真正的日志记录。它可以是您的自定义实现或委托(delegate)给另一个实现(如 AsyncAppender)。
LogEventCollector
本身:
public class LogEventCollector {
static ThreadLocal<Context> LOG_COLLECTOR = new ThreadLocal<Context>() {
@Override
protected Context initialValue() {
return new Context();
}
};
public static void clean() {
LOG_COLLECTOR.get().clean();
}
static class Context {
boolean had_error = false;
List<LogEvent> events = new ArrayList<LogEvent>();
public void clean() {
had_error = false;
events = new ArrayList<LogEvent>();
}
}
public static void markError() {
LOG_COLLECTOR.get().had_error = true;
}
public static boolean hadError() {
return LOG_COLLECTOR.get().had_error;
}
public static void collect(LogEvent event) {
LOG_COLLECTOR.get().events.add(event);
}
public static List<LogEvent> events() {
List<LogEvent> ret = LOG_COLLECTOR.get().events;
LOG_COLLECTOR.get().events = new ArrayList<LogEvent>();
return ret;
}
}
我觉得根据自己的需求定制一定够了。
关于Java 日志记录 : log everything >debug but only when an error occured,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31454904/