2025-11-25 11:51:16 +08:00
|
|
|
|
package jaeger
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"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)
|
|
|
|
|
|
}
|
|
|
|
|
|
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(gconv.String(jaegerAgent))))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
}
|
2025-11-25 13:07:27 +08:00
|
|
|
|
serverName, err := g.Cfg().Get(context.Background(), "server.Name")
|
2025-11-25 11:51:16 +08:00
|
|
|
|
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)
|
|
|
|
|
|
}
|