1. 程式人生 > >log4j2中LevelRangeFilter的注意點

log4j2中LevelRangeFilter的注意點

LevelRangeFilter的注意點

在log4j2中,LevelRangeFilter的minLevel,maxLevel的配置是和log4j 1.x相反的;minLevel需要配置的是高級別,maxLevel配置的是低級別,如下:

<LevelRangeFilter minLevel="fatal" maxLevel="info" onMatch="ACCEPT" onMismatch="DENY"/>

如上邊的配置,是列印info到fatal級別的log,如果配置反過來,則不會輸出任何log。

如果不配置minLevel、maxLevel、onMatch和onMismatch的值,則會為其設定預設值,在LevelRangeFilter中的原始碼實現如下:

@PluginFactory
public static LevelRangeFilter createFilter(
    // @formatter:off
    @PluginAttribute("minLevel") final Level minLevel,
    @PluginAttribute("maxLevel") final Level maxLevel,
    @PluginAttribute("onMatch") final Result match,
    @PluginAttribute("onMismatch") final Result mismatch) {
    // @formatter:on
    final Level actualMinLevel = minLevel == null ? Level.ERROR : minLevel;
    final Level actualMaxLevel = maxLevel == null ? Level.ERROR : maxLevel;
    final Result onMatch = match == null ? Result.NEUTRAL : match;
    final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
    return new LevelRangeFilter(actualMinLevel, actualMaxLevel, onMatch, onMismatch);
}

至於為什麼把最大最小level的值配置反了就會無法輸出,是因為在LevelRangeFilter中的原始碼實現如下:

private Result filter(final Level level) {
    return level.isInRange(this.minLevel, this.maxLevel) ? onMatch : onMismatch;
}

可以看到,在呼叫filter方法進行過濾時,是呼叫了level#isInRange()來判斷是否匹配該filter的。而在該方法中,實現如下:

public boolean isInRange(final Level minLevel, final Level maxLevel) {
    return this.intLevel >= minLevel.intLevel && this.intLevel <= maxLevel.intLevel;
}

這裡通過對比Level物件的intLevel值(int)來判斷是否匹配,而這些Level物件也在Level這個類裡進行裡實例化:

static {
    OFF = new Level("OFF", StandardLevel.OFF.intLevel());
    FATAL = new Level("FATAL", StandardLevel.FATAL.intLevel());
    ERROR = new Level("ERROR", StandardLevel.ERROR.intLevel());
    WARN = new Level("WARN", StandardLevel.WARN.intLevel());
    INFO = new Level("INFO", StandardLevel.INFO.intLevel());
    DEBUG = new Level("DEBUG", StandardLevel.DEBUG.intLevel());
    TRACE = new Level("TRACE", StandardLevel.TRACE.intLevel());
    ALL = new Level("ALL", StandardLevel.ALL.intLevel());
}

可以看到,這些Level物件的intLevel值是由另一個列舉類StandardLevel來提供的:

/**
* No events will be logged.
*/
OFF(0),

/**
* A severe error that will prevent the application from continuing.
*/
FATAL(100),

/**
* An error in the application, possibly recoverable.
*/
ERROR(200),

/**
* An event that might possible lead to an error.
*/
WARN(300),

/**
* An event for informational purposes.
*/
INFO(400),

/**
* A general debugging event.
*/
DEBUG(500),

/**
* A fine-grained debug message, typically capturing the flow through the application.
*/
TRACE(600),

/**
* All events should be logged.
*/
ALL(Integer.MAX_VALUE);

可以看到,Level級別越高,其對應的intLevel值越小,可以這樣理解:級別越高,能打印出來的日誌資訊就越少,所以其intLevel值就越小。

如果我們把LevelRangeFilter的minLevel、maxLevel配置反了,會導致level#isInRange()返回false,最終也就沒有任何日誌得以輸出了。