Commit ca36970ef430704ffbcfbbb9fcc2c0dee34ace86

Authored by YunaiV
1 parent ec3f7cbf

feat(tracer): 替换 OpenTracing 为 OpenTelemetry

- 引入 OpenTelemetry API/SDK/OTLP Exporter
- 移除 OpenTracing 与 SkyWalking trace toolkit 依赖
- 改造 Tracer 自动配置、业务链路切面和异常记录逻辑
- 使用 Span.current() 获取当前 traceId
- 保留 SkyWalking apm-toolkit-logback-1.x,避免影响日志链路输出
- 兼容 JDK8 servlet 依赖
yudao-dependencies/pom.xml
... ... @@ -40,7 +40,7 @@
40 40 <!-- 监控相关 -->
41 41 <skywalking.version>9.6.0</skywalking.version>
42 42 <spring-boot-admin.version>3.5.9</spring-boot-admin.version>
43   - <opentracing.version>0.33.0</opentracing.version>
  43 + <opentelemetry.version>1.39.0</opentelemetry.version>
44 44 <!-- Test 测试相关 -->
45 45 <podam.version>8.0.2.RELEASE</podam.version>
46 46 <jedis-mock.version>1.1.15</jedis-mock.version>
... ... @@ -343,44 +343,24 @@
343 343 </dependency>
344 344  
345 345 <dependency>
346   - <groupId>org.apache.skywalking</groupId>
347   - <artifactId>apm-toolkit-trace</artifactId>
348   - <version>${skywalking.version}</version>
349   - </dependency>
350   - <dependency>
351   - <groupId>org.apache.skywalking</groupId>
352   - <artifactId>apm-toolkit-logback-1.x</artifactId>
353   - <version>${skywalking.version}</version>
  346 + <groupId>io.opentelemetry</groupId>
  347 + <artifactId>opentelemetry-api</artifactId>
  348 + <version>${opentelemetry.version}</version>
354 349 </dependency>
355 350 <dependency>
356   - <groupId>org.apache.skywalking</groupId>
357   - <artifactId>apm-toolkit-opentracing</artifactId>
358   - <version>${skywalking.version}</version>
359   - <!-- <exclusions>-->
360   - <!-- <exclusion>-->
361   - <!-- <artifactId>opentracing-api</artifactId>-->
362   - <!-- <groupId>io.opentracing</groupId>-->
363   - <!-- </exclusion>-->
364   - <!-- <exclusion>-->
365   - <!-- <artifactId>opentracing-util</artifactId>-->
366   - <!-- <groupId>io.opentracing</groupId>-->
367   - <!-- </exclusion>-->
368   - <!-- </exclusions>-->
369   - </dependency>
370   - <dependency>
371   - <groupId>io.opentracing</groupId>
372   - <artifactId>opentracing-api</artifactId>
373   - <version>${opentracing.version}</version>
  351 + <groupId>io.opentelemetry</groupId>
  352 + <artifactId>opentelemetry-sdk</artifactId>
  353 + <version>${opentelemetry.version}</version>
374 354 </dependency>
375 355 <dependency>
376   - <groupId>io.opentracing</groupId>
377   - <artifactId>opentracing-util</artifactId>
378   - <version>${opentracing.version}</version>
  356 + <groupId>io.opentelemetry</groupId>
  357 + <artifactId>opentelemetry-exporter-otlp</artifactId>
  358 + <version>${opentelemetry.version}</version>
379 359 </dependency>
380 360 <dependency>
381   - <groupId>io.opentracing</groupId>
382   - <artifactId>opentracing-noop</artifactId>
383   - <version>${opentracing.version}</version>
  361 + <groupId>org.apache.skywalking</groupId>
  362 + <artifactId>apm-toolkit-logback-1.x</artifactId>
  363 + <version>${skywalking.version}</version>
384 364 </dependency>
385 365  
386 366 <dependency>
... ...
yudao-framework/yudao-common/pom.xml
... ... @@ -66,8 +66,8 @@
66 66  
67 67 <!-- 监控相关 -->
68 68 <dependency>
69   - <groupId>org.apache.skywalking</groupId>
70   - <artifactId>apm-toolkit-trace</artifactId>
  69 + <groupId>io.opentelemetry</groupId>
  70 + <artifactId>opentelemetry-api</artifactId>
71 71 </dependency>
72 72  
73 73 <!-- 工具类相关 -->
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java
1 1 package cn.iocoder.yudao.framework.common.util.monitor;
2 2  
3   -import org.apache.skywalking.apm.toolkit.trace.TraceContext;
  3 +import io.opentelemetry.api.trace.Span;
  4 +import io.opentelemetry.api.trace.SpanContext;
4 5  
5 6 /**
6 7 * 链路追踪工具类
... ... @@ -18,13 +19,14 @@ public class TracerUtils {
18 19 }
19 20  
20 21 /**
21   - * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。
  22 + * 获得链路追踪编号,直接返回 OpenTelemetry 的 TraceId。
22 23 * 如果不存在的话为空字符串!!!
23 24 *
24 25 * @return 链路追踪编号
25 26 */
26 27 public static String getTraceId() {
27   - return TraceContext.traceId();
  28 + SpanContext context = Span.current().getSpanContext();
  29 + return context.isValid() ? context.getTraceId() : "";
28 30 }
29 31  
30 32 }
... ...
yudao-framework/yudao-spring-boot-starter-monitor/pom.xml
... ... @@ -42,23 +42,23 @@
42 42  
43 43 <!-- 监控相关 -->
44 44 <dependency>
45   - <groupId>io.opentracing</groupId>
46   - <artifactId>opentracing-util</artifactId>
  45 + <groupId>io.opentelemetry</groupId>
  46 + <artifactId>opentelemetry-api</artifactId>
47 47 <optional>true</optional>
48 48 </dependency>
49 49 <dependency>
50   - <groupId>org.apache.skywalking</groupId>
51   - <artifactId>apm-toolkit-trace</artifactId>
  50 + <groupId>io.opentelemetry</groupId>
  51 + <artifactId>opentelemetry-sdk</artifactId>
52 52 <optional>true</optional>
53 53 </dependency>
54 54 <dependency>
55   - <groupId>org.apache.skywalking</groupId>
56   - <artifactId>apm-toolkit-logback-1.x</artifactId>
  55 + <groupId>io.opentelemetry</groupId>
  56 + <artifactId>opentelemetry-exporter-otlp</artifactId>
57 57 <optional>true</optional>
58 58 </dependency>
59 59 <dependency>
60 60 <groupId>org.apache.skywalking</groupId>
61   - <artifactId>apm-toolkit-opentracing</artifactId>
  61 + <artifactId>apm-toolkit-logback-1.x</artifactId>
62 62 <optional>true</optional>
63 63 </dependency>
64 64  
... ...
yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.tracer.config;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
  4 +import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect;
4 5 import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter;
  6 +import io.opentelemetry.api.GlobalOpenTelemetry;
  7 +import io.opentelemetry.api.trace.Tracer;
  8 +import org.springframework.beans.factory.annotation.Value;
5 9 import org.springframework.boot.autoconfigure.AutoConfiguration;
6 10 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  11 +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7 12 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
8 13 import org.springframework.boot.context.properties.EnableConfigurationProperties;
9 14 import org.springframework.boot.web.servlet.FilterRegistrationBean;
... ... @@ -16,28 +21,27 @@ import org.springframework.context.annotation.Bean;
16 21 */
17 22 @AutoConfiguration
18 23 @ConditionalOnClass(name = {
19   - "org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer", // 来自 apm-toolkit-opentracing.jar
20   -// "io.opentracing.Tracer", // 来自 opentracing-api.jar
  24 + "io.opentelemetry.api.trace.Tracer", // 来自 opentelemetry-api.jar
21 25 "jakarta.servlet.Filter"
22 26 })
23 27 @EnableConfigurationProperties(TracerProperties.class)
24 28 @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
25 29 public class YudaoTracerAutoConfiguration {
26 30  
27   - // TODO @芋艿:skywalking 不兼容最新的 opentracing 版本。同时,opentracing 也停止了维护,尬住了!后续换 opentelemetry 即可!
28   -// @Bean
29   -// public BizTraceAspect bizTracingAop() {
30   -// return new BizTraceAspect(tracer());
31   -// }
32   -//
33   -// @Bean
34   -// public Tracer tracer() {
35   -// // 创建 SkywalkingTracer 对象
36   -// SkywalkingTracer tracer = new SkywalkingTracer();
37   -// // 设置为 GlobalTracer 的追踪器
38   -// GlobalTracer.registerIfAbsent(tracer);
39   -// return tracer;
40   -// }
  31 + @Value("${spring.application.name:application}")
  32 + private String applicationName;
  33 +
  34 + @Bean
  35 + @ConditionalOnMissingBean
  36 + public Tracer tracer() {
  37 + return GlobalOpenTelemetry.getTracer(applicationName);
  38 + }
  39 +
  40 + @Bean
  41 + @ConditionalOnMissingBean
  42 + public BizTraceAspect bizTracingAop(Tracer tracer) {
  43 + return new BizTraceAspect(tracer);
  44 + }
41 45  
42 46 /**
43 47 * 创建 TraceFilter 过滤器,响应 header 设置 traceId
... ...
yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/aop/BizTraceAspect.java
... ... @@ -5,9 +5,9 @@ import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.tracer.core.annotation.BizTrace;
6 6 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
7 7 import cn.iocoder.yudao.framework.tracer.core.util.TracerFrameworkUtils;
8   -import io.opentracing.Span;
9   -import io.opentracing.Tracer;
10   -import io.opentracing.tag.Tags;
  8 +import io.opentelemetry.api.trace.Span;
  9 +import io.opentelemetry.api.trace.Tracer;
  10 +import io.opentelemetry.context.Scope;
11 11 import lombok.AllArgsConstructor;
12 12 import lombok.extern.slf4j.Slf4j;
13 13 import org.aspectj.lang.ProceedingJoinPoint;
... ... @@ -36,10 +36,10 @@ public class BizTraceAspect {
36 36 public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable {
37 37 // 创建 span
38 38 String operationName = getOperationName(joinPoint, trace);
39   - Span span = tracer.buildSpan(operationName)
40   - .withTag(Tags.COMPONENT.getKey(), "biz")
41   - .start();
42   - try {
  39 + Span span = tracer.spanBuilder(operationName)
  40 + .setAttribute("component", "biz")
  41 + .startSpan();
  42 + try (Scope ignored = span.makeCurrent()) {
43 43 // 执行原有方法
44 44 return joinPoint.proceed();
45 45 } catch (Throwable throwable) {
... ... @@ -49,7 +49,7 @@ public class BizTraceAspect {
49 49 // 设置 Span 的 biz 属性
50 50 setBizTag(span, joinPoint, trace);
51 51 // 完成 Span
52   - span.finish();
  52 + span.end();
53 53 }
54 54 }
55 55  
... ... @@ -67,8 +67,8 @@ public class BizTraceAspect {
67 67 private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) {
68 68 try {
69 69 Map<String, Object> result = SpringExpressionUtils.parseExpressions(joinPoint, asList(trace.type(), trace.id()));
70   - span.setTag(BizTrace.TYPE_TAG, MapUtil.getStr(result, trace.type()));
71   - span.setTag(BizTrace.ID_TAG, MapUtil.getStr(result, trace.id()));
  70 + span.setAttribute(BizTrace.TYPE_TAG, MapUtil.getStr(result, trace.type()));
  71 + span.setAttribute(BizTrace.ID_TAG, MapUtil.getStr(result, trace.id()));
72 72 } catch (Exception ex) {
73 73 log.error("[setBizTag][解析 bizType 与 bizId 发生异常]", ex);
74 74 }
... ...
yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/util/TracerFrameworkUtils.java
1 1 package cn.iocoder.yudao.framework.tracer.core.util;
2 2  
3   -import io.opentracing.Span;
4   -import io.opentracing.tag.Tags;
  3 +import io.opentelemetry.api.trace.Span;
  4 +import io.opentelemetry.api.trace.StatusCode;
5 5  
6 6 import java.io.PrintWriter;
7 7 import java.io.StringWriter;
8   -import java.util.HashMap;
9   -import java.util.Map;
10 8  
11 9 /**
12 10 * 链路追踪 Util
... ... @@ -22,25 +20,24 @@ public class TracerFrameworkUtils {
22 20 * @param span Span
23 21 */
24 22 public static void onError(Throwable throwable, Span span) {
25   - Tags.ERROR.set(span, Boolean.TRUE);
26   - if (throwable != null) {
27   - span.log(errorLogs(throwable));
  23 + // 忽略无效 Span
  24 + if (span == null || !span.getSpanContext().isValid()) {
  25 + return;
  26 + }
  27 + // 标记异常状态
  28 + if (throwable == null) {
  29 + span.setStatus(StatusCode.ERROR);
  30 + return;
28 31 }
29   - }
30 32  
31   - private static Map<String, Object> errorLogs(Throwable throwable) {
32   - Map<String, Object> errorLogs = new HashMap<String, Object>(10);
33   - errorLogs.put("event", Tags.ERROR.getKey());
34   - errorLogs.put("error.object", throwable);
35   - errorLogs.put("error.kind", throwable.getClass().getName());
  33 + // 记录异常事件
  34 + span.recordException(throwable);
36 35 String message = throwable.getCause() != null ? throwable.getCause().getMessage() : throwable.getMessage();
37   - if (message != null) {
38   - errorLogs.put("message", message);
39   - }
  36 + span.setStatus(StatusCode.ERROR, message == null ? "" : message);
  37 + // 记录异常堆栈
40 38 StringWriter sw = new StringWriter();
41 39 throwable.printStackTrace(new PrintWriter(sw));
42   - errorLogs.put("stack", sw.toString());
43   - return errorLogs;
  40 + span.setAttribute("error.stack", sw.toString());
44 41 }
45 42  
46 43 }
... ...