登录
首页 >  Golang >  Go问答

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

来源:stackoverflow

时间:2024-02-07 13:36:23 332浏览 收藏

在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是Golang学习者,那么本文《远程父跨度如何正确传递使用 NATS?》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

我在这个仓库中有一个虚拟示例

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

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/grpc 示例:


正确答案


go.opentelemetry.io/otel/[email protected]/trace.go 具有正确的上下文定义,您可以调用 marshaljson 并让它吐出一些看起来有用的内容,但事实是这样。没有等效的解组函数,输出是字符串,而内部格式是固定长度字节数组...

因此,要使其正常工作,只需将跟踪和跨度 id 转储为您喜欢的任何格式即可:

// attach telemetry headers
headers := 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()

好了,本文到此结束,带大家了解了《远程父跨度如何正确传递使用 NATS?》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>