SpringBoot 如何快速过滤出一次请求的所有日志?

技术深度剖析 2024-05-18 ⋅ 21 阅读

在开发过程中,我们常常需要查看一次请求的所有日志,这对于排查问题和调试非常有帮助。SpringBoot 提供了一种快速过滤出一次请求的所有日志的方法,使我们能够更加高效地分析和定位问题。

方法介绍

SpringBoot 使用 Logback 作为默认的日志框架,Logback 内置了一个叫做 MDC(Mapped Diagnostic Context)的上下文环境,可以将一些关键信息存储在其中,方便我们在日志中进行查找和过滤。

在处理一次请求的过程中,我们可以通过 MDC 将一些关键信息存储在上下文中,比如请求的唯一标识(requestId),然后在日志输出时将 requestId 添加到日志中,在日志中搜索这个 requestId 就可以过滤出一次请求的所有日志。

实现步骤

第一步:导入依赖

在 pom.xml 文件中添加如下依赖:

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>6.6</version>
</dependency>

第二步:配置 Logback

src/main/resources 目录下创建名为 logback-spring.xml 的文件,内容如下:

<configuration>
    <!-- 定义日志文件存储路径 -->
    <property name="LOG_PATH" value="/var/log/myapp" />

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <RollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <FileNamePattern>${LOG_PATH}/myapp.%i.log.gz</FileNamePattern>
            <MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>
        </RollingPolicy>
        <TriggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>50MB</MaxFileSize>
        </TriggeringPolicy>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 设置根日志 -->
    <root level="info">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>
</configuration>

第三步:添加过滤器

创建一个名为 RequestLoggingFilter 的过滤器类,继承 OncePerRequestFilter 类,并重写 doFilterInternal 方法:

import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

public class RequestLoggingFilter extends OncePerRequestFilter {

    private static final String REQUEST_ID = "requestId";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        try {
            // 生成一个唯一的 requestId
            String requestId = UUID.randomUUID().toString();
            // 将 requestId 存储在 MDC 中
            MDC.put(REQUEST_ID, requestId);
            // 继续处理请求
            filterChain.doFilter(request, response);
        } finally {
            // 在请求结束后清除 requestId
            MDC.remove(REQUEST_ID);
        }
    }
}

第四步:配置过滤器

在 SpringBoot 应用的配置文件(比如 application.properties)中添加以下配置:

# 过滤器的顺序,数值越小越先执行
spring.web.filter.order=0
# 需要过滤的路径
spring.web.filter.pattern=/*

第五步:使用 requestId 输出日志

在需要输出日志的地方,使用 MDC.get(REQUEST_ID) 获取 requestId,并添加到日志中:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SomeClass {

    private static final Logger logger = LoggerFactory.getLogger(SomeClass.class);

    public void someMethod() {
        String requestId = MDC.get(REQUEST_ID);
        logger.info("Request {} - Start processing.", requestId);

        // 执行一些操作...

        logger.info("Request {} - Finish processing.", requestId);
    }
}

总结

通过使用 Logback 的 MDC,我们可以快速过滤出一次请求的所有日志。以上是实现的一种方式,你也可以根据自己的需求进行修改和扩展。

希望这篇博客对你了解 SpringBoot 如何快速过滤出一次请求的所有日志有所帮助!


全部评论: 0

    我有话说: