How to create an OpenTelemetry span from ctx in gRPC server stub

978 views Asked by At

My Go gRPC server is instrumented with

  1. Google Tracing span exporter:

    import texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
    ...
    gcp, err := texporter.NewExporter()
    ...
    tracer := trace.NewTracerProvider(trace.WithSyncer(traceExporter),
        trace.WithSampler(trace.AlwaysSample()))
    otel.SetTracerProvider(tracer)
    
  2. otelgrpc interceptors registered on the gRPC server.

    unaryInterceptors := grpc_middleware.WithUnaryServerChain(
        otelgrpc.UnaryServerInterceptor(),
    )
    streamInterceptors := grpc_middleware.WithStreamServerChain(
        otelgrpc.StreamServerInterceptor(),
    )
    

Now I'm trying to create a trace span inside the RPC implementation so I can have child spans for the method e.g.:

func (s *srv) Test(ctx context.Context, req *pb.Request) (*pb.TestResponse, error) {
    // create a span here
    span1 := [??????].Start()
    doWork1()
    span1.End()

    span2 := [??????].Start()
    doWork2()
    span2.End()
    ...
}

However it is wildly unclear from the OpenTelemetry docs how does one do that.

Closest I've gotten is otel.GetTracerProvider().Tracer("some string here???") providing a Start(ctx)(ctx,Span). But it is not clear to me what string to provide here (my exporter doesn't have a url like the docs indicate) and this seems quite inconvenient.

I'm thinking there's something like a otelgrpc.SpanFromCtx(ctx) method somewhere that pulls the tracer+creates a span with the rpc ctx that I'm not finding. Sadly the docs are quite lacking on OT+gRPC+Go.

1

There are 1 answers

1
HelloWood On

Since you are using github.com/GoogleCloudPlatform/opentelemetry-operations-go, you should use itself to create span rather than opentelemetry.

You can create a new span like this:

    // Create custom span.
    tracer := otel.TraceProvider().Tracer("example.com/trace")
    err = func(ctx context.Context) error {
        ctx, span := tracer.Start(ctx, "foo")
        defer span.End()

        // Do some work.

        return nil
    }(ctx)

For more detail, you can reference OpenTelemetry Google Cloud Trace Exporter