Go Gin Web框架中使用 OpenTelemetry

在本文中,我们将演示如何使用OpenTelemetry(以下简称 OTEL)提供的 Gin 中间件生成端到端追踪。还将使用OpenTelemetry库对GORM数据库客户端进行仪表化,将采集的数据存储到观测云分析展示。

部署 Datakit 采集器收集 Metric、Log 和 Trace

登录观测云工作空间,点击左侧「集成」选择顶部「Datakit」,即可看到各种平台的安装命令。

开启 OTEL 采集,进入 DataKit 安装目录下的 conf.d/opentelemetry 目录,复制 opentelemetry.conf.sample 并命名为 opentelemetry.conf。运行 datakit service -R,重启 Datakit。

Datakit 重启后,运行 datakit monitor 命令查看采集器运行状态,可以看到 opentelemetry 采集器已开启。

使用 OTEL 运行 Gin 应用

声明 OTEL 需要的变量

在 main.go 中声明以下全局变量,配置 OTEL 时需要使用:

ini 复制代码
var (
    serviceName  = os.Getenv("SERVICE_NAME")
    collectorURL = os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
    insecure     = os.Getenv("INSECURE_MODE")
)

使用 OTEL 仪表化 Gin

为了配置应用程序发送数据,我们需要一个函数来初始化 OTEL ,在 main.go 文件中添加以下代码:

erlang 复制代码
import (
  .....

    "github.com/gin-gonic/gin"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/attribute"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"

    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

func initTracer() func(context.Context) error {

    secureOption := otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
    if len(insecure) > 0 {
        secureOption = otlptracegrpc.WithInsecure()
    }

    exporter, err := otlptrace.New(
        context.Background(),
        otlptracegrpc.NewClient(
            secureOption,
            otlptracegrpc.WithEndpoint(collectorURL),
        ),
    )

    if err != nil {
        log.Fatal(err)
    }
    resources, err := resource.New(
        context.Background(),
        resource.WithAttributes(
            attribute.String("service.name", serviceName),
            attribute.String("library.language", "go"),
        ),
    )
    if err != nil {
        log.Printf("Could not set resources: ", err)
    }

    otel.SetTracerProvider(
        sdktrace.NewTracerProvider(
            sdktrace.WithSampler(sdktrace.AlwaysSample()),
            sdktrace.WithBatcher(exporter),
            sdktrace.WithResource(resources),
        ),
    )
    return exporter.Shutdown
}

在 main.go 中初始化 tracer

在 main.go 文件的 main 函数的开头修改代码,以初始化跟踪器(tracer):

css 复制代码
func main() {
    cleanup := initTracer()
    defer cleanup(context.Background())

    ......
}

添加 OTEL Gin 中间件

在 main.go 文件中添加以下代码,配置 Gin 使用 OTEL 中间件:

css 复制代码
import (
    ....
  "go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
)

func main() {
    ......
    r := gin.Default()
    r.Use(otelgin.Middleware(serviceName))
    ......
}

使用 OTEL 初始化 GORM

OTEL 提供了一个 otelgorm 插件,用于监控 GORM 数据库客户端。以下步骤将 OTEL 与 GORM 数据库客户端进行仪表化:

scss 复制代码
func ConnectDatabase() {
    .....
    DB = database
    if err := DB.Use(otelgorm.NewPlugin()); err != nil {
        panic(err)
    }
}  

更新所有的数据库调用

models.DB 修改为 models.DB.WithContext(c.Request.Context())

scss 复制代码
func FindBooks(c *gin.Context) {
    .....
    models.DB.WithContext(c.Request.Context()).Find(&books)
    .....
}

以上的更改应该针对所有的数据库调用进行。

配置环境变量运行 Gin 应用

使用 OTEL 为 Gin 应用程序进行仪表化,需要设置一些环境变量将数据发送到 Datakit 后端。

ini 复制代码
SERVICE_NAME=GinApp INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 ./gin-app

IP:不要添加 http/https 协议头;

SERVICE_NAME: GinApp (应用名请根据实际场景修改);

OTEL_EXPORTER_OTLP_ENDPOINT: localhost:4317;(Datakit 监听地址 )

生成数据

  • 创建数据
css 复制代码
curl -X POST --header 'Content-Type: application/json' \
-d '{"title": "The Three-body Problem","author": "DaLiu"}' \
'localhost:8080/books'
  • 查询数据
arduino 复制代码
curl 'localhost:8080/books'

在观测云查询收到的数据

链路数据

指标数据

前端可观测

使用 vue-element-admin 编写前端demo,接入后端的Gin应用,在 VUE 中注入观测云RUM代码。

接入前端 RUM 采集器

开启 RUM 采集器,开启后通过 datakit monitor 看到 rum 已启用。

接入Web应用

登录观测云控制台,进入用户访问监测 页面,点击左上角 新建应用,即可开始创建一个新的应用。

修改接入参数,复制 NPM 接入参数到 vue main.js 文件中。

重新打包发布,打开浏览器开发者模式,可以看到 rum 上传成功信息

通过观测云观察采集的Trace和Metric

RUM链路 数据

应用链路 数据

日志采集

总结

本文通过OTEL提供的库实现了Gin应用的可观测性,使用观测云做为OTEL后端存储Trace、RUM、Log数据,并通过观测云提供的仪表板实现数据的快速查询分析。

signoz.io/blog/opente...

Gin github.com/DataDog/dd-...

docs.datadoghq.com/tracing/tra...

Gin 微服务调用:

medium.com/@emafuma/st...

相关推荐
无风听海27 分钟前
深入剖析 YARP 的 Transforms:构建灵活的反向代理转换管道
后端·中间件·asp.net
Gopher_HBo35 分钟前
负载均衡
后端
自由生长20241 小时前
RAG已死?什么标题党啊!
后端
东方小月2 小时前
5分钟搞懂Harness Engineering(驾驭工程):从提示词到AI Agent的进化之路
前端·后端·架构
折哥的程序人生 · 物流技术专研4 小时前
Java面试85题图解版(一):基础核心篇
java·开发语言·后端·面试
Moment5 小时前
面试官:如果产品经理给你多个需求,怎么让AI去完成❓❓❓
前端·后端·面试
每天进步一点_JL6 小时前
JVM 内存模型与 OOM 排查:从入门到实战
后端
REDcker6 小时前
个人博客网站建设指南 Markdown资产化与静态站选型部署
前端·后端·博客·markdown·网站·资产·建站
Supersist6 小时前
【设计模式03】使用模版模式+责任链模式优化实战
后端·设计模式·代码规范
Fox爱分享6 小时前
字节二面:10亿数据毫秒级查手机尾号后4位,答不出“异构索引”直接挂?
java·后端·面试