通过Go语言在Google PubSub中传播OpenTelemetry上下文

huangapple go评论75阅读模式
英文:

Propagate OpenTelemetry context through Google PubSub using Go

问题

使用Go语言,我该如何通过Google PubSub传播OpenTelemetry上下文?

英文:

Using Go, how can I propagate the OpenTelemetry context through Google PubSub?

答案1

得分: 1

为了实现这一点,我实现了TextMapCarrier接口

// TextMapCarrier是TextMapPropagator使用的存储介质。
type TextMapCarrier interface {
	Get(key string) string
	Set(key string, value string)
	Keys() []string
}

最终的代码如下:

package whatever

import (
	"cloud.google.com/go/pubsub"
	"context"
	"go.opentelemetry.io/otel"
)

const pubsubAttribPrefix = "whatever"

// PubsubMessageCarrier从pubsub.Message中注入和提取跟踪信息。
type PubsubMessageCarrier struct {
	msg *pubsub.Message
}

// NewPubsubMessageCarrier创建一个新的PubsubMessageCarrier。
func NewPubsubMessageCarrier(msg *pubsub.Message) PubsubMessageCarrier {
	return PubsubMessageCarrier{msg: msg}
}

// Get检索给定键的单个值。
func (c PubsubMessageCarrier) Get(key string) string {
	return c.msg.Attributes[pubsubAttribPrefix+"_"+key]
}

// Set设置一个属性。
func (c PubsubMessageCarrier) Set(key, val string) {
	c.msg.Attributes[pubsubAttribPrefix+"_"+key] = val
}

// Keys返回载体中所有键的切片。
func (c PubsubMessageCarrier) Keys() []string {
	i := 0
	out := make([]string, len(c.msg.Attributes))
	for k := range c.msg.Attributes {
		out[i] = k
		i++
	}
	return out
}

func PubSubMessageInjectContext(ctx context.Context, msg *pubsub.Message) {
	otel.GetTextMapPropagator().Inject(ctx, NewPubsubMessageCarrier(msg))
}

func PubSubMessageExtractContext(ctx context.Context, msg *pubsub.Message) context.Context {
	return otel.GetTextMapPropagator().Extract(ctx, NewPubsubMessageCarrier(msg))
}

现在只需将最新的contextPubSub消息传递给PubSubMessageInjectContext函数。这将向消息中注入数据。

在接收到的消息中,将新的context与接收到的message一起传递,以提取数据。然后使用输出的context创建一个新的span

注意,这并没有提供需要添加到指定span的属性,比如semconv.MessagingDestinationKindTopic

尽管基本功能已经实现,但这还没有经过实战测试。

致谢,来自Google开发团队的Alex Hong代码

英文:

To accomplish that I implemented the TextMapCarrier interface

// TextMapCarrier is the storage medium used by a TextMapPropagator.
type TextMapCarrier interface {
Get(key string) string
Set(key string, value string)
Keys() []string
}

The final code is:

package whatever
import (
"cloud.google.com/go/pubsub"
"context"
"go.opentelemetry.io/otel"
)
const pubsubAttribPrefix = "whatever"
// PubsubMessageCarrier injects and extracts traces from a pubsub.Message.
type PubsubMessageCarrier struct {
msg *pubsub.Message
}
// NewPubsubMessageCarrier creates a new PubsubMessageCarrier.
func NewPubsubMessageCarrier(msg *pubsub.Message) PubsubMessageCarrier {
return PubsubMessageCarrier{msg: msg}
}
// Get retrieves a single value for a given key.
func (c PubsubMessageCarrier) Get(key string) string {
return c.msg.Attributes[pubsubAttribPrefix+"_"+key]
}
// Set sets an attribute.
func (c PubsubMessageCarrier) Set(key, val string) {
c.msg.Attributes[pubsubAttribPrefix+"_"+key] = val
}
// Keys returns a slice of all keys in the carrier.
func (c PubsubMessageCarrier) Keys() []string {
i := 0
out := make([]string, len(c.msg.Attributes))
for k := range c.msg.Attributes {
out[i] = k
i++
}
return out
}
func PubSubMessageInjectContext(ctx context.Context, msg *pubsub.Message) {
otel.GetTextMapPropagator().Inject(ctx, NewPubsubMessageCarrier(msg))
}
func PubSubMessageExtractContext(ctx context.Context, msg *pubsub.Message) context.Context {
return otel.GetTextMapPropagator().Extract(ctx, NewPubsubMessageCarrier(msg))
}

So all that is left is to feed the latest context from the span and the PubSub message to PubSubMessageInjectContext. This will inject the data to the message.

On the other side feed the new context with the received message to extract the data. And use the output context to create a new span.

Note, this does not provide attributes that need to be added to the designated span. like semconv.MessagingDestinationKindTopic

It still not battle tested though the basics are here

Credit, Alex Hong from the Google dev team. code

huangapple
  • 本文由 发表于 2022年6月1日 18:41:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/72460454.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定