You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从gin.Context获取OpenTelemetry链路追踪详情信息?

使用otelgin从gin.Context获取链路追踪信息

问题描述

我正尝试用otelgin给项目做链路追踪,官方说追踪信息可以从gin.Context.Request.Context()里拿,但不知道怎么从中提取TraceID、SpanID这类详细信息来验证功能是否正常。

官方用stdout作为导出器初始化Tracer Provider的代码如下:

func initTracer() (*sdktrace.TracerProvider, error) {
    // stdout as exporter
    exporter, err := stdout.New(stdout.WithPrettyPrint())
    if err != nil {
        return nil, err
    }
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithSampler(sdktrace.AlwaysSample()),
        sdktrace.WithBatcher(exporter),
    )
    otel.SetTracerProvider(tp)
 
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
    return tp, nil
}

现在命令行已经能输出部分追踪内容:

"Name": "/users/:id",
    "SpanContext": {
        "TraceID": "e7a43d30c0e507b4c59fd65dc3bc6d77",
        "SpanID": "636c22201c903573",
        "TraceFlags": "01",
        "TraceState": "",
        "Remote": false
    },
    "Parent": {
        "TraceID": "00000000000000000000000000000000",
        "SpanID": "0000000000000000",
        "TraceFlags": "00",
        "TraceState": "",
        "Remote": false
    },
    "SpanKind": 2,
    "StartTime": "2022-11-12T16:02:07.871843+08:00",
    "EndTime": "2022-11-12T16:02:07.871843+08:00",

但我写的中间件直接打印c.Request.Context()时,得到的是:

(type *http.contextKey, val <not Stringer>).WithValue(type *http.contextKey, val [::1]:8088).WithCancel.WithCancel.WithValue(type trace.traceContextKeyType, val <not Stringer>)

想知道怎么从gin.Context里提取这些追踪信息,以及能不能获取导出器的详细信息。


解决方法

一、提取TraceID、SpanID等追踪信息

不能直接打印Context对象,要借助OpenTelemetry的trace包从Context中提取当前Span的上下文。修改中间件代码:

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "go.opentelemetry.io/otel/trace"
)

func TracerGetMiddleware(c *gin.Context) {
    // 从request context中取出当前span的上下文
    spanCtx := trace.SpanContextFromContext(c.Request.Context())
    
    if spanCtx.IsValid() {
        // 提取并打印关键追踪信息
        traceID := spanCtx.TraceID().String()
        spanID := spanCtx.SpanID().String()
        traceFlags := spanCtx.TraceFlags().String()
        
        fmt.Printf("TraceID: %s, SpanID: %s, TraceFlags: %s\n", traceID, spanID, traceFlags)
    } else {
        fmt.Println("当前上下文没有有效追踪信息")
    }
    
    c.Next()
}

这段代码会输出和stdout导出器里一致的TraceID、SpanID,用来验证链路追踪是否正常工作。

二、关于获取导出器信息

导出器属于Tracer Provider的一部分,不会存在gin.Context里。如果需要用到导出器相关内容:

  • 初始化initTracer时把导出器(或Tracer Provider)存成全局变量,后续直接调用即可
  • 要是只是验证导出器是否正常,看stdout的输出就够了,没必要从Context里拿

三、注意事项

  • 必须先注册otelgin中间件,否则c.Request.Context()里不会有追踪信息:
    r := gin.Default()
    r.Use(otelgin.Middleware("your-service-name")) // 先注册otelgin中间件
    r.Use(TracerGetMiddleware) // 再注册自定义的获取追踪信息中间件
    
  • 只有当spanCtx.IsValid()返回true时,才能拿到有效的TraceID和SpanID

内容的提问来源于stack exchange,提问作者Ltd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:50:37