從 Prometheus共同創造者Julius Volz的文章
介绍
Prometheus 是一个开源监控系统和时间序列数据库。在 How To Query Prometheus on Ubuntu 14.04 Part 1,我们设置了三个演示服务实例,向 Prometheus 服务器曝光合成指标。使用这些指标,我们然后学会了如何使用 Prometheus 查询语言来选择和过滤时间序列,如何在尺寸上汇总,以及如何计算率和衍生品。
在本教程的第二部分中,我们将从第一部分建立在设置上,并学习更多先进的查询技术和模式. 在本教程之后,您将知道如何应用基于价值的过滤,设置操作,历史图和更多。
前提条件
本教程是基于在 [如何在Ubuntu 14.04 Part 1 上查询Prometheus]中描述的设置(/community/tutorials/how-to-query-prometheus-on-ubuntu-14-04-part-1)中描述的。至少,您需要遵循该教程的步骤 1 和步骤 2 来设置一个Prometheus服务器和三个监控的演示服务实例。然而,我们也将建立在第一部分中解释的查询语言技术上,因此建议完全通过它工作。
步骤 1 – 通过值过滤和使用门槛
在本节中,我们将学习如何根据其值过滤返回的时间序列。
基于价值的过滤最常见的用途是简单的数字警报门槛,例如,我们可能希望找到具有高于每秒0.2 的总500
状态请求率的HTTP路径,作为过去15分钟的平均值。
1rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[15m]) > 0.2
在 Console视图中,结果应该是这样的:
然而,与二进制算法一样,Prometheus不仅支持单个尺度数的过滤。您还可以过滤一组时间序列基于另一组序列。 再一次,元素被标签组合匹配,并在匹配元素之间应用过滤操作器。 只有匹配右侧元素的左侧元素和通过过滤器的元素成为输出的一部分。 on(<labels>)
、 group_left(<labels>)
、 group_right(<labels>)
条款在这里与算术操作器一样工作。
例如,我们可以选择任何工作
、实例
、方法
和路径
组合的500
状态率,其中200
状态率不低于500
状态率的至少50倍:
1rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[5m]) * 50
2> on(job, instance, method, path)
3 rate(demo_api_request_duration_seconds_count{status="200",job="demo"}[5m])
这将看起来如下:
除了>
之外,普罗梅斯还支持常见的>=
,<=
,<``,
!=和
==`比较运算符用于过滤。
现在我们知道如何根据单个数字值过滤一组时间序列,或者基于与匹配标签的其他时间序列值。
步骤 2 – 使用集操作员
在本节中,您将学习如何使用 Prometheus 的集操作符来对应时间序列的集合。
通常你想过滤一组时间序列基于另一组。 为此,Prometheus提供和
序列操作员。对于操作员左侧的每个序列,它试图在右侧找到一系列具有相同标签的序列。
例如,您可能想选择任何 HTTP 终端点,其百分位延迟高于 50ms (0.05s),但仅适用于每秒接收超过一个请求的维度组合。我们将使用 histogram_quantile()
函数来计算百分位。 在下一节中,我们将准确地解释这些函数的功能。 目前,它只会计算每个子维度的百分位延迟。 为了过滤结果的坏延迟,并只保留每秒接收超过一个请求的函数,我们可以查询:
1histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])) > 0.05
2and
3 rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 1
与此相反,有时你想从两个时间序列组建一个联盟,Prometheus为此提供了或
设置操作员,结果是操作的左侧的序列,以及右侧的任何没有左侧相匹配标签的序列。
1rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) < 10
2or
3 rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 30
结果将在图表中看起来像这样:
正如您所看到的,在图表中使用值过滤器和设置操作可以导致时间序列在同一个图表中出现和消失,取决于它们是否匹配过滤器或不随时沿着图表步行。
现在你知道如何从标记的时间序列中构建交叉点和联盟。
步骤 3 – 使用历史图
在本节中,我们将学习如何解释 histogram 指标,以及如何从它们中计算量子(百分位的通用形式)。
Prometheus 支持 histogram metrics,这允许服务记录一系列值的分布。 Histograms 通常跟踪请求延迟或响应大小等测量,但基本上可以跟踪任何根据某些分布大小波动的值。
在内部, histograms 是以一组时间序列来实现的,每个时间序列代表了给定桶的计数(例如10ms以下的请求
,25ms以下的请求
,50ms以下的请求
,等等)。 桶计数是累积的,这意味着较大的值的桶包括所有低值的桶的计数。 在每个时间序列中,它是 histogram的一部分,相应的桶被标记为特殊的le
(比或等级)标签。
例如,我们的演示服务导出一个 histogram demo_api_request_duration_seconds_bucket
来跟踪 API 请求持续时间的分布,因为这个 histogram 导出每条被跟踪的子维度 26 桶,所以这个指标有很多时间序列。
1demo_api_request_duration_seconds_bucket{instance="localhost:8080",method="POST",path="/api/bar",status="200",job="demo"}
你应该看到26个系列,每个系列代表一个观测桶,标记为le
:
一个 histogram 可以帮助你回答问题,如我的请求需要多少时间超过 100ms 才能完成?
(假设 histogram 具有具有 100ms 边界的桶配置)。另一方面,你通常会想回答一个相关的问题,如我的请求的 99% 的延迟是多少?
如果你的 histogram 桶足够细粒,你可以使用histogram_quantile()
函数来计算这个函数。这个函数预计一个 histogram 计数(一组具有le
桶标签的序列)作为其输入和输出相应的量子。 与从 0 到 100 个百分位的百分位相反,指定的histogram_quantile()
函数预期作为输入的目标量子范围从 0 到 1 个百分位(因此 90 个百分位将匹配到
例如,我们可以尝试计算所有维度的 90 个百分位 API 延迟,如下:
1# BAD!
2histogram_quantile(0.9, demo_api_request_duration_seconds_bucket{job="demo"})
这不是非常有用的或可靠的。当单个服务实例重新启动时,桶计重新设置,你通常想要看到延迟是现在
的(例如,根据过去5分钟的测量),而不是整个指标的时间。
在过去的 5 分钟中计算 90 个百分位 API 延迟如下:
1# GOOD!
2histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m]))
它会更好,看起来像这样:
然而,这显示了每一个子维度(‘job’、‘instance’,‘path’,‘method’和‘status’)的第90个百分位数。我们可能对所有这些维度都没有兴趣,并且想将其中一些汇总出来。
以下查询计算了第 90 个百分位延迟,但只将结果分为工作
、实例
和路径
维度:
1histogram_quantile(
2 0.9,
3 sum without(status, method) (
4 rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])
5 )
6)
<$>[注]
注:在应用histogram_quantile()
函数之前,在任何集合中始终保留le
桶标签。
图表现在将看起来像这样:
从历史图计算量子总是会引入一些统计错误. 此错误取决于您的桶大小,观察到的值的分布以及您要计算的目标量子。
现在你知道如何解释 histogram 指标,以及如何从它们中计算不同时间范围的量子,同时在飞机上对某些维度进行汇总。
步骤 4 – 使用 Timestamp Metrics 工作
在本节中,我们将学习如何使用包含时间标记的指标。
例如,这可能是最后一次成功完成批量任务,最后一次成功重新加载配置文件,或者当机器启动时。
例如,演示服务揭示了上一次模拟批量工作成功的次数:
1demo_batch_last_success_timestamp_seconds{job="demo"}
此批量任务被模拟为每分钟运行一次,但在所有尝试中有 25% 失败. 在失败的情况下, demo_batch_last_success_timestamp_seconds
指标保留其最后值,直到另一个成功运行发生。
如果你绘制了原始时间标记,它将看起来有点像这样:
正如您所看到的,原始时刻印值通常本身并不非常有用,相反,您通常想要知道时刻印值的年龄是多少。
1time() - demo_batch_last_success_timestamp_seconds{job="demo"}
这是自上次成功的批次工作运行以来的秒数时间:
如果你想将这个年龄从秒转换为小时,你可以把结果分为‘3600’:
1(time() - demo_batch_last_success_timestamp_seconds{job="demo"}) / 3600
这样一个表达式对图表和警报都是有用的。当您像上面那样可视化时刻印的年龄时,您会收到一个牙图表,线性增加的线条和定期重置到0
,当批次任务成功完成时。如果牙尖峰变得太大,这表明一批没有完成很长一段时间的任务。您也可以通过添加一个>
门槛过滤器来警告表达式并警告所产生的时间序列(尽管我们不会在本教程中涵盖警报规则)。
若要简单列出在过去 1.5 分钟内未完成批量任务的实例,可以运行以下查询:
1time() - demo_batch_last_success_timestamp_seconds{job="demo"} > 1.5 * 60
现在你知道如何将原始时间标记指标转换为相对年龄,这对图表和警报都是有用的。
步骤 5 — 排序和使用 topk / bottomk 函数
在此步骤中,您将学习如何排序查询输出,或者只选择一组系列中最大的或最小的值。
在表格 Console 视图中,将输出序列按其值进行排序通常是有用的。 您可以通过使用 sort()
(上升排序) 和 sort_desc()
(下降排序) 函数来实现这一目标。
1sort_desc(sum by(path) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))
排序的输出将看起来像这样:
或者你甚至不感兴趣显示所有系列,但只有 K 最大的或最小的系列。 为此,Prometheus 提供了 topk()
和 bottomk()
函数. 它们每一个都采取一个 K 值(你想要选择多少系列)和一个任意表达式,返回了一组需要过滤的时间系列。 例如,要显示每条路径和方法的三大请求率,你可以查询:
1topk(3, sum by(path, method) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))
虽然排序在 Console 视图中仅有用,但在图表中也可能有用,但要注意,输出不会显示整个图表时间范围内的顶部或底部 K 序列,而输出会重新计算图表的每一个分辨率步骤的顶部或底部 K 序列。
现在我们学会了如何排序或只选择K最大的或最小的系列。
步骤6 - 检查废弃物的健康状况
在此步骤中,我们将学习如何随着时间的推移检查我们的实例的废物健康。
为了使该部分更有趣,让我们终止您三个背景演示服务实例中的第一个(听到端口8080的实例):
1pkill -f -- -listen-address=:8080
每当Prometheus扫描一个目标时,它都会存储一个合成样本,其指标名为上
以及被扫描的实例的工作
和实例
标签。如果扫描成功,样本的值将设置为1
。如果扫描失败,它将设置为0
。
1up{job="demo"}
這現在應該顯示一個例子如下:
要显示 only down 实例,您可以过滤为值 0
:
1up{job="demo"} == 0
现在您只应该看到您终止的实例:
或者,以获取下列实例的总数:
1count by(job) (up{job="demo"} == 0)
这将向你展示一个1
的计数:
这些类型的查询对于基本的废物健康警报是有用的。
<$>[注]
**注:当没有下行实例时,此查询返回一个空的结果,而不是一个单一的输出序列,其计数为 0
. 这是因为 count()
是一个聚合运算器,它将一组维度时间序列作为其输入,并可以根据通过
或没有
条款组合输出序列。
你现在知道如何查询例如健康状况。
结论
在本教程中,我们建立在 How To Query Prometheus on Ubuntu 14.04 Part 1的进度上,并涵盖了更先进的查询技术和模式。
虽然这些教程不能涵盖所有可能的查询使用案例,但我们希望示例查询对您在使用 Prometheus 构建现实世界的查询、仪表板和警报时有用。