Quarkus Netty(Vert.x)集成X-Ray追踪DynamoDB请求异常排查
解决Quarkus Reactive(Netty)中X-Ray追踪DynamoDB调用的问题
问题根源分析
你当前的核心问题是混合使用了AWS X-Ray原生SDK与Quarkus OpenTelemetry(OTel)两套追踪体系:
- Quarkus的DynamoDB扩展通过OTel生成追踪数据
- 你配置的
TracingInterceptor是基于X-Ray自身的上下文体系,与OTel上下文不共享,导致DynamoDB子段无法找到父Span;添加Vert.x Handler后异常消失,但因体系冲突仍无法生成关联的DynamoDB追踪节点。
分步解决方案
1. 统一追踪方案:移除X-Ray SDK依赖与冲突配置
删除与X-Ray原生SDK相关的内容,完全基于Quarkus OTel体系实现追踪:
- 移除Gradle依赖中的
com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 - 删除
application.properties中的quarkus.dynamodb.interceptors=com.amazonaws.xray.interceptors.TracingInterceptor - 保留
quarkus.dynamodb.telemetry.enabled=true(Quarkus会自动通过OTel追踪DynamoDB调用)
2. 实现Vert.x入站请求的根Span追踪(替代Servlet Filter)
Quarkus Reactive基于Vert.x,需通过OTel为所有入站请求创建根Span,确保DynamoDB调用能关联到父追踪上下文:
import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.Tracer import io.opentelemetry.context.Context import io.opentelemetry.context.Scope import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import io.vertx.ext.web.RoutingContext import jakarta.enterprise.context.ApplicationScoped import jakarta.inject.Inject @ApplicationScoped class TracingHandler { @Inject lateinit var tracer: Tracer fun handle(rc: RoutingContext) { val request = rc.request() val spanName = "${request.method()} ${request.path()}" // 创建根Span并填充HTTP语义属性 val span = tracer.spanBuilder(spanName) .setAttribute(SemanticAttributes.HTTP_METHOD, request.method().name()) .setAttribute(SemanticAttributes.HTTP_URL, request.absoluteURI()) .setAttribute(SemanticAttributes.HTTP_SCHEME, request.scheme()) .startSpan() try { // 将Span绑定到当前上下文 Context.current().with(span).makeCurrent().use { _: Scope -> // 请求结束时关闭Span并记录状态码 rc.addEndHandler { _ -> span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, rc.response().statusCode()) span.end() } rc.next() } } catch (e: Exception) { span.recordException(e) span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, 500) span.end() throw e } } }
注册该Handler到所有路由(确保优先级最高):
import io.quarkus.vertx.web.RouteFilter import jakarta.inject.Inject class RoutesConfig { @Inject lateinit var tracingHandler: TracingHandler @RouteFilter(100) fun applyTracingFilter(rc: RoutingContext) { tracingHandler.handle(rc) } }
3. 验证OTEL Collector配置
确保ECS中的OTEL Collector正确将OTel Span转换为X-Ray格式并发送,检查ecs-xray.yaml配置:
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: awsxray: exporters: awsxray: region: eu-central-1 service: pipelines: traces: receivers: [otlp] processors: [batch, awsxray] exporters: [awsxray]
你的IAM权限配置已经满足要求(包含xray:PutTraceSegments和xray:PutTelemetryRecords),无需修改。
4. 调试与验证
开启OTel调试日志,确认DynamoDB Span是否生成:
quarkus.log.category."io.opentelemetry".level=DEBUG quarkus.log.category."io.quarkus.opentelemetry".level=DEBUG
查看日志中是否存在DynamoDB相关的Span创建、导出记录,同时检查X-Ray控制台是否生成完整的追踪链路。
内容的提问来源于stack exchange,提问作者jDudek
相关产品推荐
相关产品推荐

