最近在尝试用 LGTM 来实现 Go 微服务的可观测性,就顺便整理一下文档。
Tempo 会分为 4 篇文章:
Tempo 的架构
官网测试实操跑通
gin 框架发送 trace 数据到 tempo
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 里面查看
评论