OpenTelemetry-通过消息队列传播Trace信息
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 建议阅读,萌叔之前的文章 OpenTelemetry原理及实战 OpenTelemetry个性化采样-根据特定Header决定是否采样 1. 前言 一些复杂的业务场景,会出现任务被从接口提交,并在后台进行异步执行的情况。 这种情况下可能需要引入消息队列,涉及TraceContext通过消息进行跨节点(服务)的传播。 参考: W3C TraceContext 规范 这篇文章萌叔以RocketMQ来举例,看trace信息如何传递。 2. Golang中的实现 手动埋点追踪RocketMQ。 由于目前Golang的RocketMQ客户端缺乏像Java那样的自动埋点支持, 我们需要在消息发送和消费处理的关键位置手动创建Span。 2.1 消息发送方(Producer) import ( "context" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) func sendMessageWithTracing(ctx context.Context, producer rocketmq.Producer, topic, body string) error { tracer := otel.Tracer("rocketmq-producer") // 创建一个新的Span,代表本次发送操作。这里的ctx可能是来自HTTP请求或上游服务的上下文。 _, span := tracer.Start(ctx, "rocketmq.send", trace.WithAttributes( attribute.String("messaging.system", "rocketmq"), // 语义约定:消息系统 attribute.String("messaging.destination", topic), // 语义约定:主题 attribute.String("messaging.rocketmq.message.tags", "your_tag"), // RocketMQ特定属性 // 可以根据需要添加更多属性,如keys )) defer span.End() // 确保Span最终会结束 // 准备消息 msg := primitive.NewMessage(topic, []byte(body)) // 关键步骤:将追踪上下文注入到消息属性中 carrier := NewMessageCarrier(msg) // 你需要实现一个Carrier,见下文说明 otel.GetTextMapPropagator().Inject(span.SpanContext(), carrier) // 发送消息 _, err := producer.SendSync(msg) if err != nil { // 记录错误 span.RecordError(err) span.SetStatus(codes.Error, "SendSync failed") return err } span.SetStatus(codes.Ok, "Success") return nil } 关于Carrier:你需要实现propagation.TextMapCarrier接口,以便将追踪信息(TraceID, SpanID等) 以键值对的形式存入RocketMQ消息的用户属性中。一个简单的实现示例如下: ...