Commit f0a633373ece16ec66230886d67627b8a5cc047f

Authored by dark
1 parent cc156f6e

调整获取traceId的优先级

src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java
... ... @@ -5,7 +5,9 @@ import cn.hutool.extra.spring.SpringUtil;
5 5 import cn.iocoder.dashboard.framework.tracer.core.ITrace;
6 6 import org.apache.skywalking.apm.toolkit.trace.TraceContext;
7 7  
  8 +import java.util.Map;
8 9 import java.util.UUID;
  10 +import java.util.concurrent.ConcurrentHashMap;
9 11  
10 12 /**
11 13 * 链路追踪工具类
... ... @@ -15,6 +17,36 @@ import java.util.UUID;
15 17 public class TracerUtils {
16 18  
17 19 /**
  20 + * 维护请求线程对应的TraceId
  21 + */
  22 + private final static Map<Thread, String> threadTraceIdMap = new ConcurrentHashMap<>();
  23 +
  24 + /**
  25 + * 保存链路流水号
  26 + *
  27 + * @param traceId 链路流水号
  28 + */
  29 + public static void saveThreadTraceId(String traceId) {
  30 + threadTraceIdMap.put(Thread.currentThread(), traceId);
  31 + }
  32 +
  33 + /**
  34 + * 根据线程获取链路流水号
  35 + *
  36 + * @return 链路流水号
  37 + */
  38 + public static String getThreadTraceId() {
  39 + return threadTraceIdMap.get(Thread.currentThread());
  40 + }
  41 +
  42 + /**
  43 + * 根据线程删除链路流水
  44 + */
  45 + public static void deleteThreadTraceId() {
  46 + threadTraceIdMap.remove(Thread.currentThread());
  47 + }
  48 +
  49 + /**
18 50 * 私有化构造方法
19 51 */
20 52 private TracerUtils() {
... ... @@ -26,10 +58,27 @@ public class TracerUtils {
26 58 * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
27 59 * <p>
28 60 * 默认情况下,我们使用 Apache SkyWalking 的 traceId 作为链路追踪编号。当然,可能会存在并未引入 Skywalking 的情况,此时使用 UUID 。
  61 + * 方法获取顺序: skywalking - > map -> 扩展接口 -> default
  62 + * 项目整体获取traceId的优先级 skywalking > 自定义实现接口 > 默认
  63 + * map中的traceId 当且仅当其他情况为产生时才会出现.
29 64 *
30 65 * @return 链路追踪编号
31 66 */
32 67 public static String getTraceId() {
  68 + String traceId;
  69 + // 通过 SkyWalking 获取链路编号
  70 + try {
  71 + traceId = TraceContext.traceId();
  72 + if (StrUtil.isNotBlank(traceId)) {
  73 + return traceId;
  74 + }
  75 + } catch (Throwable ignore) {
  76 + }
  77 + // 尝试从map中获取
  78 + traceId = threadTraceIdMap.get(Thread.currentThread());
  79 + if (StrUtil.isNotBlank(traceId)) {
  80 + return traceId;
  81 + }
33 82 // 通过自定义扩展的tracer产生traceId, 在Spring容器加载完成前会获取不到对应的Bean
34 83 ITrace tracer = null;
35 84 try {
... ... @@ -42,20 +91,20 @@ public class TracerUtils {
42 91 } catch (Throwable ignored) {
43 92 }
44 93 }
45   - // 通过 SkyWalking 获取链路编号
46   - try {
47   - String traceId = TraceContext.traceId();
48   - if (StrUtil.isNotBlank(traceId)) {
49   - return traceId;
50   - }
51   - } catch (Throwable ignore) {
52   - }
53 94 // TODO 芋艿 多次调用会问题
54 95  
55 96 return defaultTraceId();
56 97 }
57 98  
58 99 /**
  100 + * 仅仅获取Skywalking 中的traceId, 若无skywalking,则会返回""
  101 + *
  102 + * @return skywalking 的traceId
  103 + */
  104 + public static String getSkywalkingTraceId() {
  105 + return TraceContext.traceId();
  106 + }
  107 + /**
59 108 * 从Spring 容器中获取 ITrace 类,返回可以为null
60 109 *
61 110 * @return ITrace
... ...
src/main/java/cn/iocoder/dashboard/framework/tracer/filter/SpringMvcTraceFilter.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.tracer.filter;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.aspectj.lang.annotation.Aspect;
  7 +import org.aspectj.lang.annotation.Before;
  8 +import org.aspectj.lang.annotation.Pointcut;
  9 +import org.springframework.beans.factory.annotation.Value;
  10 +import org.springframework.context.annotation.Configuration;
  11 +import org.springframework.lang.Nullable;
  12 +import org.springframework.stereotype.Component;
  13 +import org.springframework.web.servlet.AsyncHandlerInterceptor;
  14 +import org.springframework.web.servlet.HandlerInterceptor;
  15 +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
  16 +
  17 +import javax.servlet.*;
  18 +import javax.servlet.http.HttpServletRequest;
  19 +import javax.servlet.http.HttpServletResponse;
  20 +import java.io.IOException;
  21 +
  22 +/**
  23 + * 对Spring Mvc 的请求拦截, 添加traceId.
  24 + *
  25 + * @author mashu
  26 + */
  27 +
  28 +@Slf4j
  29 +@Component
  30 +public class SpringMvcTraceFilter implements HandlerInterceptor {
  31 +
  32 + @Value("${cn.iocoder.tracer.name:global-trace-id}")
  33 + private String traceIdName;
  34 +
  35 + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  36 + // 请求中traceId
  37 + String reqTraceId = (String)request.getAttribute(traceIdName);
  38 + // skywalking中的traceId
  39 + String skywalkingTraceId = TracerUtils.getSkywalkingTraceId();
  40 + String traceId ;
  41 + if (null == reqTraceId && StrUtil.isBlank(skywalkingTraceId)) {
  42 + // 两者皆空,添加默认的.
  43 + traceId = TracerUtils.getTraceId();
  44 + request.setAttribute(traceIdName, traceId);
  45 + } else if (null == reqTraceId && StrUtil.isNotBlank(skywalkingTraceId)){
  46 + // 若请求空,则添加,为没有skywalking的系统添加一个TraceId
  47 + traceId = skywalkingTraceId;
  48 + request.setAttribute(traceIdName, traceId);
  49 + } else if (null != reqTraceId && StrUtil.isBlank(skywalkingTraceId)) {
  50 + // 请求非空, skywalking为空
  51 + traceId = reqTraceId;
  52 + } else {
  53 + // 两者皆非空,不动请求头
  54 + traceId = skywalkingTraceId;
  55 + }
  56 + TracerUtils.saveThreadTraceId(traceId);
  57 + log.debug("请求进入,添加traceId[{}]", traceId);
  58 + return true;
  59 + }
  60 +
  61 + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
  62 + // 请求结束,删除本地的链路流水号
  63 + log.debug("请求结束,删除traceId[{}]", TracerUtils.getTraceId());
  64 + TracerUtils.deleteThreadTraceId();
  65 +
  66 + }
  67 +
  68 +}
... ...
src/main/java/cn/iocoder/dashboard/framework/tracer/filter/WebConfig.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.tracer.filter;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.stereotype.Component;
  6 +import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  7 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  8 +
  9 +import javax.annotation.Resource;
  10 +
  11 +@Configuration
  12 +@Component
  13 +public class WebConfig implements WebMvcConfigurer {
  14 +
  15 + @Resource
  16 + private SpringMvcTraceFilter springMvcTraceFilter;
  17 +
  18 + @Override
  19 + public void addInterceptors(InterceptorRegistry registry) {
  20 + registry.addInterceptor(this.springMvcTraceFilter).addPathPatterns("/**");
  21 + }
  22 +
  23 +}
0 24 \ No newline at end of file
... ...