Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way of extracting tracer from request Headers for opentelemetry

I have krakend apigateway which is using opentracing and sending req headers as X-B3-... for tracing and my service is using opentelemetry.
This is what I'm having right now on jaeger.
enter image description here

enter image description here

I want the service spans to come under the apigateways'.

Workaround I have done:
This is the exact handler for the request using chi router.

func (env *Env) getCommentForBlogRouter(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()

    keys := []string{"X-B3-Traceid", "X-B3-Spanid", "X-B3-Sampled"}
    var carrier propagation.HeaderCarrier = propagation.HeaderCarrier{}
    for _, k := range keys {
        carrier.Set(strings.ToLower(k), r.Header[k][0])
    }

    var propagator propagation.TextMapPropagator = otel.GetTextMapPropagator()
    ctx = propagator.Extract(ctx, carrier)

    // fmt.Println(ctx)
    tr := otel.Tracer("Handler: blog-comments")
    ctx, span := tr.Start(ctx, "handler span")
    defer span.End()

    blogId := r.URL.Query().Get("blog-id")
    span.SetAttributes(attribute.Key("blog-id").String(fmt.Sprint(blogId)))

    var spanDB trace.Span
    ctx, spanDB = tr.Start(ctx, "Select row")

    comments, err := env.comments.GetForBlog(blogId)
    spanDB.End()

    var spanRes trace.Span
    _, spanRes = tr.Start(ctx, "Sending Response")
    defer spanRes.End()

    if err != nil {
        fmt.Println(err)
        SendError(w, http.StatusInternalServerError, "Something went wrong")
        return
    }

    if comments == nil {
        comments = []models.Comment{}
    }
    SendResponse(w, http.StatusOK, map[string]interface{}{
        "data": comments,
    })
}
like image 958
lazybot Avatar asked Jan 19 '26 21:01

lazybot


1 Answers

Ok, I figured out how to make it work. I added this middleware and it will sync the request context with the headers traceID, spanID and traceFlags. After this we are good to create tracer and spans as we want.

func Tracing(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        traceID, _ := trace.TraceIDFromHex(r.Header["X-B3-Traceid"][0])
        spanID, _ := trace.SpanIDFromHex(r.Header["X-B3-Spanid"][0])
        var traceFlags trace.TraceFlags
        if r.Header["X-B3-Sampled"][0] == "1" {
            traceFlags = trace.FlagsSampled
        }

        spanContext := trace.NewSpanContext(trace.SpanContextConfig{
            TraceID:    traceID,
            SpanID:     spanID,
            TraceFlags: traceFlags,
        })

        ctx := trace.ContextWithSpanContext(r.Context(), spanContext)

        r = r.WithContext(ctx)
        next.ServeHTTP(w, r)
    })
}
like image 110
lazybot Avatar answered Jan 23 '26 04:01

lazybot