Commit ca36970ef430704ffbcfbbb9fcc2c0dee34ace86
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 依赖
Showing
7 changed files
with
72 additions
and
89 deletions
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 | } |