解決logback的日誌分包與日誌分用戶導致的重複日誌輸出問題

logback 支持分模塊輸出,假如工程裏有多個模塊,可以使用每個模塊的日誌分一個日誌文件來輸出,很多情況,還會出現在這個基礎上,還想按照每個用戶的日誌輸出,這個時候可能就是用到了MDC來分割日誌文件,來實現每個

用戶單獨一個文件,如果簡單的配置會出現已經分別在每個用戶文件裏輸出的日誌,還會在模塊的日誌文件裏再輸出一遍,這樣導致模塊的日誌很大,且易讀性很差,同時也浪費空間.

這個問題在原理上理解也是比較容易理解的,因爲分模塊輸出的策略是與分用戶的策略是沒有聯繫的,因爲也得配置說分用戶策略輸出的日誌不需要在分模塊輸出,logback沒有這樣的配置,

這樣問題是需要參考每個模塊一個error文件的配置如下:

<appender name="split.package.appender.error" class="ch.qos.logback.classic.sift.SiftingAppender" timeout="10 days">
        <discriminator class="com.kiktech.swarm.common.log.SplitPackageFileDiscriminator"/>
        <sift>
            <appender name="ROLLING_FILE-${springAppName}-${swarm3}"
                      class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>./logs/${springAppName}-${swarm3}.error.log</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                    <fileNamePattern>./logs/${springAppName}-${swarm3}-%d{yyyy-MM-dd}.error.%i.log</fileNamePattern>
                    <maxFileSize>100MB</maxFileSize>
                    <maxHistory>5</maxHistory>
                    <totalSizeCap>1GB</totalSizeCap>
                </rollingPolicy>
                <encoder>
                    <pattern>${FILE_LOG_PATTERN}</pattern>
                </encoder>
                <filter class="ch.qos.logback.classic.filter.LevelFilter">
                    <level>ERROR</level>
                    <onMatch>ACCEPT</onMatch>
                    <onMismatch>DENY</onMismatch>
                </filter>
            </appender>
           </sift>
    </appender>

就是在這個appender配置里加上一個filter這個LevelFilter在全局的日誌級別再加一層過濾,至於這層過濾是怎樣過濾的,可以找下它的源碼如下:

public class LevelFilter extends AbstractMatcherFilter<ILoggingEvent> {

    Level level;

    @Override
    public FilterReply decide(ILoggingEvent event) {
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }

        if (event.getLevel().equals(level)) {
            return onMatch;
        } else {
            return onMismatch;
        }
    }

    public void setLevel(Level level) {
        this.level = level;
    }

    public void start() {
        if (this.level != null) {
            super.start();
        }
    }
}

就是如果日誌級別與配置的級別相同的就接受否則拒絕,這樣就實現了分模塊只打印錯誤的日誌

根據上面的加一層過濾的思路,就可以也這樣配置,如果有分用戶的標識就說明已經在用戶日誌文件輸出了,分模塊的日誌就不要輸出了

目前logback提代的filter只兩個"ch.qos.logback.classic.filter.LevelFilter"和"ch.qos.logback.classic.filter.ThresholdFilter"所以要自己實現個filter纔可以於就是自定義實現接口

public class NoRobotLogFilter extends AbstractMatcherFilter<ILoggingEvent> {
    @Override
    public FilterReply decide(ILoggingEvent iLoggingEvent) {

        return iLoggingEvent.getMDCPropertyMap().get(SplitRobotFileDiscriminator.ROBOT_KEY) == null ? FilterReply.ACCEPT : FilterReply.DENY;
    }
}

並配置到appender裏去

  <appender name="split.package.appender" class="ch.qos.logback.classic.sift.SiftingAppender" timeout="10 days">
        <discriminator class="com.kiktech.swarm.common.log.SplitPackageFileDiscriminator"/>
        <sift>
            <appender name="ROLLING_FILE-${springAppName}-${swarm3}"
                      class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>./logs/${springAppName}-${swarm3}.log</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                    <fileNamePattern>./logs/${springAppName}-${swarm3}-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                    <maxFileSize>100MB</maxFileSize>
                    <maxHistory>5</maxHistory>
                    <totalSizeCap>1GB</totalSizeCap>
                </rollingPolicy>
                <encoder>
                    <pattern>${FILE_LOG_PATTERN}</pattern>
                </encoder>
                <filter class="com.kiktech.swarm.base.log.NoRobotLogFilter"/>
            </appender>
        </sift>
    </appender>

這樣就可以解決 問題了,模塊日誌裏不分包含已經在分用戶日誌文件裏存在的日誌.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章