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,7 +40,7 @@
40 <!-- 监控相关 --> 40 <!-- 监控相关 -->
41 <skywalking.version>9.6.0</skywalking.version> 41 <skywalking.version>9.6.0</skywalking.version>
42 <spring-boot-admin.version>3.5.9</spring-boot-admin.version> 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 <!-- Test 测试相关 --> 44 <!-- Test 测试相关 -->
45 <podam.version>8.0.2.RELEASE</podam.version> 45 <podam.version>8.0.2.RELEASE</podam.version>
46 <jedis-mock.version>1.1.15</jedis-mock.version> 46 <jedis-mock.version>1.1.15</jedis-mock.version>
@@ -343,44 +343,24 @@ @@ -343,44 +343,24 @@
343 </dependency> 343 </dependency>
344 344
345 <dependency> 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 </dependency> 349 </dependency>
355 <dependency> 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 </dependency> 354 </dependency>
375 <dependency> 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 </dependency> 359 </dependency>
380 <dependency> 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 </dependency> 364 </dependency>
385 365
386 <dependency> 366 <dependency>
yudao-framework/yudao-common/pom.xml
@@ -66,8 +66,8 @@ @@ -66,8 +66,8 @@
66 66
67 <!-- 监控相关 --> 67 <!-- 监控相关 -->
68 <dependency> 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 </dependency> 71 </dependency>
72 72
73 <!-- 工具类相关 --> 73 <!-- 工具类相关 -->
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java
1 package cn.iocoder.yudao.framework.common.util.monitor; 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,13 +19,14 @@ public class TracerUtils {
18 } 19 }
19 20
20 /** 21 /**
21 - * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。 22 + * 获得链路追踪编号,直接返回 OpenTelemetry 的 TraceId。
22 * 如果不存在的话为空字符串!!! 23 * 如果不存在的话为空字符串!!!
23 * 24 *
24 * @return 链路追踪编号 25 * @return 链路追踪编号
25 */ 26 */
26 public static String getTraceId() { 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,23 +42,23 @@
42 42
43 <!-- 监控相关 --> 43 <!-- 监控相关 -->
44 <dependency> 44 <dependency>
45 - <groupId>io.opentracing</groupId>  
46 - <artifactId>opentracing-util</artifactId> 45 + <groupId>io.opentelemetry</groupId>
  46 + <artifactId>opentelemetry-api</artifactId>
47 <optional>true</optional> 47 <optional>true</optional>
48 </dependency> 48 </dependency>
49 <dependency> 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 <optional>true</optional> 52 <optional>true</optional>
53 </dependency> 53 </dependency>
54 <dependency> 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 <optional>true</optional> 57 <optional>true</optional>
58 </dependency> 58 </dependency>
59 <dependency> 59 <dependency>
60 <groupId>org.apache.skywalking</groupId> 60 <groupId>org.apache.skywalking</groupId>
61 - <artifactId>apm-toolkit-opentracing</artifactId> 61 + <artifactId>apm-toolkit-logback-1.x</artifactId>
62 <optional>true</optional> 62 <optional>true</optional>
63 </dependency> 63 </dependency>
64 64
yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java
1 package cn.iocoder.yudao.framework.tracer.config; 1 package cn.iocoder.yudao.framework.tracer.config;
2 2
3 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; 3 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
  4 +import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect;
4 import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter; 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 import org.springframework.boot.autoconfigure.AutoConfiguration; 9 import org.springframework.boot.autoconfigure.AutoConfiguration;
6 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 10 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  11 +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 12 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
8 import org.springframework.boot.context.properties.EnableConfigurationProperties; 13 import org.springframework.boot.context.properties.EnableConfigurationProperties;
9 import org.springframework.boot.web.servlet.FilterRegistrationBean; 14 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -16,28 +21,27 @@ import org.springframework.context.annotation.Bean; @@ -16,28 +21,27 @@ import org.springframework.context.annotation.Bean;
16 */ 21 */
17 @AutoConfiguration 22 @AutoConfiguration
18 @ConditionalOnClass(name = { 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 "jakarta.servlet.Filter" 25 "jakarta.servlet.Filter"
22 }) 26 })
23 @EnableConfigurationProperties(TracerProperties.class) 27 @EnableConfigurationProperties(TracerProperties.class)
24 @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) 28 @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
25 public class YudaoTracerAutoConfiguration { 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 * 创建 TraceFilter 过滤器,响应 header 设置 traceId 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,9 +5,9 @@ import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.tracer.core.annotation.BizTrace; 5 import cn.iocoder.yudao.framework.tracer.core.annotation.BizTrace;
6 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; 6 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
7 import cn.iocoder.yudao.framework.tracer.core.util.TracerFrameworkUtils; 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 import lombok.AllArgsConstructor; 11 import lombok.AllArgsConstructor;
12 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
13 import org.aspectj.lang.ProceedingJoinPoint; 13 import org.aspectj.lang.ProceedingJoinPoint;
@@ -36,10 +36,10 @@ public class BizTraceAspect { @@ -36,10 +36,10 @@ public class BizTraceAspect {
36 public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable { 36 public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable {
37 // 创建 span 37 // 创建 span
38 String operationName = getOperationName(joinPoint, trace); 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 return joinPoint.proceed(); 44 return joinPoint.proceed();
45 } catch (Throwable throwable) { 45 } catch (Throwable throwable) {
@@ -49,7 +49,7 @@ public class BizTraceAspect { @@ -49,7 +49,7 @@ public class BizTraceAspect {
49 // 设置 Span 的 biz 属性 49 // 设置 Span 的 biz 属性
50 setBizTag(span, joinPoint, trace); 50 setBizTag(span, joinPoint, trace);
51 // 完成 Span 51 // 完成 Span
52 - span.finish(); 52 + span.end();
53 } 53 }
54 } 54 }
55 55
@@ -67,8 +67,8 @@ public class BizTraceAspect { @@ -67,8 +67,8 @@ public class BizTraceAspect {
67 private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) { 67 private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) {
68 try { 68 try {
69 Map<String, Object> result = SpringExpressionUtils.parseExpressions(joinPoint, asList(trace.type(), trace.id())); 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 } catch (Exception ex) { 72 } catch (Exception ex) {
73 log.error("[setBizTag][解析 bizType 与 bizId 发生异常]", ex); 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 package cn.iocoder.yudao.framework.tracer.core.util; 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 import java.io.PrintWriter; 6 import java.io.PrintWriter;
7 import java.io.StringWriter; 7 import java.io.StringWriter;
8 -import java.util.HashMap;  
9 -import java.util.Map;  
10 8
11 /** 9 /**
12 * 链路追踪 Util 10 * 链路追踪 Util
@@ -22,25 +20,24 @@ public class TracerFrameworkUtils { @@ -22,25 +20,24 @@ public class TracerFrameworkUtils {
22 * @param span Span 20 * @param span Span
23 */ 21 */
24 public static void onError(Throwable throwable, Span span) { 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 String message = throwable.getCause() != null ? throwable.getCause().getMessage() : throwable.getMessage(); 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 StringWriter sw = new StringWriter(); 38 StringWriter sw = new StringWriter();
41 throwable.printStackTrace(new PrintWriter(sw)); 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 }