概述
在本文中,我们将会以 Go 项目为例,演示如何使用 Prometheus 提供的埋点库来实现 Prometheus 的埋点操作。
QuickStart
Step1: 安装 client 库
go get github.com/prometheus/client_golang/prometheusgo get github.com/prometheus/client_golang/prometheus/promautogo get github.com/prometheus/client_golang/prometheus/promhttp
Step2: 编写示例程序
为了在 Go 应用中提供 Prometheus 的监控项,你需要提供一个 /metrics 的 HTTP endpoint。你可以使用 prometheus/promhttp 库中的 Handler 来作为函数处理逻辑。
一个示例代码如下:
package mainimport ("net/http""github.com/prometheus/client_golang/prometheus/promhttp")func main() {http.Handle("/metrics", promhttp.Handler())http.ListenAndServe(":2112", nil)}
此时,你可以访问 http://localhost:2112/metrics 来查询对应的监控指标。
Step3: 添加自己的 metrics 指标
上述示例中,仅仅提供了一些默认的 metrics 指标。此外,你还可以注册自己自定义的应用特定的相关指标。例如,在如下应用中,我们提供了一个 myapp_processed_ops_total 的 Counter 类型的指标用于统计程序操作的次数。在如下程序中,每隔 2s 后,对应的 counter 指标会自增 1。
package mainimport ("net/http""time""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promauto""github.com/prometheus/client_golang/prometheus/promhttp")func recordMetrics() {// 每隔 2s 自增 1go func() {for {opsProcessed.Inc()time.Sleep(2 * time.Second)}}()}var (// 定义了一个 myapp_processed_ops_total 指标,Counter 类型opsProcessed = promauto.NewCounter(prometheus.CounterOpts{Name: "myapp_processed_ops_total",Help: "The total number of processed events",}))func main() {recordMetrics()http.Handle("/metrics", promhttp.Handler())http.ListenAndServe(":2112", nil)}
go-gin-prometheus 快速上手
gin 是 Go 语言中流行的一个 Web 框架。下面,我们来讲解一下针对 Gin 框架而言,如果实现 Prometheus 的埋点操作。
Step1: 安装 client 库
go get github.com/zsais/go-gin-prometheus
Step2: QuickStart
package mainimport ("github.com/gin-gonic/gin""github.com/zsais/go-gin-prometheus")func main() {r := gin.New()p := ginprometheus.NewPrometheus("gin")p.Use(r)r.GET("/", func(c *gin.Context) {c.JSON(200, "Hello world!")})r.Run(":29090")}
默认情况下,go-gin-prometheus 将会安装每个请求 url 作为 label 统计对应的请求次数,并作为 gin_requests_total 指标对外暴露。
但是这样会有一个问题,如果你的 url 中包含类似这样 /customer/:name 的 url 匹配规则,就会导致 labels 爆炸。一方面会使得你的指标统计规则变得更加复杂,同时也会严重的影响 Prometheus 的性能。
因此,你还需要编写一个 mapping 函数来传递给 middleware 用于重写 Labels 的计算规则:
package mainimport ("github.com/gin-gonic/gin""github.com/zsais/go-gin-prometheus")func main() {r := gin.New()p := ginprometheus.NewPrometheus("gin")p.ReqCntURLLabelMappingFn = func(c *gin.Context) string {url := c.Request.URL.Pathfor _, p := range c.Params {if p.Key == "name" {url = strings.Replace(url, p.Value, ":name", 1)break}}return url}p.Use(r)r.GET("/", func(c *gin.Context) {c.JSON(200, "Hello world!")})r.Run(":29090")}
这样一来,它就可以将 url_pattern 作为 label 来生成对应的指标数据。
