天天看點

Logback中使用TurboFilter實作日志級别等内容的動态修改

可能看到這個标題,讀者會問:要修改日志的級别,不是直接修改log.xxx就好了嗎?為何要搞那麼複雜呢?是以,先說一下場景,為什麼要通過TurboFilter去動态的修改日志級别。我們在使用Java開發各種項目的時候必然的會引入很多架構,這些架構通過堆疊的方式完成所要提供的業務服務(一個服務請求在進入後會在這些架構中兜一圈,然後傳回結果),當一個比較底層的架構在處理過程中抛出了異常之後,這個異常會不斷的向上傳遞。這個時候,有的架構直接throw,繼續向上抛,而有的在throw之前還會自己列印一下error日志,這就導緻了當出現異常的時候,往往會出現一連串類似的錯誤日志記錄。如果對接了錯誤日志告警,就會出現重複告警的現象。為了解決類似這樣的問題,修改源碼重新編譯最直接,但是不可取。是以希望可以有更好的手段去控制這些已經被編碼固化的日志列印資訊。當我們使用Logback的時候,TurboFilter就是解決該問題的工具之一。

TurboFIlter不同于之前在[《Logback中如何自定義靈活的日志過濾規則》]一文中介紹的那些通過

ch.qos.logback.core.filter.Filter

接口實作的過濾器。

ch.qos.logback.core.filter.Filter

實作的過濾器是與Appender綁定的,而TurboFIlter是與日志上下文綁定的,它會過濾所有的日志請求,并且TurboFIlter的方法中提供了豐富的可通路資訊用來進行控制和改寫。

比如下面的實作,通過繼承

ch.qos.logback.classic.turbo.TurboFilter

類,并重寫

decide

方法,将

org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter

類中原本要列印的ERROR日志DENY掉(過濾掉),同時以WARN級别列印一封相同的内容,這樣就實作了對已定義日志的動态修改。

public class ForceWarnFilter extends TurboFilter {

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable throwable) {
        if (level == Level.ERROR && logger.getName().equals("org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter")) {
            logger.warn(marker, format, params);
            return FilterReply.DENY;
        }
        return FilterReply.NEUTRAL;
    }

}      

為了讓上面定義的過濾器生效,需要在logback的配置xml中增加如下配置:

<configuration>
    <turboFilter class="com.didispace.log.filter.ForceWarnFilter" />

    ......
</configuration>      

或者也可以在應用主類中增加:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.addTurboFilter(new MyTurboFilter());      

更多關于Logback過濾器的内容可參考官方文檔:

https://logback.qos.ch/manual/filters.html