SpringBoot integrates Logback+ MDC request tracking + EvaluatorFilter to write Java code filtering

Article directory

    • SpringBoot integrates Logback + MDC request tracking + EvaluatorFilter to write Java code filter conditions
      • Introduce dependencies
      • logback-dev.xml configuration file
      • application.yml configuration
      • Configure the MDC filter
      • Configure the filter order (the order of using annotations in Filter sometimes fails)
      • Run the project to display the log results

SpringBoot integrates Logback + MDC request tracking + EvaluatorFilter to write Java code filter conditions

Introducing dependencies

Used to support EvaluatorFilter to write Java code

    <dependency>
        <groupId>org.codehaus.janino</groupId>
        <artifactId>janino</artifactId>
        <version>3.1.9</version>
    </dependency>

logback-dev.xml configuration file

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!--Define the storage address of the log file (absolute path) -->
    <property name="log_home" value="D:/LOG/" />
    <!--The name of the generated log-->
    <property name="project_name" value="test-demo" />
    <!-- log output to console -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- color log -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%X{requestId}] [%X{token}] [%thread] %magenta(%-5level) %green([%-50.50class]) > >> %cyan(%msg) %n
            </pattern>
        </layout>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
                <!-- log filters some packages or some classes do not print -->
                <expression>
if (logger.startsWith("com.test.demo.controller.api") || logger.contains("TestController")) {
return true;
}
return false;
                </expression>
            </evaluator>
            <!-- matching directly use DENY to discard without printing -->
            <OnMatch>DENY</OnMatch>
            <OnMismatch>ACCEPT</OnMismatch>
        </filter>

    </appender>

    <!-- log output to file (generated every day) -->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log_home}/${project_name}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>400MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%X{requestId}] [%X{token}] [%thread] %-5level %logger{50} - %msg%n </pattern>
        </layout>
    </appender>

    <logger name="org. hibernate. validator" level="INFO"/>
    <!-- Mybatis Mapper's sql can print the project -->
    <logger name="com.test.demo.mapper" level="DEBUG" />

    <root level="INFO">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>
</configuration>

application.yml configuration

logging:
  config: classpath:logback-dev.xml

Configure the MDC filter

import cn.hutool.core.util.IdUtil;
import org.slf4j.MDC;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;


/**
 * Log MDC Filter
 */
public class LogMdcFilter implements Filter {<!-- -->

    public static final String REQUEST_ID = "requestId";
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {<!-- -->
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {<!-- -->
    //The id tool of Hutool is used to generate it here. If there is no such dependency, it can be generated with the default UUID tool
        MDC.put(REQUEST_ID, IdUtil.simpleUUID());
        String userCode = null;
        if ( servletRequest instanceof HttpServletRequest) {<!-- -->
            var httpRequest = ((HttpServletRequest) servletRequest);
            var s = httpRequest. getHeaderNames();
            userCode = httpRequest.getHeader("x-demo-token");
        }
        //Corresponding to the parameter Key name of the logback-dev.xml configuration
        MDC.put("token", userCode);
        filterChain.doFilter(servletRequest, servletResponse);
        MDC. remove(REQUEST_ID);
        MDC. remove("token");
    }

    @Override
    public void destroy() {<!-- -->
        Filter. super. destroy();
    }
}

Configure the filter order (the order of setting the filter using annotations sometimes fails)

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import javax.servlet.Filter;

@Configuration
public class FilterConfig {<!-- -->

    @Bean
    public Filter logMdcFilter() {<!-- -->
        return new LogMdcFilter();
    }

    @Bean
    public FilterRegistrationBean registrLogMdcFilter() {<!-- -->
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration. setFilter( logMdcFilter() );
        registration.addUrlPatterns("/*");
        registration.setName("logMdcFilter");
        registration.setAsyncSupported(true);
        //The smaller the order, the higher the priority (Filter settings added later can be larger than this value)
        registration. setOrder(0);
        return registration;
    }
 
}

Run the project to display the log results

23-03-25 15:30:04 [e97f247deec544bbba26cdcbe0db5f29] [testToken123] [http-nio-9800-exec-2] DEBUG [org.apache.ibatis.logging.jdbc.BaseJdbcLogger ] >>> ==> Preparing: SELECT * FROM USER WHERE USER_CODE = ?
23-03-25 15:30:04 [e97f247deec544bbba26cdcbe0db5f29] [testToken123] [http-nio-9800-exec-2] DEBUG [org.apache.ibatis.logging.jdbc.BaseJdbcLogger ] >>> ==> Parameters: testUser (String)