创立利用
咱们首先从一个最简略的 Go 应用程序开始,在端口 8080 的 /metrics 端点上裸露客户端库的默认注册表,临时还没有跟踪任何其余自定义的监控指标。
先创立一个名为 instrument-demo 的目录,在该目录上面初始化我的项目:
$ mkdir instrument-demo && cd instrument-demo
$ go mod init github.com/cnych/instrument-demo
下面的命令会在 instrument-demo 目录上面生成一个 go.mod 文件,在同目录上面新建一个 main.go 的入口文件,内容如下所示:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// Serve the default Prometheus metrics registry over HTTP on /metrics.
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
而后执行上面的命令下载 Prometheus 客户端库依赖:
$ export GOPROXY="https://goproxy.cn"
$ go mod tidy
go: finding module for package github.com/prometheus/client_golang/prometheus/promhttp
go: found github.com/prometheus/client_golang/prometheus/promhttp in github.com/prometheus/client_golang v1.11.0
go: downloading google.golang.org/protobuf v1.26.0-rc.1
而后间接执行 go run 命令启动服务:
$ go run main.go
而后咱们能够在浏览器中拜访 http://localhost:8080/metrics 来取得默认的监控指标数据:
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 6
......
# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
go_threads 8
# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.
# TYPE promhttp_metric_handler_requests_in_flight gauge
promhttp_metric_handler_requests_in_flight 1
# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
# TYPE promhttp_metric_handler_requests_total counter
promhttp_metric_handler_requests_total{code="200"} 1
promhttp_metric_handler_requests_total{code="500"} 0
promhttp_metric_handler_requests_total{code="503"} 0
咱们并没有在代码中增加什么业务逻辑,然而能够看到仍然有一些指标数据输入,这是因为 Go 客户端库默认在咱们裸露的全局默认指标注册表中注册了一些对于 promhttp 处理器和运行工夫相干的默认指标,依据不同指标名称的前缀能够看出:
go_*: 以 go_ 为前缀的指标是对于 Go 运行时相干的指标,比方垃圾回收工夫、goroutine 数量等,这些都是 Go 客户端库特有的,其余语言的客户端库可能会裸露各自语言的其余运行时指标。
promhttp_*: 来自 promhttp 工具包的相干指标,用于跟踪对指标申请的解决。
这些默认的指标是十分有用,然而更多的时候咱们须要本人管制,来裸露一些自定义指标。这就须要咱们去实现自定义的指标了。
增加自定义指标
接下来咱们来自定义一个的 gauge 指标来裸露以后的温度。创立一个新的文件 custom-metric/main.go,内容如下所示:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// 创立一个没有任何 label 标签的 gauge 指标
temp := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "home_temperature_celsius",
Help: "The current temperature in degrees Celsius.",
})
// 在默认的注册表中注册该指标
prometheus.MustRegister(temp)
// 设置 gauge 的值为 39
temp.Set(39)
// 裸露指标
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
下面文件中和最后的文件就有一些变动了:
- 咱们应用 prometheus.NewGauge() 函数创立了一个自定义的 gauge 指标对象,指标名称为 home_temperature_celsius,并增加了一个正文信息。
- 而后应用 prometheus.MustRegister() 函数在默认的注册表中注册了这个 gauge 指标对象。
- 通过调用 Set() 办法将 gauge 指标的值设置为 39。
- 而后像之前一样通过 HTTP 裸露默认的注册表。
须要留神的是除了 prometheus.MustRegister() 函数之外还有一个 prometheus.Register() 函数,个别在 golang 中咱们会将 Mustxxx 结尾的函数定义为必须满足条件的函数,如果不满足会返回一个 panic 而不是一个 error 操作,所以如果这里不能失常注册的话会抛出一个 panic。
当初咱们来运行这个程序:
$ go run ./custom-metric
启动后从新拜访指标接口 http://localhost:8080/metrics,认真比照咱们会发现多了一个名为 home_temperature_celsius 的指标:
...
# HELP home_temperature_celsius The current temperature in degrees Celsius.
# TYPE home_temperature_celsius gauge
home_temperature_celsius 42
...
这样咱们就实现了增加一个自定义的指标的操作,整体比较简单,当然在理论的我的项目中须要联合业务来确定增加哪些自定义指标。
自定义注册表
后面咱们是应用 prometheus.MustRegister() 函数来将指标注册到全局默认注册中,此外咱们还能够应用 prometheus.NewRegistry() 函数来创立和应用本人的非全局的注册表。
既然有全局的默认注册表,为什么咱们还须要自定义注册表呢?这次要是因为:
- 全局变量通常不利于保护和测试,创立一个非全局的注册表,并明确地将其传递给程序中须要注册指标的中央,这也一种更加举荐的做法。
-
全局默认注册表包含一组默认的指标,咱们有时候可能心愿除了自定义的指标之外,不心愿裸露其余的指标。
上面的示例程序演示了如何创立、应用和裸露一个非全局注册表对象,创立一个文件 custom-registry/main.go,内容如下所示:package main import ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) func main() { // 创立一个自定义的注册表 registry := prometheus.NewRegistry() // 可选: 增加 process 和 Go 运行时指标到咱们自定义的注册表中 registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) registry.MustRegister(prometheus.NewGoCollector()) // 创立一个简略呃 gauge 指标。temp := prometheus.NewGauge(prometheus.GaugeOpts{ Name: "home_temperature_celsius", Help: "The current temperature in degrees Celsius.", }) // 应用咱们自定义的注册表注册 gauge registry.MustRegister(temp) // 设置 gague 的值为 39 temp.Set(39) // 裸露自定义指标 http.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{Registry: registry})) http.ListenAndServe(":8080", nil) }
下面咱们没有应用全局默认的注册表了,而是创立的一个自定义的注册表:
- 首先应用 prometheus.NewRegistry() 函数创立咱们本人的注册表对象。
- 而后应用自定义注册表对象下面的 MustRegister() 哈是来注册 guage 指标,而不是调用 prometheus.MustRegister() 函数(这会应用全局默认的注册表)。
- 如果咱们心愿在自定义注册表中也有过程和 Go 运行时相干的指标,咱们能够通过实例化 Collector 收集器来增加他们。
-
最初在裸露指标的时候必须通过调用 promhttp.HandleFor() 函数来创立一个专门针对咱们自定义注册表的 HTTP 处理器,为了同时裸露后面示例中的 promhttp_* 相干的指标,咱们还须要在 promhttp.HandlerOpts 配置对象的 Registry 字段中传递咱们的注册表对象。
同样咱们从新运行下面的自定义注册表程序:$ go run ./custom-metric
启动后再次拜访指标接口 http://localhost:8080/metrics,能够发现和下面示例中的指标数据是雷同的。
指标定制
- Gauges(仪表盘):Gauge 类型代表一种样本数据能够任意变动的指标,即可增可减。
- Counters(计数器):counter 类型代表一种样本数据枯燥递增的指标,即只增不减,除非监控零碎产生了重置。
- Histograms(直方图): 创立直方图指标比 counter 和 gauge 都要简单,因为须要配置把观测值纳入的 bucket 的数量,以及每个 bucket 的上边界。Prometheus 中的直方图是累积的,所以每一个后续的 bucket 都蕴含前一个 bucket 的察看计数,所有 bucket 的上限都从 0 开始的,所以咱们不须要明确配置每个 bucket 的上限,只须要配置下限即可。
- Summaries(摘要): 与 Histogram 相似类型,用于示意一段时间内的数据采样后果(通常是申请持续时间或响应大小等),但它间接存储了分位数(通过客户端计算,而后展现进去),而不是通过区间计算
Gauges
后面的示例咱们曾经理解了如何增加 gauge 类型的指标,创立了一个没有任何标签的指标,间接应用 prometheus.NewGauge() 函数即可实例化一个 gauge 类型的指标对象,通过 prometheus.GaugeOpts 对象能够指定指标的名称和正文信息:
queueLength := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "queue_length",
Help: "The number of items in the queue.",
})
咱们晓得 gauge 类型的指标值是能够回升或降落的,所以咱们能够为 gauge 指标设置一个指定的值,所以 gauge 指标对象裸露了 Set()、Inc()、Dec()、Add() 和 Sub() 这些函数来更改指标值:
// 应用 Set() 设置指定的值
queueLength.Set(0)
// 减少或缩小
queueLength.Inc() // +1:gauge 减少 1.
queueLength.Dec() // -1:gauge 缩小 1.
queueLength.Add(23) // 减少 23 个增量.
queueLength.Sub(42) // 缩小 42 个.
Counters
要创立一个 counter 类型的指标和 gauge 比拟相似,只是用 prometheus.NewCounter() 函数来初始化指标对象:
totalRequests := prometheus.NewCounter(prometheus.CounterOpts{
Name: "http_requests_total",
Help: "The total number of handled HTTP requests.",
})
咱们晓得 counter 指标只能随着工夫的推移而一直减少,所以咱们不能为其设置一个指定的值或者缩小指标值,所以该对象上面只有 Inc() 和 Add() 两个函数:
totalRequests.Inc() // +1:计数器减少 1.
totalRequests.Add(23) // +n:计数器减少 23.
当服务过程重新启动的时候,counter 指标值会被重置为 0,不过不必放心数据错乱,咱们个别会应用的 rate() 函数会主动解决。
最终 counter 指标会被渲染成如下所示的数据:
# HELP http_requests_total The total number of handled HTTP requests.
# TYPE http_requests_total counter
http_requests_total 7734
Histograms
创立直方图指标比 counter 和 gauge 都要简单,因为须要配置把观测值纳入的 bucket 的数量,以及每个 bucket 的上边界。Prometheus 中的直方图是累积的,所以每一个后续的 bucket 都蕴含前一个 bucket 的察看计数,所有 bucket 的上限都从 0 开始的,所以咱们不须要明确配置每个 bucket 的上限,只须要配置下限即可。
同样要创立直方图指标对象,咱们应用 prometheus.NewHistogram() 函数来进行初始化:
requestDurations := prometheus.NewHistogram(prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "A histogram of the HTTP request durations in seconds.",
// Bucket 配置:第一个 bucket 包含所有在 0.05s 内实现的申请,最初一个包含所有在 10s 内实现的申请。Buckets: []float64{0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
})