golang实现指标监控与Prometheus暴露的插件库metrics的使用
Golang实现指标监控与Prometheus暴露的插件库metrics的使用
关于
指标是用于比较和跟踪性能或生产的定量评估度量。这个库为Go编程语言提供了原子计数器、测量仪和直方图。用户可以选择以Prometheus文本格式公开快照。
使用
建议在包级别进行静态注册。这些声明也有助于记录代码中涵盖的功能。
// Package Metrics
var (
ConnectCount = metrics.MustCounter("db_connects_total", "Number of established initiations.")
CacheBytes = metrics.MustInteger("db_cache_bytes", "Size of collective responses.")
DiskUsage = metrics.Must1LabelRealSample("db_disk_usage_ratio", "device")
)
更新方法设计为无错误操作,例如CacheBytes.Add(-72)
或DiskUsage(dev.Name).Set(1 - dev.Free, time.Now())
。
只需使用http.HandleFunc("/metrics", metrics.ServeHTTP)
即可提供HTTP服务。
示例HTTP响应:
HTTP/1.1 200 OK
Content-Type: text/plain;version=0.0.4
Date: Sun, 07 Mar 2021 15:22:47 GMT
Content-Length: 351
# Prometheus Samples
# TYPE db_connects_total counter
# HELP db_connects_total Number of established initiations.
db_connects_total 4 1615130567389
# TYPE db_cache_bytes gauge
# HELP db_cache_bytes Size of collective responses.
db_cache_bytes 7600 1615130567389
# TYPE db_disk_usage_ratio gauge
db_disk_usage_ratio{device="sda"} 0.19 1615130563595
完整示例Demo
package main
import (
"net/http"
"time"
"github.com/pascaldekloe/metrics"
)
// 定义指标
var (
RequestCount = metrics.MustCounter("http_requests_total", "Total number of HTTP requests.")
ResponseTime = metrics.MustRealSample("http_response_time_seconds", "HTTP response time in seconds.")
)
func main() {
// 设置HTTP路由
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 处理请求
w.Write([]byte("Hello, World!"))
// 记录指标
RequestCount.Add(1)
ResponseTime.Set(time.Since(start).Seconds(), time.Now())
})
// 暴露指标端点
http.HandleFunc("/metrics", metrics.ServeHTTP)
// 启动服务器
http.ListenAndServe(":8080", nil)
}
性能
以下结果是在Apple M1上使用Go 1.20测量的:
name time/op
Label/sequential/4-8 14.4ns ± 0%
Label/sequential/4x4-8 17.1ns ± 0%
Label/sequential/4x4x4-8 29.6ns ± 0%
Label/parallel/4-8 85.3ns ± 2%
Label/parallel/4x4-8 89.2ns ± 1%
Label/parallel/4x4x4-8 103ns ± 0%
Get/histogram5/sequential-8 45.0ns ± 0%
Get/histogram5/2routines-8 85.1ns ± 0%
Set/real/sequential-8 5.64ns ± 0%
Set/real/2routines-8 16.5ns ± 2%
Set/sample/sequential-8 13.6ns ± 1%
Set/sample/2routines-8 38.7ns ± 7%
Add/counter/sequential-8 6.88ns ± 0%
Add/counter/2routines-8 16.1ns ± 2%
Add/integer/sequential-8 6.88ns ± 0%
Add/integer/2routines-8 16.1ns ± 1%
Add/histogram5/sequential-8 16.1ns ± 1%
Add/histogram5/2routines-8 69.5ns ± 1%
ServeHTTP/32/counter-8 687ns ± 0%
ServeHTTP/32/real-8 1.87µs ± 0%
ServeHTTP/32/integer-8 694ns ± 0%
ServeHTTP/32/histogram5-8 6.05µs ± 0%
ServeHTTP/32/label5-8 1.97µs ± 0%
ServeHTTP/32/label2x3x5-8 1.98µs ± 0%
ServeHTTP/32/sample-8 2.06µs ± 0%
ServeHTTP/1024/counter-8 18.5µs ± 0%
ServeHTTP/1024/real-8 50.9µs ± 0%
ServeHTTP/1024/integer-8 18.8µs ± 0%
ServeHTTP/1024/histogram5-8 192µs ± 0%
ServeHTTP/1024/label5-8 54.4µs ± 0%
ServeHTTP/1024/label2x3x5-8 54.4µs ± 0%
ServeHTTP/1024/sample-8 57.6µs ± 0%
更多关于golang实现指标监控与Prometheus暴露的插件库metrics的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现指标监控与Prometheus暴露的插件库metrics的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 实现指标监控与 Prometheus 暴露
在 Go 中实现指标监控并暴露给 Prometheus,我们可以使用 prometheus/client_golang
这个官方库。下面我将详细介绍如何使用这个库来实现各种类型的指标监控。
安装依赖
首先需要安装 Prometheus 客户端库:
go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promhttp
基本使用示例
1. 计数器(Counter)
计数器用于累计值,通常用于记录请求数量、任务完成数等。
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
requestsCounter = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
)
)
func init() {
// 注册指标
prometheus.MustRegister(requestsCounter)
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
requestsCounter.Inc()
w.Write([]byte("Hello, World!"))
})
// 暴露指标端点
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
2. 仪表盘(Gauge)
仪表盘用于表示可以增减的数值,如内存使用量、当前连接数等。
var (
memoryUsage = prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "memory_usage_bytes",
Help: "Current memory usage in bytes",
},
)
)
func init() {
prometheus.MustRegister(memoryUsage)
}
// 在代码中更新指标
func updateMemoryUsage() {
// 模拟获取内存使用量
mem := getMemoryUsageFromSystem()
memoryUsage.Set(float64(mem))
}
3. 直方图(Histogram)
直方图用于观察值分布,如请求延迟、响应大小等。
var (
requestDuration = prometheus.NewHistogram(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Duration of HTTP requests in seconds",
Buckets: prometheus.DefBuckets, // 使用默认桶
},
)
)
func init() {
prometheus.MustRegister(requestDuration)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
timer := prometheus.NewTimer(requestDuration)
defer timer.ObserveDuration()
// 处理请求
// ...
}
4. 摘要(Summary)
摘要类似于直方图,但直接在客户端计算分位数。
var (
responseSizes = prometheus.NewSummary(
prometheus.SummaryOpts{
Name: "http_response_size_bytes",
Help: "Size of HTTP responses in bytes",
Objectives: map[float64]float64{
0.5: 0.05, // 50th percentile with 5% tolerance
0.9: 0.01, // 90th percentile with 1% tolerance
0.99: 0.001, // 99th percentile with 0.1% tolerance
},
},
)
)
func init() {
prometheus.MustRegister(responseSizes)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
// 处理请求
// ...
// 记录响应大小
responseSizes.Observe(float64(len(responseData)))
}
带标签的指标
Prometheus 支持为指标添加标签,用于区分不同维度的数据。
var (
httpRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Number of HTTP requests",
},
[]string{"method", "path", "status"},
)
)
func init() {
prometheus.MustRegister(httpRequests)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
// 处理请求
status := 200 // 假设请求成功
// 记录带标签的指标
httpRequests.WithLabelValues(
r.Method,
r.URL.Path,
strconv.Itoa(status),
).Inc()
// ...
}
自定义注册表
默认情况下,指标会注册到全局注册表中。你也可以创建自定义注册表:
func main() {
// 创建自定义注册表
registry := prometheus.NewRegistry()
// 创建指标
counter := prometheus.NewCounter(prometheus.CounterOpts{
Name: "my_counter",
Help: "This is my counter",
})
// 注册指标
registry.MustRegister(counter)
// 暴露自定义注册表的指标
http.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
http.ListenAndServe(":8080", nil)
}
最佳实践
- 指标命名:使用下划线分隔单词,以单位作为后缀(如
_seconds
、_bytes
) - 标签选择:避免使用高基数标签(如用户ID、IP地址等)
- 初始化:在程序启动时注册所有指标
- 文档:为每个指标提供清晰的Help信息
- 性能:避免在关键路径上进行昂贵的指标计算
完整示例
package main
import (
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
httpRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
[]string{"method", "path"},
)
httpDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Duration of HTTP requests",
Buckets: []float64{0.1, 0.5, 1, 2, 5},
},
[]string{"path"},
)
activeRequests = prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "http_active_requests",
Help: "Number of active HTTP requests",
},
)
)
func init() {
prometheus.MustRegister(httpRequests)
prometheus.MustRegister(httpDuration)
prometheus.MustRegister(activeRequests)
}
func main() {
// 模拟业务处理函数
handler := func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
activeRequests.Inc()
defer activeRequests.Dec()
// 随机延迟模拟处理时间
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
// 记录请求
httpRequests.WithLabelValues(r.Method, r.URL.Path).Inc()
// 记录延迟
duration := time.Since(start)
httpDuration.WithLabelValues(r.URL.Path).Observe(duration.Seconds())
w.Write([]byte("OK"))
}
http.HandleFunc("/", handler)
http.HandleFunc("/api", handler)
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
这个示例展示了如何同时使用计数器、直方图和仪表盘来监控HTTP服务。你可以通过访问 http://localhost:8080/metrics
查看暴露的指标数据。
要集成到Prometheus中,只需在Prometheus配置中添加这个端点即可:
scrape_configs:
- job_name: 'my_go_app'
static_configs:
- targets: ['localhost:8080']