从请求头中提取追踪器的正确方法是使用 OpenTelemetry。

huangapple go评论95阅读模式
英文:

Proper way of extracting tracer from request Headers for opentelemetry

问题

我有一个使用opentracing的krakend apigateway,并且将请求头作为X-B3-...发送以进行跟踪,而我的服务使用opentelemetry。这是我现在在jaeger上的情况。

我希望服务的跨度能够归属于apigateway的跨度。

我已经做了以下解决方法:
这是使用chi路由器的请求的确切处理程序。

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,
    })
}
英文:

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,
	})
}

答案1

得分: 2

好的,以下是翻译好的内容:

好的,我找到了如何使其工作的方法。
我添加了这个中间件,它将使用头部的 traceID、spanID 和 traceFlags 同步请求上下文。
在这之后,我们可以根据需要创建跟踪器和跨度。

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)
	})
}

希望对你有帮助!

英文:

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)
})
}

huangapple
  • 本文由 发表于 2021年8月22日 21:22:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/68881728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定