web 请求日志追踪(traceID)提升运维效率

需求:
Spring web项目需要一个唯一id,追踪同一请求日志打印,提升运维效率。
接口请求日志可以单独记录到一个日志文件中,实现方案参考:记录web应用请求日志

1.使用MDC

MDC(Mapped Diagnostic Context)可以帮助你在日志中加入唯一的 traceId,从而在分布式系统中追踪请求

import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;

@Component
public class TraceIdFilter implements Filter {
    
    

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
    
    
        String traceId = UUID.randomUUID().toString();
        MDC.put("traceId", traceId);

        try {
    
    
            chain.doFilter(request, response);
        } finally {
    
    
            MDC.clear(); // 清除 MDC 中的 traceId,避免影响后续请求
        }
    }

    @Override
    public void destroy() {
    
    }
}

2.日志打印

logback-spring.xml


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 从spring 资源文件读取属性 -->
    <springProperty scope="context" name="log.path" source="log.path" defaultValue="logs"/>
    <springProperty scope="context" name="log.env" source="env.name" defaultValue="dev"/>
    <springProperty scope="context" name="log.service.name" source="spring.application.name"  defaultValue="nanWeb"/>

    <!-- appender是configuration的子节点,是负责写日志的组件。 -->
    <!-- ConsoleAppender:把日志输出到控制台 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--   %d表示日期时间,默认是yyyy-MM-dd HH:mm:ss -->
            <!--   %t 表示线程名称;  %-5level表示日志级别; %X{traceId} 表示MDC中的traceID;-->
            <!-- %logger{36} ; .%M表示记录方法名称; %file:%line 表示日志记录方法所在的文件名和行号; %msg:表示日志消息; %n 换行符  -->
            <pattern>%d [%t] %-5level | %X{traceId} | %logger{36}.%M\(%file:%line\) - %msg%n</pattern>
            <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
    <!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是demo.log -->
    <!--             2.如果日期没有发生变化,但是当前日志的文件大小超过1KB时,对当前日志进行分割 重命名-->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <File>${log.path}/${log.service.name}-${log.env}.log</File>
        <!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
        <!-- TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
            <!-- 定义归档文件名 -->
            <fileNamePattern>${log.path}/arch/${log.service.name}-${log.env}.%d.%i.log</fileNamePattern>
            <!-- 每产生一个日志文件,该日志文件的保存期限为3天 -->
            <maxHistory>3</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成1KB看效果 -->
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <!-- pattern节点,用来设置日志的输入格式 -->
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level | %X{traceId} | %logger{36}.%M\(%file:%line\) - %msg%n
            </pattern>
            <!-- 记录日志的编码:此处设置字符集 - -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 定义根日志级别为 INFO -->
    <root level="INFO">
        <!-- 将根日志连接到名为 STDOUT 的 appender -->
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>

猜你喜欢

转载自blog.csdn.net/code_nn/article/details/143214803