You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:06:22