Kok*_*zzu 4 go nats.io opentracing open-telemetry
我有一个虚拟示例我在这个仓库
我尝试将当前跨度上下文传递给远程跨度上下文,以便它可以正确显示跟踪,我所做的:
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)
}()
Run Code Online (Sandbox Code Playgroud)
在接收服务器上:
_, 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
})
Run Code Online (Sandbox Code Playgroud)
然后我使用这个命令运行它go run main.go natsC。
两个跨度在 Jeager (localhost:16686) 上显示为单独的跨度,不像 http/grpc 示例中那样相关,我应该修改什么以便将其视为父跨度的子跨度?
等效的 http/grpc 示例:
小智 8
go.opentelemetry.io/otel/trace@v1.11.1/trace.go has the definitions for the context right, you can call MarshalJSON and have it spit something that looks useful but here's the thing. There is no equivalent unmarshalling function and the output is a string while the internal format is a fixed length byte array...
So to get it to work just dump the trace and span IDs into whatever format you like:
// Attach telemetry headers
headers := nats.Header{}
headers.Set(otelTraceID, span.SpanContext().TraceID().String())
headers.Set(otelSpanID, span.SpanContext().SpanID().String())
Run Code Online (Sandbox Code Playgroud)
Then on the receive side you have to rebuild it manually into a 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
}
Run Code Online (Sandbox Code Playgroud)
Then actually use it:
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()
Run Code Online (Sandbox Code Playgroud)