背景:
最近搭建了ELK,发现原来的项目日志都没有全局id可以对每次的请求进行定位,所以想配置全局的日志id,对每次的请求都进行日志id的链路追踪
配置:
主要原理很简单,就是在每次的请求进入到控制器前,对请求进行拦截,给上下文中添加一个traceId(一般用uuid生成一个随机的就可以了),然后在日志配置文件中把这个traceId 打印出来,这样这个请求的所以相关日志都会带上这个全局日志id,我们就可以进行代码分析查看。
我用的是过滤器
package com.zzkj.web.filter;
import ch.qos.logback.classic.helpers.MDCInsertingServletFilter;
import com.zzkj.common.utils.StringUtils;
import org.slf4j.MDC;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;
@WebFilter(filterName = "LogFilter",urlPatterns = "/*")
public class LogFilter extends MDCInsertingServletFilter {
private String traceIdKey = "traceId";
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
//先看请求头有没有traceId参数,有就用请求头带的,这样的目的是可以实现分布式上下流的日志id统一跟踪
String traceId = ((HttpServletRequest) request).getHeader(traceIdKey);
if (StringUtils.isEmpty(traceId)) {
//随机生成日志id
traceId = UUID.randomUUID().toString().replaceAll("-","");
}
MDC.put(traceIdKey, traceId);
try {
super.doFilter(request, response, chain);
} finally {
//请求完成后移除
MDC.remove(traceIdKey);
}
}
}
}
日志配置文件中,修改下日志输出格式,输出加上traceId
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread]-[%X{traceId}] %-5level %logger{20} - [%method,%line] - %msg%n" />
效果:
完成