多线程环境下Log4j2 RoutingAppender结合ListAppender的测试问题
问题:Log4j2 RoutingAppender结合JUnit5扩展获取ListAppender始终为null
原问题跟进:Log4j2 Custom Appender in Maven Surefire: Possible to Reuse Across Threads?
我正在用JUnit5对Spring应用中的Log4j2日志输出做单元测试,为此编写了一个JUnit5扩展,在每个测试执行前创建WriterAppender来验证日志消息。但使用Maven及Surefire插件时,默认的多线程加速测试会导致每个测试的Appender混入其他并行测试的日志输出,这个问题我已经自行验证过。
有人建议采用基于ThreadContext中存储的值创建ListAppender的RoutingAppender方案,我正尝试此方案。查阅资料后选择XML配置方式,尝试了以下配置及多种变体:
log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN" name="RoutingForTests"> <Appenders> <Routing name="Routing"> <Routes pattern="$${ctx:appenderName}"> <Route> <List name="$${ctx:appenderName}" /> </Route> </Routes> </Routing> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Routing" /> </Root> </Loggers> </Configuration>
通过JUnit5扩展设置ThreadContext的示例代码如下:
LoggerExtension.java代码
public class LoggerExtension implements BeforeEachCallback, AfterEachCallback { // ... @Override public void beforeEach(ExtensionContext context) { // ... ThreadContext.put("appenderName", context.getUniqueId()); // 我甚至尝试过硬编码该值 // ... } public void verifyMessage(String message) { ListAppender appender = ListAppender.getListAppender(ThreadContext.get("appenderName")); // appender最终为null // ... } }
我还尝试过硬编码ListAppender名称、将查找变量改为单个$、设置Route的key,甚至使用event中的ThreadId,但所有获取ListAppender的尝试均失败。编程实现的方案也因逻辑混乱被迫放弃。
希望能得到帮助,若问题过于简单而被我忽略,在此提前致歉!
参考资料
- Log4j2官方FAQ:如何分离日志文件
- Log4j2官方手册:RoutingAppender章节
- Stack Overflow问题:Log4j2: 如何为每个用户写入独立日志文件?
- Apache邮件列表讨论线程
- Stack Overflow问题:Log4J2结合Routing Appenders与ThreadContext的使用
内容的提问来源于stack exchange,提问作者BtySgtMajor
相关产品推荐
相关产品推荐

