histograms and summaries直方图和总数


直方图和总数是非常复杂的度量指标类型。单个直方图或者总数不仅创建了大量的时间序列展示图,它也使得正确地使用这些度量指标类型变得非常困难。这篇文章主要帮助你挑选和合适于你的度量指标类型。

库支持 Library support

首先,检查histogramssummaries

许多库仅仅支持这直方图和总数的一种,或者仅仅以有限的方式支持summaries(缺乏分位数计算)。

Count and sum of observations 观察次数和总和

直方图和总数样本观察,通常要求持续时间或者响应大小。他们跟踪观察次数和观察值的总和,从而可以计算出观察值的平均值。请注意,观察次数(在Prometheus中显示为具有_count后缀)本质上是一个计数器(如上所述,它只会上升)。只要不存在反向观察,观察的总和(表现为_sum后缀的时间序列)就像一个计数器。显然,请求持续时间或者响应大小从不会使负数。但是,原则上你可以使用汇总和直方图来观察负数(如:温度)。在这种情况下,观察总和可能会下降,所以你不能再使用rate()

要计算最近5分钟内的平均请求持续时间(从http_request_duration_seconds的直方图和总汇),请使用以下表达式:

  1. rate(http_request_duration_seconds_sum[5m])
  2. /
  3. rate(http_request_duration_seconds_count[5m])

Apdex score 应用性能指数

直方图的直接使用(不是汇总)是对落在特定观测值中的统计计数。

你可以有一个SLA去300ms内的95%服务请求。例如:在这种情况下,请配置直方图到上限为0.3s。然后你可以直接在300ms内表达所请求的相对数量,并且如果只低于0.95,则可以轻松发出警报。以下表达式将按照过去5分钟内提供的请求的作业计算。使用成为http_request_duration_seconds的直方图收集请求持续时间。

  1. sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5])) by (job)
  2. /
  3. sum(rate(http_request_duration_seconds_count[5m])) by (job)

你可以使用类似的方式去估计Apdex score。配置目标请求持续时间为上线的桶,另外一个具有允许请求持续时间的桶(通常是目标请求持续时间的4倍)作为上限。示例:目标请求的持续时间为300ms。可容忍的请求时间为1.2s。以下表达式在过去5分钟内得到每个作业的Apdex score。

  1. (
  2. sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m])) by (job)
  3. +
  4. sum(rate(http_request_duration_seconds_bucket{le="1.2"}[5m])) by (job)
  5. ) / 2 / sum(rate(http_request_duration_seconds_count[5m])) by (job)

注意,我们划分两个数据桶的总和。原因是直方图是累计的。在le=”1.2”桶中,le=”0.3”也包含在桶中;将它除以2的正确值。

在计算与传统的Apdex score不完全一致,因为它包括计算中令人满意的和可容忍的部分中的错误。

Quatiles分位数

你可以使用汇总和直方图来计算所谓的φ-分位数,其中0<=φ<=1。φ分位数是在N个观察值中排列在数字φ*N的观察值。φ分位数的例子:0.5分位数成为中位数。0.95分位数是第95百分位数。

直方图和汇总之间的本质区别在于,总结计算客户端的流量φ分位数,并将其直接暴露出来,而直方图暴露了存储的观察值,并且使用histogram_quantile在服务器端从直方图的桶中计算分数为)功能。

这两种方法有很多不同的含义:| | Histogram | summary ||——————-|:——————————————:|———————:||所需配置 | 在观察值的范围内挑选合适的桶 |选择所需的φ-分位数和滑动窗口。其他φ-分位数和滑动窗口不能销售计算| 客户端性能 | 观察是非常低成本的,因为它们仅仅只需要增加计数器值 | 由于流分位数计算,观察是高成本的。| 服务端性能 | 服务器必须计算分位数。如果临时计算需要花费太长时间(例如:在大型面板中),则可以使用规则记录。| 低服务端成本| 时间序列数(除_sum_count系列除外)| 每个配置桶的一个时间序列 |每个配置分位数的时间序列| 分位数错误(详见下面) | 观察值的误差受到相关桶的宽度限制| φ的尺寸受限于可配置值| φ分位数和滑动时间窗的规范 | 带有Prometheus表达式的Ad-hoc | 预先由客户端配置| 聚合 | 带有Prometheus表达式的Ad-hoc | 一般不聚合

请注意表中最后一项的重要性。让我们在300ms内回到服务于95%的请求SLA。这一次, 你不想显示在300ms内提供的请求百分比,而不是显示95%请求的请求持续时间。为此,您可以配置0.95分位数的摘要,(例如)配置5分钟的衰减时间,或者在300ms的标记周围配置几个桶的直方图。 {le =“0.1”},{le =“0.2”},{le =“0.3”}和{le =“0.45”}。 如果您的服务运行复制多个实例,您将从其中每一个收集请求持续时间,然后您想将所有内容聚合到总体第95百分位数。 然而,从总结中聚合预先计算的分位数很少有意义。 在这种特殊情况下,平均分位数产生统计学无意义的值。

  1. avg(http_request_duration_seconds{quantile="0.95"}) // BAD!

使用直方图,使用histogram_quantile()函数完全可以进行聚合。

  1. histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) // GOOD.

此外,如果您的SLA更改,并且现在要绘制第90个百分位数,或者您想要考虑最后10分钟而不是最近5分钟,则只需调整上述表达式,而不需要重新配置 客户。

分位数估计误差

估算客户端或服务器端的分位数。 了解该估计的错误很重要。

继续从上面的直方图的例子,想象你通常的请求时间几乎都非常接近220毫秒,换句话说,如果你可以绘制“真实”直方图,你会看到一个非常尖锐的峰值在220毫秒。 在上面配置的普罗米修斯直方图度量中,几乎所有的观察值,因此也是第95百分位数,将落入标记为{le =“0.3”}的桶中,即桶从200ms到300ms。 直方图实现保证真正的第95百分位数在200ms到300ms之间。 要返回单个值(而不是间隔),它应用线性插值,在这种情况下可以产生295ms。 计算出的分位数给您的印象是,您接近打破SLA,但实际上,第95百分位数距离您的SLA相当舒适。

我们的思考实验的下一步:后端路由的更改为所有请求时间添加了固定的100ms量。现在,请求持续时间在320ms的急剧上升,几乎所有的观察值将从300ms降至450ms。计算第95百分位数为442.5ms,尽管正确值接近320ms。虽然你在SLA之外只有一点点,但计算出的第95个分位数看起来更糟。

至少在客户端使用适当的算法(如Go客户端使用的算法)时,总结在这两种情况下都不会计算正确的百分位数值。不幸的是,如果您需要聚合来自多个实例的观察结果,则无法使用摘要。

幸运的是,由于您对桶边界的适当选择,即使在这个具体的例子中,观察值分布非常尖锐的峰值,如果您在SLA内部或外部,则直方图能够正确识别。此外,分位数的实际值越接近我们的SLA(或换句话说,我们实际上最感兴趣的值),计算值越准确。

现在让我们再次修改实验。在新设置中,请求持续时间的分布在150ms处达到峰值,但并不像以前那样锐利,只有90%的观察值。 10%的观察结果均匀分布在150ms到450ms之间的长尾。有了这个分配,第95个百分位数正好在我们的300毫秒的SLA。使用直方图,计算的值是准确的,因为第95百分位数的值恰好与其中一个桶边界一致。即使稍微不同的值仍然是准确的,因为相关桶中的(设计的)均匀分布正是桶内的线性插值所假定的。

总结报告的分位数的误差现在变得更加有趣了。总结中的分位数的误差在φ的维度上配置。在我们的情况下,我们可能已经配置了0.95±0.01,即计算值将在94和96百分位数之间。具有上述分布的第94位分位数为270ms,第96位为330ms。总结报告的第95百分位数的计算值可以在270ms和330ms之间的间隔内的任何地方,不幸的是SLA之间的明显差异与SLA之间明显不同。

底线是:如果使用摘要,则可以控制φ的维度中的误差。如果使用直方图,则可以控制观察值的维度中的错误(通过选择适当的桶布局)。具有广泛的分布,φ的小变化导致观测值的偏差很大。具有尖锐的分布,观察值的小间隔覆盖φ的大间隔。

两个经验法则:

  • 如果需要聚合,请选择直方图。
  • 否则,如果您了解要观察的值的范围和分布,请选择直方图。 如果您需要准确的分位数,无论值的范围和分布如何,请选择摘要。

如果我的客户端库不支持我需要的指标类型,该怎么办

实施吧! 欢迎代码贡献。 一般来说,我们预计直方图比摘要更为迫切。 直方图在客户端库中也更容易实现,因此如果有疑问,我们建议首先实现直方图。