本文主要研究一下logback的DynamicThresholdFilter

DynamicThresholdFilter

public class DynamicThresholdFilter extends TurboFilter {
    private Map<String, Level> valueLevelMap = new HashMap<String, Level>();
    private Level defaultThreshold = Level.ERROR;
    private String key;

    private FilterReply onHigherOrEqual = FilterReply.NEUTRAL;
    private FilterReply onLower = FilterReply.DENY;

    //......
}    
DynamicThresholdFilter继承了TurboFilter,它定义了valueLevelMap、defaultThreshold为ERROR,onHigherOrEqual为NEUTRAL,onLower为DENY

addMDCValueLevelPair

    public void addMDCValueLevelPair(MDCValueLevelPair mdcValueLevelPair) {
        if (valueLevelMap.containsKey(mdcValueLevelPair.getValue())) {
            addError(mdcValueLevelPair.getValue() + " has been already set");
        } else {
            valueLevelMap.put(mdcValueLevelPair.getValue(), mdcValueLevelPair.getLevel());
        }
    }    
addMDCValueLevelPair方法可以根据MDCValueLevelPair往valueLevelMap添加配置

MDCValueLevelPair

ch/qos/logback/classic/turbo/MDCValueLevelPair.java

public class MDCValueLevelPair {
    private String value;
    private Level level;

    public String getValue() {
        return value;
    }

    public void setValue(String name) {
        this.value = name;
    }

    public Level getLevel() {
        return level;
    }

    public void setLevel(Level level) {
        this.level = level;
    }
}
MDCValueLevelPair定义了value及level属性

decide

    public FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects,
            Throwable throwable) {

        String mdcValue = MDC.get(this.key);
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }

        Level levelAssociatedWithMDCValue = null;
        if (mdcValue != null) {
            levelAssociatedWithMDCValue = valueLevelMap.get(mdcValue);
        }
        if (levelAssociatedWithMDCValue == null) {
            levelAssociatedWithMDCValue = defaultThreshold;
        }
        if (level.isGreaterOrEqual(levelAssociatedWithMDCValue)) {
            return onHigherOrEqual;
        } else {
            return onLower;
        }
    }
decide方法先从mdc获取key对应的mdcValue,然后根据mdcValue去valueLevelMap获取对应的level,如果获取不到则取defaultThreshold;如果要打印的level大于等于levelAssociatedWithMDCValue则返回NEUTRAL,否则返回DENY

示例

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>

    <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
        <Key>userId</Key>
        <DefaultThreshold>ERROR</DefaultThreshold>
        <MDCValueLevelPair>
            <value>user1</value>
            <level>INFO</level>
        </MDCValueLevelPair>
        <MDCValueLevelPair>
            <value>user2</value>
            <level>TRACE</level>
        </MDCValueLevelPair>

    </turboFilter>


    <appender name="LIST"
        class="ch.qos.logback.core.read.ListAppender">
    </appender>

    <root>
        <level value="DEBUG" />
        <appender-ref ref="LIST" />
    </root>
</configuration>

小结

logback提供了DynamicThresholdFilter,它可以根据配置的key从MDC取值,再根据配置的MDCValueLevelPair去映射对应的level,达到动态log级别的效果。


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...