Logback中使用TurboFilter實現日誌級別等內容的動態修改

程式猿DD_發表於2019-03-01

可能看到這個標題,讀者會問:要修改日誌的級別,不是直接修改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過濾器的內容可參考官方文件:logback.qos.ch/manual/filt…

相關文章