【GO】LGTM_Grafana_gin_trace中间件(3)_代码实操

最近在尝试用 LGTM 来实现 Go 微服务的可观测性,就顺便整理一下文档。

Tempo 会分为 4 篇文章:

  1. Tempo 的架构
  2. 官网测试实操跑通
  3. gin 框架发送 trace 数据到 tempo
  4. go-zero 微服务框架使用发送数据到 tempo

本文就是写一下如何在 gin server 里面加入 trace 的逻辑

代码地址:lgtm/example/gin-lgtm at main · zxmfke/lgtm (github.com)


gin server 接入 trace,是比较简单的,只需要封装一个 tracer 的初始化和中间件就可以了。直接看代码。

Tracer Init

初始化一个 tracerProvider,并把这个 tracerProvider 设置为全局的 provider。

func InitTracer(c Config) error {
	var err error

	err = tracerProvider(c)
	...
	otel.SetTracerProvider(tp)

	return nil
}

func createExporter(c Config) (tracesdk.SpanExporter, error) {
	switch c.Batcher {
	case kindZipKin:
		return zipkin.New(c.Endpoint)
	case kindOtlphttp:
		opts := []otlptracehttp.Option{
			otlptracehttp.WithInsecure(),
			otlptracehttp.WithEndpoint(c.Endpoint),
		}
		return otlptracehttp.New(context.Background(), opts...)

	case kindOtlpgrpc:

		opts := []otlptracegrpc.Option{
			otlptracegrpc.WithInsecure(),
			otlptracegrpc.WithEndpoint(c.Endpoint),
		}
		return otlptracegrpc.New(context.Background(), opts...)

	default:
		return nil, fmt.Errorf("unknown exporter: %s", c.Batcher)
	}
}
Tracer Middleware

利用 gin 路由的中间件模式,添加一个 tracer 的中间件,把要 trace 的路由的信息,在请求前记录并在请求结束后发送到 tempo。

func Trace(ctx *gin.Context) {

	newSpan := Extract(ctx.Request, "trace-middleware")

	defer newSpan.End()

	ctx.Set(HeaderTraceContextKey, newSpan.spanCtx)
	ctx.Set(HeaderTraceIDKey, newSpan.SpanID())

	newSpan.Inject(ctx.Request)

	ctx.Next()

	newSpan.SetIntTag("http.status_code", ctx.Writer.Status())
	if ctx.Writer.Status() == http.StatusOK {
		newSpan.SetStatus(codes.Ok, "well done")
		return
	}
	newSpan.SetStatus(codes.Error, "something goes wrong")

}
Main

在代码仓库的 main.go 逻辑就是初始化,并把 tracer middleware 加入到 router 里面。

func main() {

	if err := tracer.InitTracer(tracer.Config{
		ServiceName: "tracer-demo",
		Endpoint:    "127.0.0.1:4318",
		Sampler:     1.0,
		Batcher:     "otlphttp",
	}); err != nil {
		fmt.Println(fmt.Errorf("%s", err.Error()))
		return
	}

	r := gin.Default()

	r.Use(tracer.Trace)
	r.GET("/ping", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})

	r.POST("/test", func(ctx *gin.Context) {

		Sub(ctx)

		ctx.JSON(http.StatusOK, gin.H{
			"code": 0,
			"msg":  "success",
		})

	})

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")

}

请求接口后,可以通过 Grafana Tempo 里面查看

【GO】LGTM_Grafana_gin_trace中间件(3)_代码实操_第1张图片

你可能感兴趣的:(Go,微服务,golang,grafana,gin,tempo,trace)