OpenTelemetry:基于Artemis消息系统的上下文传递实现咨询
Quarkus + Artemis + OpenTelemetry 链路追踪实现
核心结论
Quarkus 针对 ActiveMQ Artemis 的 OpenTelemetry 链路追踪自带自动传递机制,无需手动硬编码传递追踪ID,只要配置正确就能自动关联消息生产与消费的链路上下文。
具体实现步骤
1. 确保依赖齐全
在pom.xml(Maven)或build.gradle(Gradle)中添加核心依赖:
- OpenTelemetry 基础扩展:
quarkus-opentelemetry - Artemis 客户端扩展:
quarkus-artemis-jms或quarkus-artemis-core(根据你使用的API选择) - 可选(Jaeger后端):
quarkus-opentelemetry-exporter-jaeger
2. 配置自动追踪
在application.properties中添加必要配置:
# OpenTelemetry 基础配置 quarkus.opentelemetry.tracer.exporter.otlp.endpoint=http://你的Jaeger收集器地址:4317 quarkus.opentelemetry.tracer.sampler.type=always_on # Artemis 自动追踪开关(默认已开启,显式声明更清晰) quarkus.artemis.tracing.enabled=true
3. 验证链路关联
- 当你在HTTP请求上下文内发送Artemis消息时,OpenTelemetry会自动将当前追踪上下文(TraceID、SpanID)注入到消息的属性中(属性名符合OpenTelemetry规范,如
traceparent)。 - 消息消费端接收到消息后,Quarkus的Artemis扩展会自动读取这些属性并重建追踪上下文,Jaeger中就能看到从HTTP请求 → 消息生产 → 消息消费的完整链路。
手动处理场景(仅自动机制失效时)
如果因为自定义消息发送逻辑、手动创建JMS连接等特殊场景导致自动追踪失效,可手动传递上下文:
生产端手动注入追踪上下文
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.TextMapPropagator; import jakarta.enterprise.inject.Default; import jakarta.jms.Message; @Inject Tracer tracer; @Inject @Default TextMapPropagator textMapPropagator; public void sendMessageWithTrace(Message message) { Context currentContext = Context.current().with(Span.current()); // 将追踪上下文注入消息属性 textMapPropagator.inject(currentContext, message, (msg, key, value) -> { try { msg.setStringProperty(key, value); } catch (Exception e) { // 处理属性注入异常 } }); // 执行消息发送逻辑 }
消费端手动重建上下文
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.context.propagation.TextMapPropagator; import jakarta.enterprise.inject.Default; import jakarta.jms.Message; @Inject Tracer tracer; @Inject @Default TextMapPropagator textMapPropagator; public void consumeMessage(Message message) { // 从消息属性提取追踪上下文 Context extractedContext = textMapPropagator.extract(Context.current(), message, (msg, key) -> { try { return msg.getStringProperty(key); } catch (Exception e) { return null; } }); // 基于提取的上下文创建消费Span try (Scope scope = extractedContext.makeCurrent()) { Span span = tracer.spanBuilder("artemis-message-consume") .setSpanKind(Span.Kind.CONSUMER) .startSpan(); try (Scope spanScope = span.makeCurrent()) { // 执行消息处理逻辑 } finally { span.end(); } } }
常见问题排查
- 确保Quarkus版本在2.10及以上(更早版本对Artemis追踪的支持不完善)
- 检查Jaeger收集器地址配置正确,服务可正常访问
- 查看日志中是否有OpenTelemetry相关报错,比如上下文注入失败
内容的提问来源于stack exchange,提问作者Timz
相关产品推荐
相关产品推荐

