在使用log4j2的時候,一般都需要不同的日志分類打印不同的日志等級,如下面的配置
<!-- 用於指定log4j自動重新配置的監測間隔時間,單位是秒 --> <configuration debug="off" monitorInterval="10"> <Properties> <Property name="log-path">server_logs</Property> </Properties> <Appenders> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %t-%T %-5level %class{36} - %msg%xEx%n" /> </Console> </Appenders> <Loggers> <logger name = "com.mygame" level="debug"> <appender-ref ref="console" /> </logger> <root level="error"> <appender-ref ref="console" /> </root> </Loggers> </configuration>
這個配置的目標是,沒有指定logger的時候,日志輸出使用root,而root的級別是error,希望com.mygame包下面的日志輸出debug級別。但是這樣運行之后,發現日志輸出了兩遍,我是在從消息隊列中接收消息之后打印的日志,害得我以為一個消息被處理了兩次。
這種情況是log4j2的機制問題,在Log4j2中,logger是有繼承關系的,root是根節點,而上面配置中添加的logger就是root的子節點,在log4j2中,有個additivity的屬性,它是子Logger 是否繼承 父Logger 的 輸出源(appender) 的標志位。具體說,默認情況下子Logger會繼承父Logger的appender,也就是說子Logger會在父Logger的appender里輸出。若是additivity設為false,則子Logger只會在自己的appender里輸出,而不會在父Logger的appender里輸出。由於上面的配置com.mygame的logger和root都輸出到console中了,所以會顯示輸出了兩條日志。
要打破這種傳遞性,也非常簡單,在logger中添加 additivity = "false",如下所示:
<Loggers> <logger name = "com.mygame" level="debug" additivity = "false"> <appender-ref ref="console" /> </logger> <root level="error"> <appender-ref ref="console" /> </root> </Loggers>