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>
這樣就可以解決 問題了,模塊日誌裏不分包含已經在分用戶日誌文件裏存在的日誌.