3

I am trying to distribute tracing between 2 Go microservices using Opentelemetry and Gin-Gonic.

Please help, I have come across Otelhttp examples, but I couldn't find examples with Otelgin.

Using "go.opentelemetry.io/otel/sdk/trace" as tracesdk

Microservice 1

func TracerProvider() (*tracesdk.TracerProvider, error) {
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
    exporter, _:= stdouttrace.New(stdouttrace.WithPrettyPrint())
    tp := tracesdk.NewTracerProvider(
        tracesdk.WithSampler(tracesdk.AlwaysSample()),
        tracesdk.WithBatcher(exporter),
        tracesdk.WithResource(resource.NewWithAttributes(
            semconv.ServiceNameKey.String("microservice-1"),
            attribute.String("environment", "test"),
        )),
    )

    otel.SetTracerProvider(tp)
    return tp, nil
}
func main() {
    TracerProvider()
    resty := resty.New()

    router := gin.Default()
    router.Use(otelgin.Middleware("microservice-1"))
    {
        
        router.GET("/ping", func(c *gin.Context) {
            result := Result{}
            req := resty.R().SetHeader("Content-Type", "application/json")
            ctx := req.Context()
            span := trace.SpanFromContext(ctx)
            defer span.End()
            otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
            resp, _ := req.Get("http://localhost:8088/pong")

        json.Unmarshal([]byte(resp.String()), &result)
            c.IndentedJSON(200, gin.H{
                "message": result.Message,
            })
        })
    }
    router.Run(":8085")

}

// Microservice 2

//TracerProvider func is the same as Microservice 1

//main

TracerProvider()
router := gin.Default()
router.Use(otelgin.Middleware("microservice-2"))
{
    router.GET("/pong", func(c *gin.Context) {
        ctx := c.Request.Context()
        span := trace.SpanFromContext(otel.GetTextMapPropagator().Extract(ctx, propagation.HeaderCarrier(c.Request.Header)))
        defer span.End()

        c.IndentedJSON(200, gin.H{
            "message": "pong",
        })
    })
}
router.Run(":8088")

2 Answers 2

2

There is an example of go-gin instrumentation in the official repository of OpenTelemetry Go Contrib: https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/github.com/gin-gonic/gin/otelgin/example

Basically, you need use the package:
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"

And you can also add the otelgin.HTML to render your response.

HTML will trace the rendering of the template as a child of the span in the given context.
This is a replacement for gin.Context.HTML function - it invokes the original function after setting up the span.

As detailed in its implementation: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/github.com/gin-gonic/gin/otelgin/gintrace.go

Sign up to request clarification or add additional context in comments.

Comments

1

It might be a bit late but it will still be useful. In the 1st microservice, you need to put:

req := resty.R().SetHeader("Content-Type", "application/json")
req.SetContext(c.Request.Context())

That will fix the problem. On this screenshot you are able to see the 2 spans on the 1st microservice

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.