瞭解log4j的源代碼來源於項目中一次需求,咱們想將系統全部的warn日誌統一收集到common-warn.log的日誌中去,以便於系統對其進行監控處理。因而模擬自動生成的error配置完成了warn的配置,可是測試發現common-warn.log中居然有error日誌,並且業務的正常日誌中居然也存在error和warn日誌。這樣至關於日誌重複打了好多地方,無疑增長了日誌量,同時增長了磁盤消耗。html
原始配置:apache
<appender name="DEFAULT-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="file" value="${log_root}/${sys_host_name}/app-service.log"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%X{loginUserEmail}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/> </layout> </appender> <!-- [公共Appender] 彙總錯誤 --> <appender name="ERROR-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="file" value="${log_root}/${sys_host_name}/common-error.log"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <param name="threshold" value="error"/>` <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%X{loginUserEmail}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/> </layout> </appender> <!-- [公共Appender] 彙總警告 --> <appender name="WARN-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="file" value="${log_root}/${sys_host_name}/common-warn.log"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <param name="threshold" value="WARN"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%X{loginUserEmail}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/> </layout> </appender> <!-- [應用Logger] - 默認 --> <logger name="APP-LOG" additivity="false"> <level value="${log_level}"/> <appender-ref ref="DEFAULT-APPENDER"/> <appender-ref ref="WARN-APPENDER"/> <appender-ref ref="ERROR-APPENDER"/> </logger>
因此個人核心訴求就是:將小於等於info的日誌打印到app-service.log,將error打印到common-error.log, 將warn打印到common-warn.log。 app
核心抽象:測試
整個日誌打印的過程能夠理解爲Loger拿着LoggingEvent去找Appender, 讓Appender按照Layout的形式將日誌打印到指定的位置。 而Level起的啥做用呢? Logger和Appender都是有原則的不能說你讓我打印我就打印,必須知足個人規則我纔給你打印,這裏的規則就是指Level(出來混都是要講原則的)。spa
覈對類圖:日誌
核心邏輯在LogManager的靜態代碼塊,根據配置信息解析初始化Logger,Appender和Layout等核心組件;htm
核心的日誌打印流程, 中間還有不少控制的細節,具體能夠看源代碼:對象
回到咱們的出發點,如何實現:
將小於等於info的日誌打印到app-service.log,將error打印到common-error.log, 將warn打印到common-warn.log。 blog
目前項目中使用的方案爲2, 同時app-service.log的Appender不配置Filter默認接受error和warn的日誌, 可是warn和error經過Fileter進行區分不會相互影響,這樣能夠知足業務監控warn和error日誌的需求,不須要修改任何代碼,同時知足不會丟失日誌的問題。可是存在error和warn日誌重複打印的問題。 接口
最終的解決方案配置:
<appender name="DEFAULT-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="file" value="${log_root}/${sys_host_name}/app-default.log"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%X{loginUserEmail}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/> </layout> </appender> <!-- [公共Appender] 彙總錯誤 --> <appender name="ERROR-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="file" value="${log_root}/${sys_host_name}/common-error.log"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <param name="threshold" value="error"/>` <!-- 僅打印error級別的日誌 --> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="levelMin" value="ERROR" /> <param name="levelMax" value="ERROR"/> <param name="acceptOnMatch" value="true"/> </filter> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%X{loginUserEmail}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/> </layout> </appender> <!-- [公共Appender] 彙總警告 --> <appender name="WARN-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="file" value="${log_root}/${sys_host_name}/common-warn.log"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <param name="threshold" value="WARN"/> <!-- 僅打印warn級別的日誌 --> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="levelMin" value="WARN" /> <param name="levelMax" value="WARN"/> <param name="acceptOnMatch" value="true"/> </filter> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%X{loginUserEmail}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/> </layout> </appender> <!-- [應用Logger] - 默認 --> <logger name="APP-LOG" additivity="false"> <level value="${log_level}"/> <appender-ref ref="DEFAULT-APPENDER"/> <appender-ref ref="WARN-APPENDER"/> <appender-ref ref="ERROR-APPENDER"/> </logger>