web 请求日志追踪(traceID)提升运维效率
需求:
Spring web项目需要一个唯一id,追踪同一请求日志打印,提升运维效率。
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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic 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,避免影响后续请求}}@Overridepublic 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>