1. 程式人生 > 程式設計 >利用logback 設定不同包下的日誌級別

利用logback 設定不同包下的日誌級別

1、實現效果:專案的整體的日誌列印級別為ERROR,但在某個包下或某個類想列印INFO級別的日誌。

2、配置:

FILE是ERROR級別日誌列印;

SPECIAL 是INFO級別日誌列印;

FILE與SPECIAL唯一不同是日誌儲存路徑不同,其它策略相同;

通過 logger標籤指定包路徑或類路徑並引用SPECIAL;

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <contextName>test</contextName>
 <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
   <fileNamePattern>${catalina.home}/logs/test/test.%d.%i.log</fileNamePattern>
   <maxHistory>30</maxHistory>
   <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    <maxFileSize>10MB</maxFileSize>
   </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
  <encoder>
   <pattern>%d %p (%file:%line\)- %m%n -[%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}]</pattern>
   <charset>UTF-8</charset>
  </encoder>
 </appender>

 <appender name="SPECIAL" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
   <fileNamePattern>${catalina.home}/logs/test/special/special.%d.%i.log</fileNamePattern>
   <maxHistory>30</maxHistory>
   <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    <maxFileSize>10MB</maxFileSize>
   </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
  <encoder>
   <pattern>%d %p (%file:%line\)- %m%n -[%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}]</pattern>
   <charset>UTF-8</charset>
  </encoder>
 </appender>

 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
   <pattern>%d %p (%file:%line\)- %m%n </pattern>
   <charset>UTF-8</charset>
  </encoder>
 </appender>
 <!--列印SQL-->
 <logger name="daoLog" level="ERROR" />
 <!-- 記錄special操作日誌 -->
 <logger name="aaa.bbb.ccc.DemoService" level="INFO" >
  <appender-ref ref="SPECIAL"/>
 </logger>

 <root level="error">
  <appender-ref ref="FILE"/>
  <appender-ref ref="STDOUT"/>
 </root>
</configuration> 

補充知識:logback框架使用誤區 如何將所有包的ERROR級別日誌集中列印到一個日誌檔案中

早就想寫這個事情了,起因是自己想寫一個東西,其中使用logback日誌框架記錄日誌

打算 將所有包的ERROR及以上級別日誌打到一個檔案中,各個包下的日誌打到對應包的檔案中。

起初寫的xml配置類似於這樣:

<!-- 其中一個appender,其他appender與其相同 ,只有name、file和fileNamePattern不同-->
<appender name="ALL-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
 <file>all-error.log</file>
 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  <fileNamePattern>
   ${log_dir}/all-error.%d{yyyy-MM-dd}.%i.log
  </fileNamePattern>
  <maxFileSize>100MB</maxFileSize>
  <maxHistory>60</maxHistory>
  <totalSizeCap>20GB</totalSizeCap>
 </rollingPolicy>
 <encoder>
  <pattern>
   %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
  </pattern>
 </encoder>
</appender>
<logger name="com.some.package1" level="INFO" additivty="true">
 <appender-ref ref="appender-1"/>
</logger>
<logger name="com.some.package2" level="INFO" additivty="true">
 <appender-ref ref="appender-2"/>
</logger>

<logger name="com.some" level="ERROR" additivty="true">
 <appender-ref ref="ALL-ERROR"/>
</logger>

然而執行後卻發現,這樣配置後的,並沒有達到預期目標。

反而,所有INFO及以上的資訊,不僅在appender appender-1和appender-2對應的日誌檔案中有,在appender為ALL-ERROR對應的日誌檔案中也都有,這是為何?

追蹤了一下斷點,發現如下程式碼片段:

/**
 * Invoke all the appenders of this logger.
 * 
 * @param event
 *   The event to log
 */
public void callAppenders(ILoggingEvent event) {
 int writes = 0;
 for (Logger l = this; l != null; l = l.parent) {
  writes += l.appendLoopOnAppenders(event);
  if (!l.additive) {
   break;
  }
 }
 // No appenders in hierarchy
 if (writes == 0) {
  loggerContext.noAppenderDefinedWarning(this);
 }
}

這段程式碼來自logback的 ch.qos.logback.classic.Logger檔案,是最終決定日誌內容輸出在哪裡的程式碼。

從這段程式碼我們可以發現:

1. logback會找到第一個符合日誌級別要求的logger,然後將日誌內容輸入到這個logger下配置的appender中。舉例來說:如果有一個com.some.package1內的類的INFO級別日誌,那麼首先會找到logger com.some.package1,然後找到logger下配置的appender appender-1;最後根據appender-1的配置,將日誌內容輸出到appender-1配置的檔案中。

2. 之後,logback根據additivty檢查logger是否允許繼承,如果配置為true(預設為true),則查詢上一級logger(實際是按照以包名為name查詢上一層包的logger),找到logger後,不再判斷logger配置是否符合日誌級別要求,直接找到對應的appender,將日誌內容輸出。

這就帶來了一個問題,位於低層次包的logger,在接收到日誌後,不僅會把它輸出到自身的appender中,還會將其傳遞給位於高層次包logger的appender中,無論高層次包logger配置的日誌級別是什麼。正因為如此,所以我打算將所有包的ERROR級別 日誌輸出到一個檔案的目的沒有實現,反而所有INFO及以上級別的日誌都輸出了。

按照這個思路,如果logger com.some.package1和com.some.package2日記級別為ERROR,而logger com.some日誌級別為INFO的話,是否所有INFO及以上級別的日誌都可以記入logger com.some對應的appender下,而ERROR及以上級別的日誌會記入logger com.some.package1和com.some.package2呢?測試證明,是這樣。

知道了為什麼上面的配置達不到目的,接下來要考慮的是,藉助什麼方式實現這個需求呢?

logback提供了實現需求的方式:藉助Filter來做:

既然logger無法判斷日誌級別,那我們可以在對應的appender裡判斷日誌級別。

logback的過濾器使用起來可以達到對每一條日誌的DENY、ACCEPT和NEUTRAL。

根據文章開始提出的需求,我們需要的是一個繫結appender的,過濾日誌等級的filter,那麼ch.qos.logback.classic.filter.ThresholdFilter正好是我們需要的。通過加入如下配置,appender ALL-ERROR將只能接受ERROR及以上的日誌:

<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
 <level>INFO</level> 
</filter> 

完整的xml配置如下,僅改變了filter的部分,就實現了需求:

<!-- 其中一個appender,其他appender與其相同 ,只有name、file和fileNamePattern不同,並且沒有filter的標籤-->
<appender name="ALL-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
 <file>all-error.log</file>
 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
  <level>ERROR</level> 
 </filter> 
 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  <fileNamePattern>
   ${log_dir}/all-error.%d{yyyy-MM-dd}.%i.log
  </fileNamePattern>
  <maxFileSize>100MB</maxFileSize>
  <maxHistory>60</maxHistory>
  <totalSizeCap>20GB</totalSizeCap>
 </rollingPolicy>
 <encoder>
  <pattern>
   %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
  </pattern>
 </encoder>
</appender>
<logger name="com.some.package1" level="INFO" additivty="true">
 <appender-ref ref="appender-1"/>
</logger>
<logger name="com.some.package2" level="INFO" additivty="true">
 <appender-ref ref="appender-2"/>
</logger>

<logger name="com.some" level="ERROR" additivty="true">
 <appender-ref ref="ALL-ERROR"/>
</logger>

更多關於logback的Filter的講解,請見

1. logback filter文件

以上這篇利用logback 設定不同包下的日誌級別就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。