问题描述
我希望Log4j2仅在第一次引发异常时才输出一次完整的Java堆栈跟踪,而不会在异常沿调用链传播时重复该信息。我正在尝试找出哪些自定义Log4j2组件将实现此最小调用链日志记录策略。
我正在基于 PatternLayout 创建自定义布局,想知道是否需要创建自己的 PatternSelector 。在我走这条路之前,我很喜欢那些了解Log4j2(v2.13.3)内部原理的人的建议。
以下伪代码说明了问题。
m0() {try {m1();} catch (Exception e) {log.error("emsg0",e);} }
m1() {try {m2();} catch (Exception e) {log.error("msg1",e); throw new Exception("emsg1",e);} }
m2() {try {m3();} catch (Exception e) {log.error("msg2",e); throw new Exception("emsg2",e);} }
m3() {_log.error("msg3"); throw new Exception("emsg3"); }
以下是实际代码运行时的日志记录:
14:08:47.425 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg3
14:08:47.426 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg2
java.lang.Exception: emsg3
at edu.utexas.tacc.log4j2.Log4j2TestA.m3(Log4j2TestA.java:24)
at edu.utexas.tacc.log4j2.Log4j2TestA.m2(Log4j2TestA.java:22)
at edu.utexas.tacc.log4j2.Log4j2TestA.m1(Log4j2TestA.java:19)
at edu.utexas.tacc.log4j2.Log4j2TestA.m0(Log4j2TestA.java:17)
at edu.utexas.tacc.log4j2.Log4j2TestA.main(Log4j2TestA.java:14)
14:08:47.431 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg1
java.lang.Exception: emsg2
at edu.utexas.tacc.log4j2.Log4j2TestA.m2(Log4j2TestA.java:23)
at edu.utexas.tacc.log4j2.Log4j2TestA.m1(Log4j2TestA.java:19)
at edu.utexas.tacc.log4j2.Log4j2TestA.m0(Log4j2TestA.java:17)
at edu.utexas.tacc.log4j2.Log4j2TestA.main(Log4j2TestA.java:14)
Caused by: java.lang.Exception: emsg3
at edu.utexas.tacc.log4j2.Log4j2TestA.m3(Log4j2TestA.java:24)
at edu.utexas.tacc.log4j2.Log4j2TestA.m2(Log4j2TestA.java:22)
... 3 more
14:08:47.432 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg0
java.lang.Exception: emsg1
at edu.utexas.tacc.log4j2.Log4j2TestA.m1(Log4j2TestA.java:20)
at edu.utexas.tacc.log4j2.Log4j2TestA.m0(Log4j2TestA.java:17)
at edu.utexas.tacc.log4j2.Log4j2TestA.main(Log4j2TestA.java:14)
Caused by: java.lang.Exception: emsg2
at edu.utexas.tacc.log4j2.Log4j2TestA.m2(Log4j2TestA.java:23)
at edu.utexas.tacc.log4j2.Log4j2TestA.m1(Log4j2TestA.java:19)
... 2 more
Caused by: java.lang.Exception: emsg3
at edu.utexas.tacc.log4j2.Log4j2TestA.m3(Log4j2TestA.java:24)
at edu.utexas.tacc.log4j2.Log4j2TestA.m2(Log4j2TestA.java:22)
at edu.utexas.tacc.log4j2.Log4j2TestA.m1(Log4j2TestA.java:19)
... 2 more
这就是我希望看到的:
14:08:47.425 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg3
14:08:47.426 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg2
java.lang.Exception: emsg3
at edu.utexas.tacc.log4j2.Log4j2TestA.m3(Log4j2TestA.java:24)
at edu.utexas.tacc.log4j2.Log4j2TestA.m2(Log4j2TestA.java:22)
at edu.utexas.tacc.log4j2.Log4j2TestA.m1(Log4j2TestA.java:19)
at edu.utexas.tacc.log4j2.Log4j2TestA.m0(Log4j2TestA.java:17)
at edu.utexas.tacc.log4j2.Log4j2TestA.main(Log4j2TestA.java:14)
14:08:47.431 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg1
java.lang.Exception: emsg2
Caused by: java.lang.Exception: emsg3
14:08:47.432 [main] ERROR edu.utexas.tacc.log4j2.Log4j2TestA - msg0
java.lang.Exception: emsg1
Caused by: java.lang.Exception: emsg2
Caused by: java.lang.Exception: emsg3
任何指导表示赞赏, 丰富
解决方法
您将需要创建一个自定义的ThrowablePatternConverter。但是这样做可能不是一个好主意。在应用程序长时间运行(几天,几周或几个月)的现实生活中,您可能不会长时间看到异常,而仅看到由引起的1行可能会让人感到沮丧,因为异常引起的根源通常是最有趣的一个。 此外,缓存异常并尝试进行匹配会使处理异常非常缓慢。
,我认为,解决此问题的最佳方法是采纳njzk2的建议,并记录或引发异常,但不要两者都做。只要代码结构合理,每个异常将被记录一次,Log4j2将以可接受的方式记录完整的异常链。