Search code examples
gogrpcjaegeropentracingdistributed-tracing

Child span in Go GRPC opentracing


I am working on adding opentracing in our micro services, using Jaeger. I have two GRPC server and one REST server.

enter image description here

The default opentracing with perfectly fine with both GRPC server and all the rest-grpc request are tracked under one parent span. With Java GRPC I am able to add custom child spans and it appears in perfect hierarchy in the Jaeger UI. But When I am trying to add same custom child in Go Lang, it is not added to the parent Rest Service span which has called the GRPC service. Below is the golang code

"github.com/opentracing/opentracing-go"

cfg := jaegerConfig.Configuration{
    ServiceName: t.Name,
}

tracer, closer, err := cfg.NewTracer(
    jaegerConfig.Logger(jLogger),
    jaegerConfig.Metrics(jMetricsFactory),
)

gRPCServer := grpc.NewServer(
        grpc.UnaryInterceptor(
            otgrpc.OpenTracingServerInterceptor(tracer)),
        grpc.StreamInterceptor(
            otgrpc.OpenTracingStreamServerInterceptor(tracer)))

var span = tracer.StartSpan("Test Span")
span.SetTag("one", "value")
span.Finish()

I do not want to do the whole http headers extraction, as that is already taken care by GRPC library. Even with java GRPC I do not do any extraction. The scope manager that I use with opentracing is not available with go lang opentracing.

Thanks in advance!!!

Cheers.


Solution

  • You could try with StartSpanFromContext, inside your gRPC handlers:

        // import "github.com/opentracing/opentracing-go"
        
        span, _ := opentracing.StartSpanFromContext(ctx, "some_child_span")
        defer span.Finish()
    
        span.SetTag("foo", "bar")
    

    As the documentation of otgrpc.OpenTracingServerInterceptor says:

    [...] the server Span will be embedded in the context.Context for the application-specific gRPC handler(s) to access.

    If we look at the function implementation:

    // import "github.com/opentracing/opentracing-go"
    
    func OpenTracingServerInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.UnaryServerInterceptor {
            // ... a lot omitted
            ctx = opentracing.ContextWithSpan(ctx, serverSpan)
            // ...
            resp, err = handler(ctx, req) // your gRPC handler
            // ...   
    }
    



    Edit: Given the above, you probably can omit this code:

    var span = tracer.StartSpan("Test Span")
    span.SetTag("one", "value")
    span.Finish()