日志快速定位-traceId
最近跟微信对接的时候有个细节让我比较关注,他们在解决问题的时候会问你请求的traceId是什么,然后他们就能通过日志快速定位问题。然后我就想,我们能不能搞一个玩一下。
我们来想一下这个东西怎么实现。
- 我们要给每个请求分配一个单独的id
- 我们需要把这个id放到我们的日志中
- 我们还需要把这个id放到response中,可以被调用方感知到。
实现方案1
第一个方案比较简单,我们可以通过filter拦截所有请求,然后给每个请求分配一个traceId,然后把这个id放到response的header里,同时我们将traceId放到MCD中,然后log4j里读取输出就可以了
先写个Filter拦截请求
package com.example.demo2.filter;
import cn.hutool.core.util.IdUtil;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @AuThor zhangjiapeng
* @version V1.0
* @Title: TraceIdFilter
* @Description: 每个请求分配一个traceId
* @date 2022/1/13 10:22
*/
@WebFilter
@Component
public class TraceIdFilter extends OncePerRequestFilter {
private static final String TRACE_ID = "traceId";
@Override
public void destroy() {
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String traceId = IdUtil.fastSimpleUUID();
response.addHeader(TRACE_ID,traceId);
MDC.put(TRACE_ID,traceId);
filterChain.doFilter(request,response);
}
}
在logback中使用**%X{traceId}**读取MDC中的内容
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%X{traceId} ] [%thread][%file:%line] - %msg%n</Pattern>
</layout>
</encoder>
</appender>
效果如下:
2022-01-13 11:12:11.926 INFO [845ad00ad3014a2a9c70db003494c81f ] [http-nio-9090-exec-1][Demo2Application.java:29] - hello world
response
Content-Length: 11
Content-Type: text/html;charset=UTF-8
Date: Thu, 13 Jan 2022 03:12:11 GMT
traceId: 845ad00ad3014a2a9c70db003494c81f
实现方案2
因为我们接入了APM,APM中也有对应的traceId,所以我们能不能用APM的traceId呢。
首先引入APM工具包
<!-- https://mvnrepository.com/artifact/org.apache.skywalking/apm-toolkit-trace -->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.8.0</version>
</dependency>
改造一下TraceIdFilter
package com.example.demo2.filter;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author zhangjiapeng
* @version V1.0
* @Title: TraceIdFilter
* @Description:
* @date 2022/1/13 10:22
*/
@WebFilter
@Component
public class TraceIdFilter extends OncePerRequestFilter {
private static final String TRACE_ID = "traceId";
@Override
public void destroy() {
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String traceId = TraceContext.traceId();
response.addHeader(TRACE_ID,traceId);
MDC.put(TRACE_ID,traceId);
filterChain.doFilter(request,response);
}
}
效果如下:
2022-01-13 11:28:07.226 INFO [e9a1abc4800345c6af4ee926be230f15.43.16420444870010001 ] [http-nio-9090-exec-2][Demo2Application.java:29] - hello world
response
Content-Length: 11
Content-Type: text/html;charset=UTF-8
Date: Thu, 13 Jan 2022 03:28:07 GMT
traceId: e9a1abc4800345c6af4ee926be230f15.43.16420444870010001
看一下APM能不能搜到