You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Log4j2的Appender递归调用错误?

解决Log4j2中"ERROR Recursive call to appender"的问题

问题场景

你已经完成了从Log4j到Log4j2的迁移,所有配置都按Log4j2标准调整了文件名和语法,但在添加针对pl.package.x或pl.package.y的Logger后,遇到了ERROR Recursive call to appender RootConsole的错误。有意思的是,当把该Logger的additivity设为false时一切正常,设为true就会触发错误。

你添加自定义Logger后的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
 <Appenders>
 <Console name="RootConsole" target="SYSTEM_OUT">
 <PatternLayout pattern="%d{ISO8601} %c{1} [%t] %p - %m%n"/>
 </Console>
 <RollingFile name="IntegrationTestFile" fileName="it_test.log" filePattern="integration_test.log.%i">
 <PatternLayout pattern="%d{ISO8601} %c{1} [%t] %p - %m%n"/>
 <Policies>
 <SizeBasedTriggeringPolicy size="100 KB"/>
 </Policies>
 <DefaultRolloverStrategy max="1"/>
 </RollingFile>
 </Appenders>
 <Loggers>
 <Root level="DEBUG">
 <AppenderRef ref="RootConsole"/>
 <AppenderRef ref="IntegrationTestFile"/>
 </Root>
 <!-- 新增的引发错误的Logger -->
 <Logger name="pl.package.x" level="DEBUG" additivity="true">
 <AppenderRef ref="RootConsole"/>
 <AppenderRef ref="IntegrationTestFile"/>
 </Logger>
 </Loggers>
</Configuration>

递归调用错误的原因

咱们来拆解Log4j2的日志事件流转逻辑:

  • 当additivity="true"(这是默认值)时,子Logger处理完一条日志事件后,会把同一个事件传递给它的父Logger链,最终会传到Root Logger。
  • 你的自定义pl.package.x Logger和Root Logger,都配置了向完全相同的两个Appender输出:RootConsole和IntegrationTestFile。

这就导致了一个重复处理的场景:日志事件先被自定义Logger的两个Appender处理一遍,然后通过additivity机制传递给Root Logger,Root Logger又会把同一个事件再次发给这两个Appender。Log4j2内部有检测机制,防止同一个日志事件被同一个Appender重复处理,这种重复触发的情况会被判定为递归调用,于是就抛出了错误。

修复方案

根据你的需求,这里有两种简单有效的修复方式:

方案1:保持additivity="false"(推荐)

既然你的自定义Logger已经把事件输出到目标Appender了,完全没必要让Root Logger再重复输出一次。设置additivity="false"可以切断事件向父Logger的传递,既解决了递归错误,还能避免日志重复打印:

<Logger name="pl.package.x" level="DEBUG" additivity="false">
 <AppenderRef ref="RootConsole"/>
 <AppenderRef ref="IntegrationTestFile"/>
</Logger>

方案2:移除自定义Logger中的Appender引用

如果你确实需要additivity="true"(比如希望Root Logger的其他Appender也能收到这个事件),那自定义Logger就不需要自己绑定Appender,让事件自然传递到Root Logger,由Root统一处理输出即可:

<Logger name="pl.package.x" level="DEBUG" additivity="true">
 <!-- 这里不添加AppenderRef,事件会自动传给Root Logger处理 -->
</Logger>

这样既保留了事件向上传递的能力,又不会让同一个Appender处理重复事件,递归错误自然就不会出现了。


内容的提问来源于stack exchange,提问作者Szymon Gross

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:02:44