1. level规则

logj42会先匹配是否符合Logger/Root的level,如果符合的话,再一一匹配Logger/Root下的AppenderRef的level是否匹配。

<Configuration status="DEBUG" updateCheck="false">
    <Appenders>
        <Console name="Console1" target="SYSTEM_OUT">
            <PatternLayout pattern="[%d] [%t] [%c\:%L] [%p] [%X{RequestID}] %m%n" charset="UTF-8"/>
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
        </Console>
        <Console name="Console2" target="SYSTEM_OUT">
            <PatternLayout pattern="[%d] [%t] [%c\:%L] [%p] [%X{RequestID}] %m%n" charset="UTF-8"/>
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="DEBUG">
            <AppenderRef ref="Console1" />
            <AppenderRef ref="Console2"/>
        </Root>
    </Loggers>
</Configuration>

log4j2会先匹配日志级别是否符合Root的level级别,如果是,则一一匹配是否符合Console1Console2的level级别。
以上配置,logger.debug只会在Console1里打印出来,logger.info则会Console1Console2两个都打印出来。

2. additivity

log4j2会优先查找最优匹配的name,然后将日志一级级往上抛,每一个name匹配的Logger/Root都会再打印一次日志。

<Loggers>
    <Logger name="com.test" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="org" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="com" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Root level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Root>
</Loggers>

以上配置,如果在com.test包下调用logger.debug,会打印三次,因为log4j2优先匹配到com.test,然后往上抛再匹配到com,继续往上抛又匹配到Root,所以打印了三次。
可以通过配置additivity="false"阻止上抛,additivity默认为true

<Loggers>
    <Logger name="org.test" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="my.test" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="com.test" level="DEBUG" additivity="false">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="org" level="DEBUG" additivity="false">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="my" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="com" level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Root level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Root>
</Loggers>

以上配置,如果在com.test包下调用logger.debug,只会打印一次;如果在org.test包下调用logger.debug,会打印两次;如果在my.test包下调用logger.debug,会打印三次。

3. 继承

Logger如果没有配置AppenderRef,会默认继承“有配置AppenderRef”的上一级的配置。

<Loggers>
    <Logger name="com.test" level="ERROR"/>
    <Root level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Root>
</Loggers>

以上配置,最终的效果是,com.test包下level级别为ERROR,其他包的级别为DEBUG,但是只会打印一次日志,类似于 :

<Loggers>
    <Root if(name="com.test") { level="ERROR" } else { level="DEBUG" }>
        <AppenderRef ref="Console1"/>
    </Root>
</Loggers>

注:log4j2没有if-else这种写法,这里只是表达最终的效果类似是这样的。

<Loggers>
    <Logger name="com.test.test2" level="INFO"/>
    <Logger name="com.test" level="INFO"/>
    <Logger name="com" level="INFO" additivity="false">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Root level="DEBUG">
        <AppenderRef ref="Console1"/>
        <AppenderRef ref="Console2"/>
    </Root>
</Loggers>

以上配置,com.test.test2包下打印日志,最终会继承name为com的Logger的配置,因为com是“有配置AppenderRef”中最优匹配com.test.test2的Logger。

4. 继承+additivity

<Loggers>
    <Logger name="com.test" level="INFO"/>
    <Logger name="org.test" level="INFO"/>
    <Logger name="com" level="INFO">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Logger name="org" level="INFO" additivity="false">
        <AppenderRef ref="Console1"/>
    </Logger>
    <Root level="DEBUG">
        <AppenderRef ref="Console1"/>
    </Root>
</Loggers>

以上配置,com.test包下打印日志,会打印两次,因为com.test继承了comLogger打印了一次,然后com上抛到Root又打印了一次;org.test包下打印日志,只会打印一次,因为org.test继承了orgLogger打印了一次,而org上配置了additivity="false"


noname
314 声望49 粉丝

一只菜狗