如何使用 NATS 正确传递远程父跨度?

我在这个 repo上有一个虚拟示例

我试图将当前跨度上下文传递给远程上下文,以便它可以正确显示跟踪,我所做的是:

go func() {

    _, span := otel.Tracer("natsC").Start(context.Background(), "publish")

    defer span.End()


    // send current span context as header

    spanCtx := span.SpanContext()

    spanJson, _ := spanCtx.MarshalJSON()

    log.Println(string(spanJson))

    msg, err := nc.RequestMsg(&nats.Msg{

        Subject: topic1, Data: []byte("whatever"), Header: nats.Header{

            "otelTrace": []string{string(spanJson)},

        },

    }, 2*time.Second)

    if L.IsError(err, `nc.Publish`) {

        return

    }

    log.Println(`reply:`, msg)

}()

在接收方服务器上:


_, err = nc.QueueSubscribe(topic1, "my-queue", func(msg *nats.Msg) {

    // take header and deserialize back to spanContext

    rsc := msg.Header.Get(`otelTrace`)

    parentSpanCtx := trace.SpanContext{}

    err := json.Unmarshal([]byte(rsc), &parentSpanCtx)

    L.IsError(err, `json.Unmarshal`)


    // use remote context as parent context

    _, span := otel.Tracer(`natsC`).Start(trace.ContextWithRemoteSpanContext(context.Background(), parentSpanCtx), topic1)

    defer span.End()


    data := string(msg.Data)

    fmt.Println(data)

    err = msg.Respond(msg.Data)

    L.IsError(err, `msg.Respond`) // ignore error

})

然后我使用这个命令运行它go run main.go natsC。


Jeager (localhost:16686) 上显示的两个跨度都是单独的跨度,不像 http/grpc 示例中那样相关,我应该修改什么才能将其视为父跨度?

http://img.mukewang.com/63f48341000100da22860391.jpg

等效的 http/grpc 示例:

http://img1.mukewang.com/63f483530001008722840535.jpg


Cats萌萌
浏览 130回答 1
1回答

慕斯709654

go.opentelemetry.io/otel/trace@v1.11.1/trace.go正确定义了上下文,您可以调用 MarshalJSON 并让它吐出一些看起来有用的东西,但这就是事情。没有等效的解组函数,输出是一个字符串,而内部格式是一个固定长度的字节数组......因此,要使其正常工作,只需将跟踪和跨度 ID 转储为您喜欢的任何格式:// Attach telemetry headersheaders := nats.Header{}headers.Set(otelTraceID, span.SpanContext().TraceID().String())headers.Set(otelSpanID, span.SpanContext().SpanID().String())然后在接收端,您必须手动将其重建为 SpanContext:func getParentContext(msg *nats.Msg) (spanContext trace.SpanContext, err error) {    var traceID trace.TraceID    traceID, err = trace.TraceIDFromHex(msg.Header.Get(otelTraceID))    if err != nil {        return spanContext, err    }    var spanID trace.SpanID    spanID, err = trace.SpanIDFromHex(msg.Header.Get(otelSpanID))    if err != nil {        return spanContext, err    }    var spanContextConfig trace.SpanContextConfig    spanContextConfig.TraceID = traceID    spanContextConfig.SpanID = spanID    spanContextConfig.TraceFlags = 01    spanContextConfig.Remote = true    spanContext = trace.NewSpanContext(spanContextConfig)    return spanContext, nil}然后实际使用它:remoteCtx, err := getParentContext(msg)if err != nil {    logrus.Fatal(err)}_, span := otel.Tracer(fqpn).Start(trace.ContextWithRemoteSpanContext(context.Background(), remoteCtx), msg.Subject)defer span.End()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go