Spring3+Java8应用Log4j1转Log4j2后日志仅输出到控制台问题排查
Log4j 1.x迁移至Log4j2后日志输出异常排查
问题背景
为修复安全漏洞,将基于Java8的Spring3旧应用从Log4j 1.x迁移到Log4j2,应用运行正常但日志输出不符合预期:部分日志仅出现在控制台,未写入指定日志文件。预期控制台仅输出ERROR级日志,日志文件包含INFO、DEBUG级日志。@LOG_DIR@/@LOG_FILE_NAME@等变量已在构建阶段完成替换。
原Log4j 1.x配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <param name="Threshold" value="ERROR" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] [%c] %m%n" /> </layout> </appender> <appender name="APPLOG" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="@LOG_DIR@/@LOG_FILE_NAME@" /> <param name="Append" value="true" /> <param name="MaxFileSize" value="15MB" /> <param name="MaxBackupIndex" value="10" /> <param name="Threshold" value="@THRESHOLD@" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%t] [%c] %m%n" /> </layout> </appender> <appender name="AUDITLOG" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="@AUDIT_LOG_DIR@/@AUDIT_LOG_FILE_NAME@"/> <param name="Append" value="true"/> <param name="Threshold" value="INFO"/> <param name="DatePattern" value="'.'yyyy-MM-dd-HH" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%t] %m%n"/> </layout> </appender> <category name="com.abc" additivity="false"> <priority value="@THRESHOLD@" /> <appender-ref ref="APPLOG" /> </category> <category name="org.httpclient" additivity="false"> <priority value="INFO" /> <appender-ref ref="APPLOG" /> </category> <category name="org.springframework" additivity="false"> <priority value="INFO" /> <appender-ref ref="APPLOG" /> </category> <category name="com.mchange.v2" additivity="false"> <priority value="INFO" /> <appender-ref ref="APPLOG" /> </category> <category name="org.mortbay" additivity="false"> <priority value="INFO" /> <appender-ref ref="APPLOG" /> </category> <category name="org.apache" additivity="false"> <priority value="INFO" /> <appender-ref ref="APPLOG" /> </category> <category name="AUDIT_LOGGER" additivity="false"> <priority value="INFO" /> <appender-ref ref="AUDITLOG"/> </category> <!-- Setup the Root category --> <root> <priority value="@THRESHOLD@" /> <appender-ref ref="APPLOG" /> </root> </log4j:configuration>
转换后的Log4j2配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <!--<Properties> <Property name="logPath">target/cucumber-logs</Property> <Property name="rollingFileName">cucumber</Property> </Properties>--> <Appenders> <Console name="CONSOLE" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/> <ThresholdFilter level="ERROR"/> </Console> <RollingFile name="APPLOG" append="true" fileName="@LOG_DIR@/@LOG_FILE_NAME@" filePattern="@LOG_DIR@/@LOG_FILE_NAME@.%d{yyyy-MM-dd-HH}"> <PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/> <ThresholdFilter level="@THRESHOLD@"/> <SizeBasedTriggeringPolicy size="15 MB"/> <DefaultRolloverStrategy max="10"/> </RollingFile> <RollingFile name="AUDITLOG" append="true" fileName="@AUDIT_LOG_DIR@/@AUDIT_LOG_FILE_NAME@" filePattern="@AUDIT_LOG_DIR@/@AUDIT_LOG_FILE_NAME@.%d{yyyy-MM-dd-HH}"> <PatternLayout pattern="[%t] %m%n"/> <ThresholdFilter level="INFO"/> <!-- Causes a rollover once the date/time pattern no longer applies to the active file --> <TimeBasedTriggeringPolicy modulate="true"/> </RollingFile> </Appenders> <Loggers> <!-- Category definitions --> <Logger name="com.abc" level="@THRESHOLD@" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.httpclient" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.springframework" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="com.mchange.v2" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.mortbay" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.apache" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="AUDIT_LOGGER" level="INFO" additivity="false"> <AppenderRef ref="AUDITLOG"/> </Logger> <!-- Setup the Root category --> <Root level="DEBUG"> <AppenderRef ref="APPLOG" level="@THRESHOLD@"/> </Root> </Loggers> </Configuration>
问题排查与修复方案
1. Root Logger配置逻辑偏差
原Log4j1中Root Logger的优先级为@THRESHOLD@,直接关联APPLOG;但Log4j2配置中将Root Logger的level设为DEBUG,同时在AppenderRef上额外指定level="@THRESHOLD@"。这种双层过滤会导致:
- 若
@THRESHOLD@的值高于DEBUG(比如INFO),DEBUG级日志会被Root Logger拦截,无法到达APPLOG - 未被自定义Logger覆盖的日志会流向Root,最终无法写入文件,可能通过默认配置输出到控制台
修复:将Root Logger的level直接设为@THRESHOLD@,移除AppenderRef上的level属性,与原配置逻辑保持一致:
<Root level="@THRESHOLD@"> <AppenderRef ref="APPLOG"/> </Root>
2. RollingFileAppender滚动策略不符合原逻辑
原Log4j1的APPLOG仅基于文件大小滚动,最多保留10个备份;但Log4j2配置中filePattern包含日期格式,会自动启用时间滚动,导致滚动逻辑与原配置不一致,可能干扰日志写入。
修复:若仅需大小滚动,修改filePattern为仅包含序号后缀:
<RollingFile name="APPLOG" append="true" fileName="@LOG_DIR@/@LOG_FILE_NAME@" filePattern="@LOG_DIR@/@LOG_FILE_NAME@.%i"> <PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/> <ThresholdFilter level="@THRESHOLD@"/> <SizeBasedTriggeringPolicy size="15 MB"/> <DefaultRolloverStrategy max="10"/> </RollingFile>
3. ThresholdFilter缺少明确匹配规则
Log4j2的ThresholdFilter默认行为可能因版本略有差异,建议明确添加onMatch和onMismatch属性,确保过滤逻辑生效:
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
额外检查点
- 确认
@THRESHOLD@变量替换后的值是否符合预期(如DEBUG/INFO) - 清理依赖:移除所有Log4j1依赖,确保仅保留Log4j2及
log4j-1.2-api桥接包 - 检查日志目录的读写权限,确保应用有写入权限
- 启用Log4j2调试模式(在
Configuration标签添加status="debug"),查看配置加载和日志路由的详细日志,定位未写入文件的具体日志来源
最终修复后的Log4j2配置示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn"> <Appenders> <Console name="CONSOLE" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> </Console> <RollingFile name="APPLOG" append="true" fileName="@LOG_DIR@/@LOG_FILE_NAME@" filePattern="@LOG_DIR@/@LOG_FILE_NAME@.%i"> <PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/> <ThresholdFilter level="@THRESHOLD@" onMatch="ACCEPT" onMismatch="DENY"/> <SizeBasedTriggeringPolicy size="15 MB"/> <DefaultRolloverStrategy max="10"/> </RollingFile> <RollingFile name="AUDITLOG" append="true" fileName="@AUDIT_LOG_DIR@/@AUDIT_LOG_FILE_NAME@" filePattern="@AUDIT_LOG_DIR@/@AUDIT_LOG_FILE_NAME@.%d{yyyy-MM-dd-HH}"> <PatternLayout pattern="[%t] %m%n"/> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/> <TimeBasedTriggeringPolicy modulate="true"/> </RollingFile> </Appenders> <Loggers> <Logger name="com.abc" level="@THRESHOLD@" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.httpclient" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.springframework" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="com.mchange.v2" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.mortbay" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="org.apache" level="INFO" additivity="false"> <AppenderRef ref="APPLOG"/> </Logger> <Logger name="AUDIT_LOGGER" level="INFO" additivity="false"> <AppenderRef ref="AUDITLOG"/> </Logger> <Root level="@THRESHOLD@"> <AppenderRef ref="APPLOG"/> </Root> </Loggers> </Configuration>
内容的提问来源于stack exchange,提问作者MadOverJava
相关产品推荐
相关产品推荐

