Prometheus是一个开源监控系统和时间序列数据库。在如何在Ubuntu 14.04第1部分中查询Prometheus,我们设置了三个演示服务实例,向Prometheus服务器公开合成度量。使用这些指标,我们学习了如何使用Prometheus查询语言来选择和过滤时间序列,如何聚合维度,以及如何计算费率和衍生物。
在本教程的第二部分中,我们将从第一部分开始构建设置,并学习更高级的查询技术和模式。在本教程之后,您将了解如何应用基于值的过滤,设置操作,直方图等。
要完成本教程,您需要具备一台已经设置好可以使用sudo
命令的非root账号的Ubuntu 服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。
本教程基于如何在Ubuntu 14.04第1部分上查询Prometheus中概述的设置。至少,您需要按照该教程中的步骤1和步骤2来设置Prometheus服务器和三个受监控的演示服务实例。但是,我们还将在第一部分中解释的查询语言技术的基础上进行构建,从而建议完全使用它。
在本节中,我们将学习如何根据其值过滤返回的时间序列。
基于值的过滤最常见的用途是简单的数字警报阈值。例如,我们可能希望找到总500
-status请求率高于每秒0.2的HTTP路径,这是过去15分钟内的平均值。为此,我们只需查询所有500
-status请求率,然后在表达式的末尾附加一个过滤器运算符> 0.2
:
rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[15m]) > 0.2
在Console视图中,结果应如下所示:
但是,与二进制算法一样,Prometheus不仅支持通过单个标量数进行过滤。您还可以根据另一组系列过滤一组时间序列。同样,元素由其标签集匹配,并且过滤器运算符应用于匹配元素之间。只有左侧的元素与右侧的元素匹配且通过滤波器的元素才成为输出的一部分。on(<labels>)
,group_left(<labels>)
,group_right(<labels>)
子句在这里以算术运算符相同的方式工作。
例如,我们可以选择500
-status率为任何job
,instance
,method
,和path
组合的量,200
-status率不高于至少50倍500
-status率,类似这样:
rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[5m]) * 50
> on(job, instance, method, path)
rate(demo_api_request_duration_seconds_count{status="200",job="demo"}[5m])
这将如下所示:
除了>
,prometheus还支持通常>=
,<=
,<
,!=
,和==
比较操作符用于过滤用途。
我们现在知道如何基于单个数值或基于具有匹配标签的另一组时间序列值来过滤一组时间序列。
在本节中,您将学习如何使用Prometheus的集合运算符来相互关联时间序列集。
通常,您希望根据另一组过滤一组时间序列。为此,Prometheus提供了and
集合运算符。对于操作员左侧的每个系列,它会尝试在右侧找到具有相同标签的系列。如果找到匹配项,则左侧系列成为输出的一部分。如果右侧不存在匹配的系列,则从输出中省略该系列。
例如,您可能希望选择任何具有高于50毫秒(0.05秒)的90%延迟的HTTP端点,但仅限于每秒接收多个请求的维度组合。我们将在此处使用histogram_quantile()
函数进行百分位数计算。我们将在下一节中解释这个功能的确切作用。目前,它只计算每个子维度的第90百分位延迟。要过滤导致的错误延迟并仅保留每秒接收多个请求的延迟,我们可以查询:
histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])) > 0.05
and
rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 1
有时你想要从两组时间序列中构建联合,而不是采用交集。Prometheus为此提供了集合运算符 or
。它导致操作的左侧系列,以及右侧的任何左侧没有匹配标签组的系列。例如,要列出低于10或高于30的所有请求率,请查询:
rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) < 10
or
rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 30
结果将在图表中显示如下:
如您所见,在图表中使用值过滤器和设置操作可能会导致时间序列出现并在同一图表中消失,具体取决于它们是否与图表中的任何时间步骤匹配。通常,建议仅将此类过滤器逻辑用于警报规则。
您现在知道如何使用标记的时间序列构建交叉点和联合。
在本节中,我们将学习如何解释直方图度量以及如何从中计算分位数(百分位数的一般形式)。
Prometheus支持直方图指标,允许服务记录一系列值的分布。直方图通常跟踪请求延迟或响应大小等测量值,但可以从根本上跟踪根据某种分布在幅度上波动的任何值。Prometheus直方图在客户端采样数据,这意味着他们使用许多可配置(例如延迟)存储区计算观察值,然后将这些存储桶作为单独的时间序列公开。
在内部,直方图被实现为一组时间序列,每个时间序列表示给定桶的计数(例如“10ms以下的请求”,“25ms以下的请求”,“50ms以下的请求”等)。存储桶计数器是累积的,这意味着较大值的存储桶包括所有较低值存储桶的计数。在作为直方图一部分的每个时间序列上,相应的桶由特殊的le
(小于或等于)标签指示。这会为您已跟踪的任何现有维度添加额外维度。
例如,我们的演示服务导出一个跟踪API请求持续时间分布的直方图demo_api_request_duration_seconds_bucket
。由于此直方图为每个跟踪的子维度导出26个存储桶,因此该指标具有大量时间序列。让我们首先从一个实例中查看一种类型的请求的原始直方图:
demo_api_request_duration_seconds_bucket{instance="localhost:8080",method="POST",path="/api/bar",status="200",job="demo"}
您应该看到26个系列,每个系列代表一个观察桶,由le
标签标识:
直方图可以帮助您回答诸如“我的请求中有多少要求完成时间超过100毫秒?”之类的问题。(如果直方图配置了一个具有100ms边界的桶)。另一方面,您经常希望回答一个相关问题,例如“99%的查询完成的延迟是多少?”。如果你的直方图桶足够精细,你可以使用histogram_quantile()
函数计算它。此函数需要直方图度量(一组带有le
桶标签的系列)作为其输入并输出相应的分位数。在对比百分,其范围从第0到第100个百分位数,即目标位数规范histogram_quantile()
函数期望作为输入的范围是从0
到1
(所以第90百分位数将对应于的分位数0.9
)。
例如,我们可以尝试计算所有维度的90%百分位API延迟,如下所示:
# BAD!
histogram_quantile(0.9, demo_api_request_duration_seconds_bucket{job="demo"})
这不是非常有用或可靠。当重新启动单个服务实例时,存储区计数器会重置,并且您通常希望查看“现在”的延迟(例如,在过去5分钟内测量的),而不是指标的整个时间。您可以通过将rate()
函数应用于基础直方图桶计数器来实现此目的,这些计数器既处理计数器重置,也仅考虑每个桶在指定时间窗口内的增加率。
计算过去5分钟内90%的API延迟,如下所示:
# GOOD!
histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m]))
这样会好得多,看起来像这样:
然而,这说明你的第90百分位的每个子维度(job
,instance
,path
,method
,和status
)。同样,我们可能不会对所有这些维度感兴趣,并希望将其中一些维度聚合在一起。幸运的是,Prometheus的sum
聚合运算符可以与histogram_quantile()
函数一起组合,以允许我们在查询时间内聚合维度!
下面的查询计算第90百分位的延迟,但只能通过job
, instance
和path
尺寸拆分结果:
histogram_quantile(
0.9,
sum without(status, method) (
rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])
)
)
注意:le
在应用histogram_quantile()
功能之前,始终在任何聚合中保留存储桶标签。这确保了它仍然可以对桶组进行操作并从中计算分位数。
该图现在看起来像这样:
从直方图计算分位数总是会引入一定量的统计误差。此错误取决于您的铲斗尺寸,观测值的分布以及您要计算的目标分位数。
您现在知道如何解释直方图度量以及如何在不同时间范围内从它们计算分位数,同时还可以动态地聚合某些维度。
在本节中,我们将学习如何使用包含时间戳的指标。
prometheus生态系统中的组件经常暴露时间戳。例如,这可能是批处理作业最后一次成功完成,上次成功重新加载配置文件或引导计算机的时间。按照惯例,时间表示为自1970年1月1日UTC以来的Unix时间戳(以秒为单位)。
例如,演示服务公开模拟批处理作业成功的最后一次:
demo_batch_last_success_timestamp_seconds{job="demo"}
此批处理作业被模拟为每分钟运行一次,但在所有尝试的25%中失败。在失败的情况下,demo_batch_last_success_timestamp_seconds
度量标准保持其最后一个值,直到另一个成功运行发生。
如果您绘制原始时间戳图,它看起来会像这样:
如您所见,原始时间戳值本身通常不是很有用。相反,您经常想知道时间戳值的年龄。常见的模式是从当前时间中减去度量中的时间戳,如time()
函数所提供:
time() - demo_batch_last_success_timestamp_seconds{job="demo"}
这将产生自上次成功运行批处理作业以来的秒数:
如果您想将此年龄从秒转换为小时,则可以将结果除以3600
:
(time() - demo_batch_last_success_timestamp_seconds{job="demo"}) / 3600
像这样的表达式对于绘图和警报都很有用。当像上面那样可视化时间戳年龄时,您会收到一个锯齿图,线性增加的行和定期重置到0
批处理作业成功完成时。如果锯齿形尖峰变得太大,则表示批量作业在很长时间内未完成。您还可以通过向>
表达式添加阈值过滤器并对生成的时间序列发出警报来提醒您(尽管我们不会介绍本教程中的警报规则)。
要简单地列出最后1.5分钟内批处理作业尚未完成的实例,可以运行以下查询:
time() - demo_batch_last_success_timestamp_seconds{job="demo"} > 1.5 * 60
您现在知道如何将原始时间戳指标转换为相对年龄,这对图形和警报都很有帮助。
在此步骤中,您将学习如何对查询输出进行排序或仅选择一组系列的最大值或最小值。
在表格控制台视图中,按输出系列的值对输出系列进行排序通常很有用。您可以使用sort()
(升序排序)和sort_desc()
(降序排序)函数来实现此目的。例如,要显示按其值排序的每个路径请求率,从最高到最低,您可以查询:
sort_desc(sum by(path) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))
排序后的输出如下所示:
或者你可能根本没有兴趣展示所有系列,但只有K最大或最小的系列。为此,prometheus提供topk()
和bottomk()
功能。它们各自取一个K值(要选择多少个系列)和一个任意表达式,它返回一组应该过滤的时间序列。例如,要仅显示每个路径和方法的前三个请求率,您可以查询:
topk(3, sum by(path, method) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))
而排序是仅在有用控制台视图,topk()
和bottomk()
也可以在曲线图是有用的。请注意,输出不会显示在整个图形时间范围内平均的顶部或底部K系列 - 相反,输出将重新计算图表中每个分辨率步骤的K顶部或底部输出系列。因此,您的顶部或底部K系列实际上可以在图表的范围内变化,并且您的图表可能总共显示超过K系列。
我们现在学会了如何排序或仅选择K最大或最小的系列。
在这一步中,我们将学习如何随着时间的推移检查实例的刮擦健康状况。
为了使该部分更有趣,让我们终止你的三个后台演示服务实例中的第一个(监听端口8080):
pkill -f -- -listen-address=:8080
每当prometheus擦伤的目标,它会存储与度量名称合成样品up
与job
和instance
刮下实例的标签。如果刮擦成功,则将样本的值设置为1
。如果刮擦失败则设置为0
。因此,我们可以轻松查询当前“向上”或“向下”的实例:
up{job="demo"}
现在应该将一个实例显示为down:
要仅显示向下的实例,您可以过滤值0
:
up{job="demo"} == 0
您现在应该只看到您终止的实例:
或者,要获取关闭实例的总数:
count by(job) (up{job="demo"} == 0)
这将显示1
:
这些类型的查询对于基本的刮擦健康警报很有用。
注意:如果没有关闭实例,则此查询将返回空结果,而不是计数为0
的单个输出系列。这是因为count()
聚合运算符需要一组维度时间序列作为其输入,并且可以根据by
或without
子句对输出序列进行分组。任何输出组只能基于现有的输入系列 - 如果根本没有输入系列,则不会产生输出。
您现在知道如何查询实例健康状况了。
在本教程中,我们构建了如何在Ubuntu 14.04第1部分上查询Prometheus的进度,并介绍了更高级的查询技术和模式。我们学习了如何根据系列的值过滤系列,从直方图计算分位数,处理基于时间戳的指标等。
虽然这些教程无法涵盖所有可能的查询用例,但我们希望在使用Prometheus构建实际查询,仪表板和警报时,示例查询对您有用。
想要了解更多关于查询Prometheus的相关教程,请前往腾讯云+社区学习更多知识。
参考文献:《How To Query Prometheus on Ubuntu 14.04 Part 2》
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。