Histograms and summaries
是更复杂的度量标准类型。 单个Histogram
或summary
不仅会创建大量时间序列,而且正确使用这些度量标准类型也更加困难。 本节帮助您为用例选择和配置适当的度量标准类型。
首先,检查库支持histograms和summaries。
许多库仅仅支持histograms
和summary
的一种,或者仅仅以有限的方式支持summaries
(缺乏分位数计算)。
Histograms and summaries
都是样本观察,通常是请求持续时间或响应大小。 它们跟踪观测数量和观测值之和,使您可以计算观测值的平均值。 请注意,观察的数量(在Prometheus中显示为带有_count
后缀的时间序列)本质上是一个计counter
(如上所述,它只会上升)。 只要没有负面观察,观察总和(显示为带有_sum
后缀的时间序列)的行为就像一个counter
。 显然,请求持续时间或响应大小永远不会消极。 但是,原则上,您可以使用Histograms and summaries
来观察负值(例如摄氏温度)。 在这种情况下,观察的总和可能会下降,因此您不能再对它应用rate()
。
要从名为http_request_duration_seconds
的Histograms and summaries
计算过去5分钟内的平均请求持续时间,请使用以下表达式:
rate(http_request_duration_seconds_sum[5m])
/
rate(http_request_duration_seconds_count[5m])
Histograms
(但不是summaries
)的直接使用是计算落入特定观察值桶的观察值。
您可能拥有SLA,可在300毫秒内为95%的请求提供服务。 在这种情况下,将Histogram
配置为具有上限为0.3秒的存储桶。 然后,您可以直接表达300毫秒内提供的相对请求数量,如果值低于0.95,则可以轻松发出警报。 以下表达式按job
计算最近5分钟内提供的请求。 使用名为http_request_duration_seconds
的Histograms
收集请求持续时间。
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m])) by (job)
/
sum(rate(http_request_duration_seconds_count[5m])) by (job)
您可以用类似的方式估算出著名的Apdex分数。 配置目标请求持续时间为上限的桶,以及容忍请求持续时间(通常为目标请求持续时间的4倍)的另一个桶作为上限。 示例:目标请求持续时间为300毫秒。 可容忍的请求持续时间为1.2秒。 以下表达式生成过去5分钟内每个job
的Apdex分数:
(
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m])) by (job)
+
sum(rate(http_request_duration_seconds_bucket{le="1.2"}[5m])) by (job)
) / 2 / sum(rate(http_request_duration_seconds_count[5m])) by (job)
请注意,我们除以两个桶的总和。 原因是Histograms
桶是累积的。 le="0.3"
桶也包含在le="1.2"
桶中; 将它除以2校正。
该计算与传统的Apdex分数不完全匹配,因为它包括计算的满意和可容忍部分中的误差。
您可以使用Histograms and summaries
来计算所谓的φ-分位数,其中0≤φ≤1
。-分位数是在N个观测值中按数量φ* N
排序的观测值。 φ
-分位数的示例:0.5分位数称为中值。 0.95分位数是第95百分位数。
Histograms and summaries
之间的本质区别在于summaries
计算客户端的流式φ-分位数并直接暴露它们,而histograms
显示分段观察计数,histograms
桶的分位数计算在服务器端使用histogram_quantile()
函数进行。
这两种方法有许多不同的含义:
Histogram | summary | |
---|---|---|
所需配置 | 在观察值的范围内挑选合适的桶 | 选择所需的φ-分位数和滑动窗口。其他φ-分位数和滑动窗口不能销售计算 |
客户端性能 | 观察是非常低成本的,因为它们仅仅只需要增加计数器值 | 由于流分位数计算,观察是高成本的。 |
服务端性能 | 服务器必须计算分位数。如果临时计算需要花费太长时间(例如:在大型面板中),则可以使用规则记录。 | 低服务端成本 |
时间序列数(除_sum 和_count 系列除外) |
每个配置桶的一个时间序列 | 每个配置分位数的时间序列 |
分位数错误(详见下面) | 观察值的误差受到相关桶的宽度限制 | φ的尺寸受限于可配置值 |
φ分位数和滑动时间窗的规范 | 带有Prometheus表达式的Ad-hoc | 预先由客户端配置 |
聚合 | 带有Prometheus表达式的Ad-hoc | 一般不聚合 |
请注意表中最后一项的重要性。 让我们回到SLA,在300ms内提供95%的请求。 这次,您不希望显示在300毫秒内提供的请求的百分比,而是显示第95百分位数,即您为95%的请求提供服务的请求持续时间。 要做到这一点,您可以配置一个带有0.95分位数的总数和(例如)一个5分钟的衰减时间,或者在300ms标记周围配置几个桶的Histogram
,例如: {le="0.1"}
,{le="0.2"}
,{le="0.3"}
和{le="0.45"}
。 如果您的服务使用多个实例进行复制,您将从每个实例中收集请求持续时间,然后您希望将所有内容聚合到整体的第95个百分位。 但是,从summaries
中汇总预先计算的分位数很少有意义。 在这种特殊情况下,对分位数求平均值会产生统计上无意义的值。
avg(http_request_duration_seconds{quantile="0.95"}) // BAD!
使用直方图,使用histogram_quantile()
函数完全可以进行聚合。
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) // GOOD.
此外,如果您的SLA发生变化并且您现在想要绘制第90个百分点,或者您想要考虑最后10分钟而不是最后5分钟,您只需要调整上面的表达式而您不需要重新配置客户端。
计算客户端或服务器端的分位数。了解该估计的错误非常重要。
继续上面的histograms
示例,假设您的通常请求持续时间几乎都非常接近220ms,或者换句话说,如果您可以绘制“真实”直方图,您会看到220ms处的非常尖锐的尖峰。在如上配置的Prometheus histograms
度量中,几乎所有观测值以及因此第95百分位数将落入标记为{le="0.3"}
的桶中,即桶从200ms到300ms。直方图实现保证真正的第95百分位数介于200ms和300ms之间。为了返回单个值(而不是间隔),它应用线性插值,在这种情况下产生295ms。计算出的分位数给你的印象是你已经接近打破SLA,但实际上,第95百分位数略高于220毫秒,与你的SLA相当舒适。
我们的思想实验的下一步:后端路由的更改会为所有请求持续时间添加固定的100毫秒。现在请求持续时间在320毫秒处急剧上升,几乎所有观测值都将从300毫秒降至450毫秒。计算出第95百分位数为442.5ms,但正确值接近320ms。虽然你只是SLA之外的一小部分,但计算出的第95个分位数看起来更糟糕。
在两种情况下,总结都没有问题计算正确的百分位数值,至少如果它在客户端使用适当的算法(就像Go客户端使用的算法)。遗憾的是,如果您需要汇总来自多个实例的观察结果,则无法使用总数。
幸运的是,由于您适当选择了桶边界,即使在这个设计的观测值分布非常尖锐的示例中,如果您在SLA内部或外部,直方图也能够正确识别。此外,分位数的实际值越接近我们的SLA(或换句话说,我们实际上最感兴趣的值),计算值变得越准确。
现在让我们再次修改实验。在新设置中,请求持续时间的分布具有150ms的峰值,但它不像以前那么尖锐,仅包含90%的观测值。 10%的观察结果均匀地分布在150ms到450ms之间的长尾中。通过该分布,第95百分位正好恰好在我们的300毫秒的SLA。使用直方图,计算出的值是准确的,因为第95百分位的值恰好与其中一个桶边界重合。即使稍微不同的值仍然是准确的,因为相关桶内的(人为的)均匀分布正是桶内的线性插值所假设的。
summaries
报告的分位数误差现在变得更加有趣。summaries
中的分位数的误差在φ的维度中配置。在我们的例子中,我们可能已经配置了0.95±0.01,即计算值将在第94百分位和第96百分位之间。具有上述分布的第94个分位数是270ms,第96个分位数是330ms。摘要报告的第95百分位数的计算值可以是270毫秒到330毫秒之间的任何位置,不幸的是,在SLA中明显不同于SLA之外的所有区别。
底线是:如果使用summaries
,则控制φ维度中的误差。如果使用直方图,则可以控制观察值维度中的误差(通过选择适当的铲斗布局)。由于分布广泛,φ的微小变化导致观察值的偏差很大。通过明显的分布,观察值的小间隔覆盖了大的φ间隔。
两个经验法则:
- 如果需要聚合,请选择
histograms
。 - 否则,如果您了解要观察的值的范围和分布,请选择
histgorams
。 如果您需要准确的分位数,无论值的范围和分布如何,请选择summarirs
。
实施它! 代码贡献是受欢迎的。 一般来说,我们希望直方图比总数更迫切需要。 直方图也更容易在客户端库中实现,因此我们建议首先实现直方图,如果有疑问的话。