LOG4J2日志无法在控制台输出及全量日志文件内容缺失求助
我遇到了LOG4J2的Logger无法在控制台完整输出日志的问题,具体问题如下:
- 应用入口类的日志从未出现在
uService_all_logs.log中,且该文件仅写入INFO和WARN级别日志,但期望包含除DEBUG和TRACE外的所有级别日志; - 控制台完全不显示入口类的日志。
我的Log4j2配置文件(log4j2.xml)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xml> <!-- Fichier de configuration des loggers @author theo.lalande Hiérarchie des lvl: ALL<TRACE<DEBUG<INFO<WARN<ERROR<FATAL<OFF --> <Configuration status="INFO" monitorInterval="30"> <!-- PROPERTIES ______________________________________________________________________________ --> <Properties> <Property name="LOG_PATTERN"> %d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${hostName} - [%15.15t] %-40.40c{1.} : %m%n%ex </Property> </Properties> <!-- APPENDERS ______________________________________________________________________________ --> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout> <Pattern>${LOG_PATTERN}</Pattern> </PatternLayout> </Console> <!-- POUR TOUS LES LOGS --> <RollingFile name="FileAppenderAllLogs" fileName="logs/uService_all_logs.log" filePattern="logs/uService_all_logs-%d{yyyy-MM-dd}-%i.log"> <PatternLayout> <Pattern>${LOG_PATTERN}</Pattern> </PatternLayout> <Policies> <SizeBasedTriggeringPolicy size="10MB" /> </Policies> <DefaultRolloverStrategy max="7" /> </RollingFile> <!-- POUR LES LOGS DE NIVEAU INFO --> <RollingFile name="FileAppenderInfoLogs" fileName="logs/uService_info_logs.log" filePattern="logs/uService_info_logs-%d{yyyy-MM-dd}-%i.log"> <Filters> <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="ACCEPT" /> </Filters> <PatternLayout> <Pattern>${LOG_PATTERN}</Pattern> </PatternLayout> <Policies> <SizeBasedTriggeringPolicy size="10MB" /> </Policies> <DefaultRolloverStrategy max="7" /> </RollingFile> <!-- POUR LES LOGS DE NIVEAU WARN --> <RollingFile name="FileAppenderWarnLogs" fileName="logs/uService_warn_logs.log" filePattern="logs/uService_warn_logs-%d{yyyy-MM-dd}-%i.log"> <Filters> <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT" /> </Filters> <PatternLayout> <Pattern>${LOG_PATTERN}</Pattern> </PatternLayout> <Policies> <SizeBasedTriggeringPolicy size="10MB" /> </Policies> <DefaultRolloverStrategy max="7" /> </RollingFile> <!-- POUR LES LOGS DE NIVEAU ERROR --> <RollingFile name="FileAppenderErrorLogs" fileName="logs/uService_error_logs.log" filePattern="logs/uService_error_logs-%d{yyyy-MM-dd}-%i.log"> <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT" /> <PatternLayout> <Pattern>${LOG_PATTERN}</Pattern> </PatternLayout> <Policies> <SizeBasedTriggeringPolicy size="10MB" /> </Policies> <DefaultRolloverStrategy max="7" /> </RollingFile> <!-- POUR LES LOGS DE NIVEAU FATAL --> <RollingFile name="FileAppenderFatalLogs" fileName="logs/uService_fatal_logs.log" filePattern="logs/uService_fatal_logs-%d{yyyy-MM-dd}-%i.log"> <ThresholdFilter level="OFF" onMatch="DENY" onMismatch="ACCEPT" /> <PatternLayout> <Pattern>${LOG_PATTERN}</Pattern> </PatternLayout> <Policies> <SizeBasedTriggeringPolicy size="10MB" /> </Policies> <DefaultRolloverStrategy max="7" /> </RollingFile> </Appenders> <!-- LOGGERS ______________________________________________________________________________ --> <Loggers> <Root level="INFO" additivity="true"> <priority value="INFO" /> <AppenderRef ref="FileAppenderAllLogs" level="INFO" /> <AppenderRef ref="Console" level="INFO" /> </Root> <Logger name="com.compufirst.outstanding" level="INFO" additivity="false"> <AppenderRef ref="FileAppenderInfoLogs" level="INFO" /> <AppenderRef ref="FileAppenderWarnLogs" level="WARN" /> <AppenderRef ref="FileAppenderErrorLogs" level="ERROR" /> <AppenderRef ref="FileAppenderFatalLogs" level="FATAL" /> </Logger> </Loggers> </Configuration>
应用入口类代码
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.Configurator; @SpringBootApplication public class OutstandingPoc1Application { private static final Logger logger = LogManager.getLogger(OutstandingPoc1Application.class); public static void main(String[] args) { SpringApplication.run(OutstandingPoc1Application.class, args); Configurator.setAllLevels(logger.getName(), Level.TRACE); logger.debug("Debugging log"); logger.info("Info log"); logger.warn("Hey, This is a warning1!"); logger.error("Oops! We have an Error. OK"); logger.fatal("Damn! Fatal error. Please fix me."); } }
问题原因分析
入口类日志不进入
uService_all_logs.log和控制台:
自定义Loggercom.compufirst.outstanding设置了additivity="false",这意味着该Logger下的日志不会向上传递到Root Logger。而uService_all_logs.log和Console都是绑定在Root Logger下的,所以入口类(属于com.compufirst.outstanding包)的日志根本不会被Root的Appender处理。uService_all_logs.log缺少ERROR/FATAL级别日志:
同样因为自定义Logger的additivity="false",ERROR和FATAL级别的日志被自定义Logger绑定的FileAppenderErrorLogs、FileAppenderFatalLogs处理后,不会再传递给Root的FileAppenderAllLogs,导致all日志文件里只有INFO和WARN(这两个可能来自其他不属于com.compufirst.outstanding包的日志)。
解决方案
方案一:开启自定义Logger的日志传递
修改自定义Logger的配置,把additivity="false"改成additivity="true":
<Logger name="com.compufirst.outstanding" level="INFO" additivity="true"> <AppenderRef ref="FileAppenderInfoLogs" level="INFO" /> <AppenderRef ref="FileAppenderWarnLogs" level="WARN" /> <AppenderRef ref="FileAppenderErrorLogs" level="ERROR" /> <AppenderRef ref="FileAppenderFatalLogs" level="FATAL" /> </Logger>
这样自定义Logger的日志会同时传递给Root Logger,uService_all_logs.log就能收到所有INFO及以上级别(INFO、WARN、ERROR、FATAL)的入口类日志,控制台也能显示这些日志。
方案二:在自定义Logger中直接绑定目标Appender
如果不想让日志向上传递到Root,可以在自定义Logger里添加FileAppenderAllLogs和Console的绑定:
<Logger name="com.compufirst.outstanding" level="INFO" additivity="false"> <AppenderRef ref="FileAppenderInfoLogs" level="INFO" /> <AppenderRef ref="FileAppenderWarnLogs" level="WARN" /> <AppenderRef ref="FileAppenderErrorLogs" level="ERROR" /> <AppenderRef ref="FileAppenderFatalLogs" level="FATAL" /> <!-- 添加这两个AppenderRef --> <AppenderRef ref="FileAppenderAllLogs" level="INFO" /> <AppenderRef ref="Console" level="INFO" /> </Logger>
这样入口类的日志会直接被这两个Appender处理,同时不影响Root Logger处理其他包的日志。
额外说明
- 代码里的
Configurator.setAllLevels(logger.getName(), Level.TRACE)是在Spring Boot启动后设置日志级别,这会让入口类的Logger接受TRACE及以上级别日志,但因为Root和自定义Logger的level都是INFO,所以DEBUG和TRACE日志还是不会被输出到文件或控制台,如果需要输出DEBUG日志,需要把对应的Logger level改成DEBUG。 FileAppenderAllLogs本身没有过滤规则,只要Logger级别允许,就能接收所有符合级别的日志,调整additivity或者添加AppenderRef后,ERROR和FATAL日志就会正常写入该文件。
内容的提问来源于stack exchange,提问作者Théo

