slf4j2自定义filter插件

204 阅读3分钟

1. maven配置

必须引入依赖并按照slf4j2插件说明配置maven编译插件log4j-plugin-processor

<!--pom.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>local.my</groupId>
    <artifactId>jdkdemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.23.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- slf4j2自定义插件必须的注解处理器 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <executions>
                    <execution>
                        <id>log4j-plugin-processor</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <phase>process-classes</phase>
                        <configuration>
                            <proc>only</proc>
                            <annotationProcessors>
                                <annotationProcessor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor</annotationProcessor>
                            </annotationProcessors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

2. 自定义Filter

  1. 自定义Filter继承自org.apache.logging.log4j.core.filter.AbstractFilter
  2. 使用@Plugin注解 Filter类
  3. 实现注解@PluginFactory()创建Filter对象
  4. 本例中,如果日志消息包含指定字符串则过滤不打印
package local.my;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.PerformanceSensitive;

@Plugin(name = "CustomFilter", // Filter的名称,即xml配置时的节点名称
        category = "Core", elementType = "filter", printObject = true)
@PerformanceSensitive("allocation")
public class CustomFilter extends AbstractFilter {
    private String str;
    private Filter.Result isOk(String msg){
        //包含str的日志消息被过滤并阻止打印输出
        return str!=null&&msg.contains(str)? Result.DENY:Filter.Result.ACCEPT;
    }
    @Override
    public Filter.Result filter(final Logger logger, final Level level, final Marker marker, final Message msg, final Throwable t) {
        return isOk(msg.getFormattedMessage());
    }
    @Override
    public Filter.Result filter(final Logger logger, final Level level, final Marker marker, final Object msg, final Throwable t) {
        return isOk(msg.toString());
    }
    @Override
    public Filter.Result filter(final Logger logger, final Level level, final Marker marker, final String msg, final Object... params) {
        return isOk(msg);
    }
    @Override
    public Result filter(LogEvent event) {
        return isOk(event.getMessage().getFormattedMessage());
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0) {
        return filter(logger, level, marker, msg, new Object[]{p0});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3, p4});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3, p4, p5});
    }

    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3, p4, p5, p6});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3, p4, p5, p6, p7});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3, p4, p5, p6, p7, p8});
    }
    @Override
    public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {
        return filter(logger, level, marker, msg, new Object[]{p0, p1, p2, p3, p4, p5, p6, p7, p8, p9});
    }
    @PluginFactory()
    public static CustomFilter createFilter(@PluginAttribute("str") final String str) {
        var s = new CustomFilter();
        s.str=str==null|| str.isEmpty() ? null:str;
        return s;
    }
}

3. 配置slf4j2

  1. 配置Logger节点
  2. 添加自定义的CustomFilter
  3. 本例中过滤包含字符串“过滤”的日志
<!--log4j2.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="debug" monitorInterval="30">
    <Properties>
        <Property name="myPattern" value="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Properties>
    <Appenders>
        <Console name="ConsoleAppend" target="SYSTEM_OUT">
            <PatternLayout pattern="${myPattern}"/>
            <!--<CustomFilter />这里也可以配置Filter,和下面的独立,即是两个不同的对象-->
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="ConsoleAppend"/>
            <!--自定义的Filter,过滤指定字符串-->
            <CustomFilter str="过滤"/>
        </Root>
    </Loggers>
</Configuration>

4. 测试启动

  1. 创建日志对象
  2. 正常使用日志打印API
  3. 本例中第二行日志将不会打印
package local.my;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Main {
    static Logger logger = LogManager.getLogger(Main.class);
    public static void main(String[] args) {
        logger.info("消息正常打印");
        logger.error("消息被过滤将不打印");
    }
}