一个可靠的例子将很好地解释histogram_quantile。
假设:
-
只有一个系列为简单起见
- 10 个桶用于度量
http_request_duration_seconds。
10ms、50ms、100ms、200ms、300ms、500ms、1s、2s、3s、5s
-
http_request_duration_seconds 是 COUNTER 的度量类型
| time |
value |
delta |
rate (quantity of items) |
| t-10m |
50 |
N/A |
N/A |
| t-5m |
100 |
50 |
50 / (5*60) |
| t |
200 |
100 |
100 / (5*60) |
| ... |
... |
... |
... |
- 我们至少有两个系列的抓取,覆盖 5 分钟,供
rate() 计算每个存储桶的 quantity
rate_xxx(t) = (value_xxx[t]-value_xxx[t-5m]) / (5m*60) 是quantity of items 的[t-5m, t]
- 我们正在查看 2 个样本(
value(t) 和 value(t-5m))。
-
记录了
10000http 请求时长(items),即
10000 = rate_10ms(t) + rate_50ms(t) + rate_100ms(t) + ... + rate_5s(t)。
| bucket(le) |
10ms |
50ms |
100ms |
200ms |
300ms |
500ms |
1s |
2s |
3s |
5s |
+Inf |
| range |
~10ms |
10~50ms |
50~100ms |
100~200ms |
200~300ms |
300~500ms |
500ms~1s |
1~2s |
2s~3s |
3~5s |
5s~ |
| rate_xxx(t) |
3000 |
3000 |
1500 |
1000 |
800 |
400 |
200 |
40 |
30 |
5 |
5 |
桶是直方图的本质。我们只需要rate_xxx(t)中的10个数字来进行分位数计算
让我们仔细看看这个表达式(为简单起见,省略了像 sum() 这样的聚合)
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
我们实际上是在从bucket=10ms 到bucket=+Inf 的rate_xxx(t) 中寻找95%th 项目。 95%th 在这里表示9500th,因为我们总共得到了10000 个项目(10000 * 0.95)。
从上表可以看出,bucket=500ms之前有9300 = 3000+3000+1500+1000+800项。
所以9500th 项目是bucket=500ms(range=300~500ms) 中的200th 项目(9500-9300),其中包含400 项目
Prometheus 假设桶中的项目以线性模式均匀分布。
bucket=500ms 中 200th 项的度量值是 400ms = 300+(500-300)*(200/400)
也就是说,95% 是 400ms。
有几点需要注意
- 直方图指标类型的指标本质上应该是
COUNTER
- 用于分位数计算的系列应始终得到标签
le 已定义
- 特定存储桶中的项目(数据)以线性模式均匀分布(例如:300~500ms)
Prometheus 至少做出了这个假设
- 分位数计算需要按升序/降序对桶进行排序(定义)(例如:1ms
-
histogram_quantile 的结果是一个近似值
附:
由于Items (Data) in a specific bucket spread evenly a linear pattern的假设,度量值并不总是accurate
说,bucket=500ms(range=300~500ms) 中的实际最长持续时间(例如:来自 nginx 访问日志)是310ms,但是,我们将通过上述设置从histogram_quantile 获得400ms,这是相当不错的有时令人困惑。
桶距越小,approximation 越准确。
因此,请设置适合您需求的铲斗距离。