只输出单一级别,而不是本级及以上的级别日志。
直接上代码
eg: 只输出WARN级别
<!--经测试,console标签里面也可以用,RollingFile没有测试,应该也可以-->
<File name="FileWarn" fileName="${FILE_PATH}/warn.log" append="false">
<Filters>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</File>
核心是:
<Filters>内部去套多个<ThresholdFilter>过滤器,外部的<Filters>标签不能少,不能直接用多个<ThresholdFilter>。网上很多资料就是没有说清楚这个,让人头疼。
原理:
<ThresholdFilter> 的 onMatch :如何处理level及其以上级别的信息 ,onMismatch则相应的,如何处理level以下的信息。因此要先定义日志级别高的Filter。
ACCEPT、DENY好理解,关键的就是NEUTRAL:中立,不处理但也不拦截,交给后续过滤器处理。而DENY是直接拦截,后续有处理器也没办法处理。
因此要完成输出单一级别的任务:需要两个过滤器。还是以warn级别为例
-
第一个过滤器,level为上一级别,此处即
level="ERROR",然后onMatch="DENY" onMismatch="NEUTRAL",效果等价于:(DENY)拦截ERROR及其以上的信息,放行ERROR以下的信息 -
第二个过滤器,level即为需要输出的级别,此处为
level="WARN",然后onMatch="ACCEPT" onMismatch="DENY",效果等价于:接收WARN及其以上级别的信息,拦截WARN以下级别的信息。但经第一个过滤器,此时WARN及其以上的级别的信息,只剩下WARN自己
至此,完成目标。
只要搞懂了原理,就算是想输出特定几个,或者某级别以下的,都是信手拈来。
拓:NEUTRAL的特例。
如果使用NEUTRAL的,已经是最后一个拦截器。那无论是onMatch还是onMismatch,都会匹配。
这里可能onMatch还容易理解,onMismatch都匹配是什么操作。但这是亲测出来的,是没错的。
笔者的理解:既然上面放行了,证明这些信息是有意义的,而到最后一个都还未处理,证明编程失误了,应该是要接收的。所以就统一接收了。
举个例子帮助理解:
<Filters>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
效果是接收WARN以下级别的信息。
(这里直接只有一个拦截器,当然也是最后一个拦截器了)
如果按照上述做法还达不到目标的,可能需要调整一下root 的级别。
必须先符合root规定的level,才能到自定义的appender中进行处理
<loggers>
<root level="">
<appender-ref ref=""/>
</root>
</loggers>
参考xml
附上笔者的xml文件,效果是:
- 分别输出
info、warn、error级别的到不同文件, - 控制台输出debug及其以上级别的所有信息。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="C:\Users\Lenovo\Desktop\log"/>
<!--<property name="FILE_NAME" value="更换为你的项目名"/> -->
</Properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<ThresholdFilter level="ALL"/>
</console>
<!-- 打印出所有的info级别的信息,-->
<File name="FileInfo" fileName="${FILE_PATH}/info.log" append="false">
<Filters>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
<!-- 同,打印出所有的Warn级别-->
<File name="FileWarn" fileName="${FILE_PATH}/warn.log" append="false">
<Filters>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
<File name="FileError" fileName="${FILE_PATH}/error.log" append="false">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和hibernate的一些无用的debug信息-->
<logger name="org.springframework" level="INFO"/>
<logger name="org.mybatis" level="INFO"/>
<root level="debug">
<appender-ref ref="Console"/>
<appender-ref ref="FileInfo"/>
<appender-ref ref="FileWarn"/>
<appender-ref ref="FileError"/>
</root>
</loggers>
</configuration>
吐槽一下,找了那么多资料居然都没个对的,还以为有多复杂。
正文完,有误欢迎指出。

本文介绍如何在log4j2中仅输出特定日志级别,而非该级别及其以上级别。关键在于配置多个过滤器,通过ACCEPT、DENY和NEUTRAL策略实现。示例以输出WARN级别为例,详细解析了过滤器的工作原理,并提供相关XML配置参考。
&spm=1001.2101.3001.5002&articleId=107867023&d=1&t=3&u=b9888965025f47e18387518ab7903420)
664

被折叠的 条评论
为什么被折叠?



