我正在构建一个简单的客户端服务器应用程序,我想跟踪客户端执行到调用第二个服务器微服务的服务器微服务。
简单来说,并不比 CLI -> ServiceA -> ServiceB 复杂。
我面临的挑战是如何序列化上下文 - 我看过的大多数文档似乎都进行某种形式的自动 HTTP 标头注入(例如https://opentelemetry.lightstep.com/core-concepts/context- propagation/ ) ,但我无权访问它。我需要序列化(我认为)客户端中跟踪/跨度的上下文并将其推送到服务器,我将在服务器上重新水化它。(请注意,我希望这更简单,但我无法弄清楚)。
所以该对象看起来像这样(称为“作业”):
args := &types.SubmitArgs{
SerializedOtelContext: serializedOtelContext,
}
job := &types.Job{}
tracer := otel.GetTracerProvider().Tracer("myservice.org")
_, span := tracer.Start(ctx, "Submitting Job to RPC")
err := system.JsonRpcMethod(rpcHost, rpcPort, "Submit", args, job)
Run Code Online (Sandbox Code Playgroud)
提交到 JsonRpcMethod 的函数在这里:
func JsonRpcMethod(
host string,
port int,
method string,
req, res interface{},
) error {
client, err := rpc.DialHTTP("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil {
return fmt.Errorf("Error in dialing. %s", err)
}
return client.Call(fmt.Sprintf("JobServer.%s", method), req, res)
}
Run Code Online (Sandbox Code Playgroud)
接收它的函数在这里:
func (server *JobServer) Submit(args *types.SubmitArgs, reply *types.Job) error {
//nolint
job, err := server.RequesterNode.Scheduler.SubmitJob(args.Spec, args.Deal)
if err != nil {
return err
}
*reply = *job
return nil
}
Run Code Online (Sandbox Code Playgroud)
我的问题是如何在接收功能(上面的“提交”)中从发送者那里提取跟踪/跨度?
小智 6
这里用一个小程序来说明使用方法。希望这能够清楚地说明这一点。
package main
import (
"context"
"fmt"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
// common init
// You may also want to set them as globals
exp, _ := stdouttrace.New(stdouttrace.WithPrettyPrint())
bsp := sdktrace.NewSimpleSpanProcessor(exp) // You should use batch span processor in prod
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithSpanProcessor(bsp),
)
propgator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
ctx, span := tp.Tracer("foo").Start(context.Background(), "parent-span-name")
defer span.End()
// Serialize the context into carrier
carrier := propagation.MapCarrier{}
propgator.Inject(ctx, carrier)
// This carrier is sent accros the process
fmt.Println(carrier)
// Extract the context and start new span as child
// In your receiving function
parentCtx := propgator.Extract(context.Background(), carrier)
_, childSpan := tp.Tracer("foo").Start(parentCtx, "child-span-name")
childSpan.AddEvent("some-dummy-event")
childSpan.End()
}
Run Code Online (Sandbox Code Playgroud)