无需Otel Java Agent,Spring Boot中IBM MQ/JMS生产者埋点咨询
解决方案:IBM MQ 生产者的 OpenTelemetry 埋点实现
核心思路
你不需要从零实现 JMS 生产者,利用 OpenTelemetry API 和 @WithSpan 注解即可完成埋点,同时满足不向 MQ 消息传播上下文但仍导出追踪数据的需求。关键是确保 MQ 发送的 Span 作为 Kafka 消费 Span 的子 Span 关联起来。
具体实现步骤
1. 优化 Kafka 消费者的上下文传递
你的 Kafka 消费者代码已正确提取消息中的追踪上下文并设置为当前上下文,可简化实现——无需手动传递 extractedContext 到 send 方法,因为 Scope 已让该上下文在当前线程生效:
@KafkaListener( topics = "#{'${spring.kafka.topics}'.split(',')}", groupId = "my-group-id") public void subscribe(MessageHeaders messageHeaders, String message) { Context extractedContext = GlobalOpenTelemetry.get() .getPropagators() .getTextMapPropagator() .extract(Context.current(), messageHeaders, new KafkaTextMapGetter()); // 自定义TextMapGetter保持不变 try (Scope scope = extractedContext.makeCurrent()) { // 直接调用send,当前线程上下文已关联Kafka消费Span ibmMqService.send(message); } }
2. 完善 MQ 发送方法的埋点
使用 @WithSpan 注解会自动创建新 Span,且由于当前线程上下文已绑定 Kafka 消费的上下文,这个新 Span 会自动成为 Kafka 消费 Span 的子 Span。因你不需要向 MQ 消息传播上下文,无需调用 TextMapPropagator.inject:
import org.springframework.jms.core.JmsTemplate; import io.opentelemetry.extension.annotations.WithSpan; ... @WithSpan(value = "ibm-mq-send") // 自定义Span名称,便于Jaeger中识别 public void send(String message) { jmsTemplate.send(session -> session.createTextMessage(message)); }
3. (可选)若后续需向 MQ 消息传播上下文
如果之后需要将追踪上下文注入到 MQ 消息头中,可使用 TextMapPropagator.inject,此时载体(carrier)为 JMS Message 实例,需实现对应的 TextMapSetter:
// 自定义TextMapSetter,用于将追踪上下文注入JMS消息头 public class JmsMessageTextMapSetter implements TextMapSetter<Message> { @Override public void set(Message carrier, String key, String value) { try { carrier.setStringProperty(key, value); } catch (JMSException e) { // 异常处理,如日志记录 } } } // 在send方法中注入上下文(仅当需要传播时使用) @WithSpan(value = "ibm-mq-send") public void send(String message) { jmsTemplate.send(session -> { TextMessage textMessage = session.createTextMessage(message); GlobalOpenTelemetry.get() .getPropagators() .getTextMapPropagator() .inject(Context.current(), textMessage, new JmsMessageTextMapSetter()); return textMessage; }); }
关键说明
@WithSpan会自动基于当前线程上下文创建子 Span,只要 Kafka 消费者的Scope生效,MQ 发送 Span 就会与 Kafka 消费 Span 正确关联。- 不调用
inject方法即可避免将追踪信息写入 MQ 消息头,满足你不传播上下文的需求。 - 无需替换
com.ibm.mq:mq-jms-spring-boot-starter,直接使用现有JmsTemplate即可完成埋点。
内容的提问来源于stack exchange,提问作者ALVIN
相关产品推荐
相关产品推荐

