一 Prometheus 指标类型
Prometheus的4种metrics(指标)类型:
- Counter 只增不减的计数器
- Gauge 可增减的仪表盘
- Histogram
- Summary
2.1 Counter 与 Gauge
在记录相同监控指标时,最基础的有两类指标,分别是Counter和Gauge。
Counter 用于表示那些只会增加的值,比如已处理的 HTTP 请求总数。而 Gauge 则用于表示那些可以增加或减少的值,比如机器的 CPU 使用率,GPU 的温度等。
例如,如果你想监控一个服务的 HTTP 请求量,你可以使用 Counter 类型的指标,因为这个数值只会随着时间的推移而增加。但如果你想监控机器的 CPU 使用率,你应该使用 Gauge 类型的指标,因为 CPU 使用率是一个随时都可能变化的值。
Counter 是一个单调递增的计数器,只有在机器重启等情况会清空重新计算。所以可以通过该类型的指标观察一些指标的变化速率。
例如,通过rate()函数获取HTTP请求量的增长率:
rate(http_requests_total[5m])
查询当前系统中,访问量前10的HTTP地址:
topk(10, http_requests_total)
Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常用的查询使用方式如下:
通过Gauge指标,用户可以直接查看系统的当前状态:
node_memory_MemFree
2.2 Histogram和Summary
除了Counter和Gauge类型的监控指标以外,Prometheus还定义了Histogram和Summary的指标类型。Histogram和Summary主用用于统计和分析样本的分布情况。
长尾效应的影响:某些使用场景中,我们可能更关注平均值,如接口的平均响应时间。但是如果大多数响应时间都是 100ms,但是有几个响应时间在 1m,平均响应时间就会被拉高到一个不真实的值。所以这个时候我们需要对指标值在不同的区间进行分组。例如,统计延迟在0~10ms之间的请求数有多少而10~20ms之间的请求数又有多少。这样可以更符合真实的使用场景,还可以通过 promQL 查询出指标的 90 分位、95 分位、99 分位的响应耗时分别是多少。
Histogram
- 核心机制:
- 客户端将观测值(如请求延迟)分配到预定义的桶(Bucket) 中,例如
[0.1s, 0.5s, 1s]。 - 服务端存储每个桶的累计计数(
_bucket)、总和(_sum)和总数(_count)。 - 查询时通过
histogram_quantile()函数计算分位数。
- 指标示例:
其中 label 中有le,含义为小于等于(less than or equal to),表示直方图的分桶(Bucket)的上界值。
指标的含义是落在这个桶区间的请求数量,而不是具体的耗时。
histogram_quantile() 返回的结果是估算的 P99 响应时间。由于直方图是用固定的桶来分组的,因此结果是基于这些桶的上限进行插值计算的,所以是一个近似值,而不是绝对精确的值。http_request_duration_seconds_bucket{le="0.1"} 20 # 延迟 ≤0.1s 的请求数 http_request_duration_seconds_bucket{le="0.5"} 50 # 延迟 ≤0.5s 的请求数 http_request_duration_seconds_bucket{le="+Inf"} 100 # 所有请求总数(_count) http_request_duration_seconds_sum 45.6 # 总延迟时间 http_request_duration_seconds_count 30 # 总请求次数
- 分位数计算:
注意:_bucket类型应该是一个单调递增的数据,所以在求分位数时,使用 rate 来计算增长速率。
# 计算 P99 延迟 histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])
Summary
- 核心机制:
- 客户端直接计算预定义的分位数(如 P50、P99),并将结果暴露给服务端。查询
- 服务端存储分位数值(
{quantile="<φ>"})、总和(_sum)和总数(_count)。 - 分位数在客户端计算,查询时无法调整。
- 指标示例:
http_request_duration_seconds{quantile="0.5"} 0.2 # P50 延迟 http_request_duration_seconds{quantile="0.99"} 0.8 # P99 延迟 http_request_duration_seconds_sum 45.6 # 总延迟时间 http_request_duration_seconds_count 100 # 总请求数
而这两种指标的区别在于,Summary 指标的分位数固定。Histogram 可以查询不同的分位数。
以下是官方文档中对应的介绍:‣
二 不同语言埋点方式
以下给出不同的语言中就行埋点的方式,便于快速进行埋点使用。
3.1 Counter
特性
- 单调递增的数值(只能增加或重置为 0)。
- 适用于统计累计事件(如请求总数、错误次数)。
- 支持
inc()和add()操作。
埋点方式
Go:
import ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) // 定义 Counter var httpRequestsTotal = prometheus.NewCounter( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests.", }, ) func init() { prometheus.MustRegister(httpRequestsTotal) } func handler(w http.ResponseWriter, r *http.Request) { httpRequestsTotal.Inc() // 每次请求 +1 w.Write([]byte("OK")) } func main() { http.Handle("/metrics", promhttp.Handler()) http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }
Java:
import io.micrometer.core.instrument.Counter; import io.micrometer.prometheus.PrometheusMeterRegistry; import io.prometheus.client.CollectorRegistry; import io.prometheus.client.exporter.HTTPServer; // 使用 Micrometer PrometheusMeterRegistry registry = new PrometheusMeterRegistry(); Counter httpRequestsTotal = Counter.builder("http_requests_total") .description("Total HTTP requests") .register(registry); // 埋点 httpRequestsTotal.increment();
Python:
from prometheus_client import Counter, start_http_server http_requests_total = Counter( 'http_requests_total', 'Total HTTP requests' ) if __name__ == '__main__': start_http_server(8000) while True: http_requests_total.inc() # 每次请求 +1
3.2 Gauge
特性
- 可增可减的瞬时值(如内存使用量、并发连接数)。
- 支持
inc(),dec(),set()和add()操作。
埋点方式
Go
var memoryUsage = prometheus.NewGauge( prometheus.GaugeOpts{ Name: "memory_usage_bytes", Help: "Current memory usage in bytes.", }, ) // 更新值 memoryUsage.Set(getCurrentMemoryUsage())
Java
Gauge.builder("memory_usage_bytes", this, MyClass::getCurrentMemoryUsage) .description("Memory usage in bytes") .register(registry);
python
memory_usage = Gauge('memory_usage_bytes', 'Memory usage in bytes') memory_usage.set(get_current_memory_usage())
3.3 Histogram
特性
- 对观测值(如请求延迟)进行分桶统计。
- 提供
_bucket(各桶计数)、_sum(总和)、_count(总数)三个指标。
- 分位数需在查询时通过
histogram_quantile计算。
埋点示例
Go
var requestDuration = prometheus.NewHistogram( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "Request duration in seconds.", Buckets: prometheus.DefBuckets, // 默认桶 [.005, .01, .025, ..., 10] }, ) // 记录时间 start := time.Now() defer func() { requestDuration.Observe(time.Since(start).Seconds()) }()
Java
Timer.builder("http_request_duration_seconds") .description("Request duration in seconds") .serviceLevelObjectives(0.1, 0.5, 1.0) // 自定义桶 .register(registry) .record(() -> handleRequest());
python
from prometheus_client import Histogram REQUEST_DURATION = Histogram( 'http_request_duration_seconds', 'Request duration in seconds', buckets=[0.1, 0.5, 1.0] ) @REQUEST_DURATION.time() def handle_request(): pass