1. level規則
logj42會先匹配是否符合Logger/Root的level,如果符合的話,再一一匹配Logger/Root下的AppenderRef的level是否匹配。
<Configuration status="DEBUG" updateCheck="false">
<Appenders>
<Console name="Console1" target="SYSTEM_OUT">
<PatternLayout pattern="[%d] [%t] [%c\:%L] [%p] [%X{RequestID}] %m%n" charset="UTF-8"/>
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
</Console>
<Console name="Console2" target="SYSTEM_OUT">
<PatternLayout pattern="[%d] [%t] [%c\:%L] [%p] [%X{RequestID}] %m%n" charset="UTF-8"/>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Console>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Console1" />
<AppenderRef ref="Console2"/>
</Root>
</Loggers>
</Configuration>
log4j2會先匹配日誌級別是否符合Root
的level級別,如果是,則一一匹配是否符合Console1
和Console2
的level級別。
以上配置,logger.debug
只會在Console1
裏打印出來,logger.info
則會Console1
和Console2
兩個都打印出來。
2. additivity
log4j2會優先查找最優匹配的name
,然後將日誌一級級往上拋,每一個name
匹配的Logger/Root都會再打印一次日誌。
<Loggers>
<Logger name="com.test" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="org" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="com" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Root level="DEBUG">
<AppenderRef ref="Console1"/>
</Root>
</Loggers>
以上配置,如果在com.test
包下調用logger.debug
,會打印三次,因爲log4j2優先匹配到com.test
,然後往上拋再匹配到com
,繼續往上拋又匹配到Root
,所以打印了三次。
可以通過配置additivity="false"
阻止上拋,additivity
默認爲true
。
<Loggers>
<Logger name="org.test" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="my.test" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="com.test" level="DEBUG" additivity="false">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="org" level="DEBUG" additivity="false">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="my" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="com" level="DEBUG">
<AppenderRef ref="Console1"/>
</Logger>
<Root level="DEBUG">
<AppenderRef ref="Console1"/>
</Root>
</Loggers>
以上配置,如果在com.test
包下調用logger.debug
,只會打印一次;如果在org.test
包下調用logger.debug
,會打印兩次;如果在my.test
包下調用logger.debug
,會打印三次。
3. 繼承
Logger如果沒有配置AppenderRef,會默認繼承“有配置AppenderRef”的上一級的配置。
<Loggers>
<Logger name="com.test" level="ERROR"/>
<Root level="DEBUG">
<AppenderRef ref="Console1"/>
</Root>
</Loggers>
以上配置,最終的效果是,com.test
包下level級別爲ERROR
,其他包的級別爲DEBUG
,但是隻會打印一次日誌,類似於 :
<Loggers>
<Root if(name="com.test") { level="ERROR" } else { level="DEBUG" }>
<AppenderRef ref="Console1"/>
</Root>
</Loggers>
注:log4j2沒有if-else
這種寫法,這裏只是表達最終的效果類似是這樣的。
<Loggers>
<Logger name="com.test.test2" level="INFO"/>
<Logger name="com.test" level="INFO"/>
<Logger name="com" level="INFO" additivity="false">
<AppenderRef ref="Console1"/>
</Logger>
<Root level="DEBUG">
<AppenderRef ref="Console1"/>
<AppenderRef ref="Console2"/>
</Root>
</Loggers>
以上配置,com.test.test2
包下打印日誌,最終會繼承name爲com
的Logger的配置,因爲com
是“有配置AppenderRef”中最優匹配com.test.test2
的Logger。
4. 繼承+additivity
<Loggers>
<Logger name="com.test" level="INFO"/>
<Logger name="org.test" level="INFO"/>
<Logger name="com" level="INFO">
<AppenderRef ref="Console1"/>
</Logger>
<Logger name="org" level="INFO" additivity="false">
<AppenderRef ref="Console1"/>
</Logger>
<Root level="DEBUG">
<AppenderRef ref="Console1"/>
</Root>
</Loggers>
以上配置,com.test
包下打印日誌,會打印兩次,因爲com.test
繼承了com
Logger打印了一次,然後com
上拋到Root
又打印了一次;org.test
包下打印日誌,只會打印一次,因爲org.test
繼承了org
Logger打印了一次,而org
上配置了additivity="false"
。