package jaeger import ( "context" "encoding/json" "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/util/gconv" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/jaeger" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.21.0" "strconv" ) var Tp = new(trace.TracerProvider) func init() { jaegerAgent, err := g.Cfg().Get(context.Background(), "jaeger.addr") if err != nil { panic(err) } fmt.Println(jaegerAgent) exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(gconv.String(jaegerAgent)))) if err != nil { panic(err) } serverName, err := g.Cfg().Get(context.Background(), "server.Name") if err != nil { panic(err) } // 创建一个 TracerProvider,并将 Jaeger exporter 设置为其处理器 Tp = trace.NewTracerProvider( // 使用 BatchSpanProcessor 可以提高性能,它会批量发送 span trace.WithBatcher(exp), // 设置资源属性,这些属性会附加到所有导出的 span 上 trace.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceName(gconv.String(serverName)), // 服务名称,在 Jaeger UI 中会显示 )), ) // 将 TracerProvider 设置为全局,方便在应用的任何地方通过 otel.Tracer() 获取 otel.SetTracerProvider(Tp) } func NewTracer(r *ghttp.Request) { // 从传入的上下文中获取 Tracer,或者直接使用全局的 tracer := otel.Tracer(r.GetServeHandler().GetMetaTag("summary")) _, span := tracer.Start(r.Context(), r.GetServeHandler().GetMetaTag("summary")) defer span.End() // 非常重要:确保 span 在函数结束时被关闭 span.SetAttributes(attribute.String("request", getParams(r))) r.Middleware.Next() span.SetAttributes(attribute.String("response", r.Response.BufferString())) //span.AddEvent("Saying hello is done") } func getParams(r *ghttp.Request) string { params := map[string]interface{}{} if r.Method == "POST" { json.Unmarshal(r.GetBody(), ¶ms) //获取raw传参 } if r.Method == "GET" { r.Request.ParseForm() form := r.Form for k, v := range form { if vl, e := strconv.Atoi(v[0]); e == nil { params[k] = vl } else { params[k] = v[0] } } } rp, _ := json.Marshal(¶ms) return string(rp) }