概述
在本文中,我们将会以 Go 项目为例,演示如何使用 Prometheus 提供的埋点库来实现 Prometheus 的埋点操作。
QuickStart
Step1: 安装 client 库
go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promauto
go get github.com/prometheus/client_golang/prometheus/promhttp
Step2: 编写示例程序
为了在 Go 应用中提供 Prometheus 的监控项,你需要提供一个 /metrics 的 HTTP endpoint。你可以使用 prometheus/promhttp 库中的 Handler 来作为函数处理逻辑。
一个示例代码如下:
package main
import (
"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 main
import (
"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 自增 1
go 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 main
import (
"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 main
import (
"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.Path
for _, 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 来生成对应的指标数据。