我正在考虑使用org.apache.logging.log4j.CloseableThreadContext将相关的日志记录信息保留在webapp中。一切正常,直到抛出异常(但不一定记录)时遇到一个问题来保留上下文。
我能想到的最好的方法如下。之所以可以使用它,是因为不可变堆栈在创建时就被捕获并卡在了Exception中,但是我不确定它是否是最佳解决方案。
在下面的示例中,log.error消息打印出完整的ThreadContext堆栈,但前提是我将堆栈保存到Exception,然后在调用log.error之前将其设置为:
{Inner1 = value1,Inner2 = value2,Inner3 = value3,InnerLevel = 3,Outer = Hello Word}
在不保存上下文的情况下,消息ThreadContext仅是:
{Outer = Hello Word}
令我惊讶的是,这肯定是一件很普通的事情。有没有人有更好的解决方案,或者Log4j2工具包中有明显的我缺少的东西?
public class LogTest {
@Test
public void testCloseableThreadContext() {
ThreadContext.put("Outer", "Hello Word");
log.warn("Starting...");
try (final CloseableThreadContext.Instance t1 =
CloseableThreadContext.put("Inner1", "value1").put("InnerLevel", "1")) {
log.warn("A logging message from inner");
try (final CloseableThreadContext.Instance t2 =
CloseableThreadContext.put("Inner2", "value2").put("InnerLevel", "2")) {
log.warn("Another logging message");
try (final CloseableThreadContext.Instance t3 =
CloseableThreadContext.put("Inner3", "value3").put("InnerLevel", "1")) {
log.warn("Another logging message");
throw new TCException("A problem", ThreadContext.getImmutableContext());
}
}
}
catch (TCException e) {
try (final CloseableThreadContext.Instance t2 =
CloseableThreadContext.putAll(e.errorContext)) {
log.error("An error occurred further up the stack", e);
}
}
log.warn("finished");
}
class TCException extends Exception {
Map<String, String> errorContext;
public TCException(String msg, Map<String, String> errorContext) {
super(msg);
this.errorContext = errorContext;
}
}
}