Prometheus数据类型和查询语法

 2018年4月2日 15:09   Nick王   运维  自动化    0 评论   489 浏览 

Prometheus数据类型和查询语法

数据模型

官方链接: https://prometheus.io/docs/concepts/data_model/

Prometheus本质上会将所有的数据存储为时序数据。

Metric名称和labels

每个时序数据都是由metric名称和一组key-value对(也可以称为是labels)的集合来唯一标识的。

关于metric名称通常是根据器特征来命名的,比如http_requests_total表示接收的HTTP请求的总数。是由ASCII字符和数字以及下划线和冒号。必须匹配[a-zA-Z_:][a-zA-Z0-9_:]*该正则表达式

标签数据可以增加Prometheus数据的维度:对于具有相同的metric名称,但是不同标签组合,那么就能标识一个特定维度的metric。查询语法允许基于这些维度进行过滤和聚合。改变任何标签的值,包含增加和删除,都会创建一个新的时序数据。

标签名称可以包含ASCII字母,数字和下划线。必须符合正则表达式[a-zA-Z_][a-zA-Z0-9_]*__开头的标签名称供内部使用。

标签的值可能包含任何Unicode字符。

样本

每个时序数据样本包含一个浮点数和一个毫秒级精度的时间戳

完整格式

给定一个metric名称和一组标签,这通常都是时序数据的做法:

<metric name>{<label name>=<label value>, ...}

Metric类型

官方链接: https://prometheus.io/docs/concepts/metric_types/

Prometheus的Client Library提供了四种metric类型,分别是:CounterGaugeHistogramSummary当访问Exporter/metrics API地址时我们可以看到类似下面的数据:

# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 10
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.10"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 1.254648e+06

这些数据类型只是Prometheus Client定义的不同的数据类型。Prometheus Server并不会使用这些数据类型。/metrics中所有的数据类型都会无差别的存储到时序数据库中。这些数据类型只是用于表示这些数据适用于哪些场景。

Counter计数器

关于counter是一个累计的度量,它表示一个只会递增的一个单一数值。一个计数器通常被用于统计服务请求次数(比如API访问总次数), 完成的任务数, 发生的错误数等。

这个值会永远随着时间的推移而增加。所以往往我们都统计他的增长率。

Gauge测量值

关于gauge是一个单一的数值,可以大也可以小,可以表示一个当前的瞬时数值。比如当前内存使用,当前温度值,当前正在运行的goroutines,当前系统的负载。

Histogram柱状图

关于histogram对观察结果(通常是请求持续时间或者响应大小)进行采样,并在可配置的桶中对其进行统计。它还提供所有观察值的总和。

在一次数据采样过程中,柱状图会提供以下数据(这些数据以<basename>开头):

  • 观察桶累计计数器,命名为<basename>_bucket={le="<upper inclusive bound>"}

  • 观察值的总和,命名为<basename>_sum

  • 已经观察到的事件数量,命名为<basename>_count,等同于<basename>_bucket{le="+Inf"}

可以使用histogram_quantile()函数,从histogram或者是histogram聚合,来计算百分比数目。比如我们想知道90%的http请求低于某个延迟数,可以使用histogram_quantile(0.9, histogram)

histogram的数据中会有三种metric,分别是<basename>_bucket<basename>_sum<basename>_count

关于histogram用于统计一些数据分布的情况,用于计算在一定范围内的分布情况。

Summary概要图

类似histogramsummary观察样本值(使用场景类似:请求持续时间和响应大小)。它也提供观察的总计数和所有观察值的总和。

在一次数据采样过程中,Summary会提供以下数据(这些数据以<basename>开头)

  • 观察时间的φ-quantiles (0 ≤ φ ≤ 1), 显示为[basename]{quantile="[φ]"}

  • [basename]_sum, 是指所有观察值的总和

  • [basename]_count, 是指已观察到的事件计数值

主要用于表示一段时间内数据采样结果,(通常是请求持续时间或响应大小),它直接存储了quantile数据,而不是根据统计区间计算出来的。

Histogram vs Summary

  • 都包含 <basename>_sum<basename>_count

  • Histogram 需要通过 <basename>_bucket 计算 quantile, 而 Summary 直接存储了 quantile 的值。


基础

官方链接: https://prometheus.io/docs/prometheus/latest/querying/basics/

Prometheus提供了一种表达式语法,利用这种功能可以实时的对时间序列进行选择和汇总。表达式的结果可以以图形的方式显示,也可以使用HTTP API获取。

在Prometheus的表达式语法中,一个表达式或者子表达式评估结果可以是下面四种类型中的一种:

  • 瞬间向量:一组时间序列(time series),这些时间序列包含一个单独的sample(样本数据),共享相同的时间戳。比如

  • 范围向量:一组时间序列(time series),这些时间序列包含一段时间范围内的数据点。比如

  • 纯量:一个简单的浮点数字值

  • 字符串

瞬间向量选择器

简单来说,只提供一个metric名称,就是一个瞬间向量。这会产生包含该metric名称的所有的时序数据,这就是瞬间向量

下面的例子,会包含所有的metric名称为http_requests_total的时序数据:

http_requests_total

其结果如下:

http_requests_total{code="200",group="node",handler="prometheus",instance="localhost:9090",job="prometheus",method="get",service="prometheus"}  1217
http_requests_total{code="200",group="node",handler="query",instance="localhost:9090",job="prometheus",method="get",service="prometheus"}   39
http_requests_total{code="200",group="node",handler="query_range",instance="localhost:9090",job="prometheus",method="get",service="prometheus"} 15

可以在{}中添加一组标签来进一步过滤这些时序数据。

比如下面这样:

http_requests_total{job="prometheus",handler="query"}

其结果如下:

http_requests_total{code="200",group="node",handler="query",instance="localhost:9090",job="prometheus",method="get",service="prometheus"}   40

{}中可以使用下面几种形式的匹配:

  • =: 选择与提供的字符串完全相同的标签

  • !=: 选择不等于提供的字符串的标签

  • =~: 选择与提供的字符串(或子字符串)正则表达式匹配的标签

  • !~: 选择与提供的字符串(或子字符串)正则表达式不匹配的标签

比如可以这样:

http_requests_total{handler=~"query|query_range"}

向量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配器。

{job=~".*"} # Bad!
{job=~".+"}              # Good!
{job=~".*",method="get"} # Good!

标签选择器可以通过使用内部的标签__name__来实现匹配metric name

比如http_requests_total等于{__name__="http_requests_total"}

范围向量选择器

范围向量选择器跟瞬间向量选择器一样,只不过瞬间向量选择器返回的是当前瞬间的时序数据样本。而范围向量选择器要在向量选择器的末尾通过[]提供一个持续时间范围

持续时间必须指定为一个数字,紧跟着的是一个单位:

  • s: 秒

  • m: 分钟

  • h: 小时

  • d: 天

  • w: 周

  • y: 年

比如可以这样:

http_requests_total{handler=~"query|query_range"}[5m]

偏移修改器

关于offset修改器,允许在查询中修改当前瞬间或者范围向量的时间偏移。

下面这个例子,表示查询5分钟前的瞬间向量时序数据:

http_requests_total offset 5m

特别注意: offset关键字永远要跟随向量选择器,比如下面这样:

sum(http_requests_total{method="GET"} offset 5m) // GOOD.

如果这么写就是无效的:

sum(http_requests_total{method="GET"}) offset 5m // INVALID.

如果使用范围向量选择器,那么写法是一样的:

rate(http_requests_total[5m] offset 1w)

操作符

官方链接: https://prometheus.io/docs/prometheus/latest/querying/operators/

Prometheus支持很多的二元和聚合操作符。

算术二元运算符

Prometheus存在以下的二元算数运算符:

  • +

  • -

  • *

  • /

  • %

  • ^

二元算数运算符可以应用在 纯量/纯量, 向量/纯量, 向量/向量之间。

纯量/纯量之间

AA

向量/纯量:

AA

运算符会应用于向量中的每个数据样本。并且结果中的metric name被丢弃了。

向量/向量

运算符会应用在左侧的向量数据和与其对应的右侧的向量数据。结果会丢弃metric name。如果左侧有三条数据,右侧有四条数据,那么右侧会丢弃一条。

AA

比较二元运算符

Prometheus中存在一下的比较二元运算符:

  • ==

  • !=

  • >

  • <

  • >=

  • <=

二元比较运算符可以应用在 纯量/纯量, 向量/纯量, 向量/向量之间。默认用于过滤。

提供修饰符bool: 返回0(false)和1(true)

AA


AA

向量/纯量: 不提供修饰符的时候,结果为false的会被丢弃, 只保留结果为true的时序数据; 提供修饰符之后, 结果都会变成0和1

AA


AA

逻辑/集合二元运算符

这些逻辑二元运算符仅仅应用于瞬间向量之间:

  • and

  • or

  • unless

一对一向量匹配

多对一和一对多向量匹配

聚合操作符

Prometheus 支持一些内建的聚合运算符,这些运算符可以用于汇总单个的即时向量的元素, 生成一个由被聚合的值组成的新向量。

  • sum

  • min

  • max

  • avg

  • stddev: 标准偏差

  • stdvar: 标准方差

  • count

  • count_values: 按元素的值分组,分别计算具有相同的值的元素的数量

  • bottomk: 最小的K个元素

  • topk: 最大的K个元素

  • quantile: 计算 0-1 之间的百分比数量的样本的最大值

这些操作符可以被用于聚合所有的标签维度,或者通过包含without或者by关键字保留不同的维度。

标准语法:

<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
  • <aggr-op>: 聚合操作

  • parameter: 只有部分运算符用到(count_values, quantile, topk  bottomk)

  • <vector expression>: 向量表达式

  • without: 列出的标签,会从结果向量中去除

  • by: 列出的标签, 会保留在结果向量中,其余都去除

如果http_requests_total时序数据有application, instancegroup标签,我们想要看到每个applicationgroup的所有instance的HTTP请求总和,可以这样:

sum(http_requests_total) without (instance)

这等同于

sum(http_requests_total) by (application, group)

如果我们只对所有的HTTP请求总和感兴趣可以这样做:

sum(http_requests_total)

统计每个版本运行的二进制的数量:

count_values("version", build_version)

TOP5:

topk(5, http_requests_total)

函数

官方文档: https://prometheus.io/docs/prometheus/latest/querying/functions/

函数说明示例
abs()返回向量中所有样本值的绝对值
absent()

ceil()返回向量中所有样本值的向上取整数
floor()返回向量中所有样本值的向下取整数
round()返回向量中所有样本值的最接近的整数
exp()计算指数值
ln()

log2()

log10()

sqrt()求平方根
scalar()给定一个向量,转换为纯量scalar(http_requests_total{handler="query",code="200"})
vector()将纯量参数作为无标签的向量返回vector(100)
sort()对向量按元素的值进行升序排序
sort_desc()对向量按元素的值进行降序排序
day_of_month()

day_of_week()

days_in_month()

time()返回一个UTC时间戳, 是表达式评估当时的时间戳time()
timestamp()返回数据样本的时间戳timestamp(http_requests_total)
histogram_quantile()bucket类型的向量中计算φ (0 ≤ φ ≤ 1)百分比的样本的最大值.所谓bucket类型就是labels中必须要有le这个label来表示不同bucket区间 的样本数量.
clamp_max()即时向量中的每个元素的值,不让它们的最大值超越指定的最大值.
clamp_min()即时向量中的每个元素的值,不让它们的最小值超越指定的最小值.
label_join()

label_replace()

changes()参数是一个范围向量, 他返回一个即时向量labels不变,值是 元素的值发生变化的次数
idelta()参数是一个范围向量, 返回一个即时向量它计算最新的2个样本值之间的差别.这个函数一般只用在 gauge 类型的时序上
delta()数是一个范围向量,返回一个即时向量它计算每个时序数据中的第一个值和最后一个值的差别,这个函数一般只用在 gauge类型的时序数据上
deriv()参数是一个范围向量,返回一个即时向量.它计算每个时序数据的每秒的导数(derivative),它使用简单的线性回归计算这个导数
holt_winters()一种算法模型, 用于时间序列挖掘, 接收三个参数
increase()参数是一个范围向量.它计算指定范围内的增长值increase(http_requests_total[20m])
irate()参数是一个范围向量.它计算每秒的平均增长值, 它基于的是最新的2个数据点,而不是第一个和最后一个值.irate(http_requests_total[20m])
rate()参数是一个范围向量.它计算每秒的平均增长值rate(http_requests_total[20m])
predict_linear()根据线性分布预测n秒后的值,基于给定的范围向量.predict_linear(http_requests_total[20m], 5)
resets()

<aggregation>_over_time()
avg_over_time(range-vector), sum_over_time(range-vector), count_over_time(range-vector)
hour()返回给定时间的小时,UTC时间, 默认是当前时间
minute()返回给定时间的分钟,UTC时间, 默认是当前时间
month()返回给定时间的月份,UTC时间, 默认是当前时间
year()返回给定时间的年份,UTC时间, 默认是当前时间year()

案例

官方文档: https://prometheus.io/docs/prometheus/latest/querying/examples/

指定metric名称,返回所有的时序数据

http_requests_total

指定metric名称和label,返回所有的时序数据

http_requests_total{job="apiserver", handler="/api/comments"}

指定metric名称和label,并指定时间范围, 返回范围向量时序数据

http_requests_total{job="apiserver", handler="/api/comments"}[5m]

指定metric名称,使用正则匹配label

http_requests_total{job=~".*server"}

获取所有的HTTP状态码,除了4xx的一部分

http_requests_total{status!~"4.."}

返回5分钟之内,每秒的增长速率

rate(http_requests_total[5m])

根据job统计所有的增长速率

sum(rate(http_requests_total[5m])) by (job)

如果我们有相同维度标签的两个不同的metric,我们可以使用二元算数运算符。下面是计算每个实例的未使用的内存

(instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024

相同的表达式,但是通过应用来进行统计:

sum(
  instance_memory_limit_bytes - instance_memory_usage_bytes
) by (app, proc) / 1024 / 1024

假如有下面的样本数据:

instance_cpu_time_ns{app="lion", proc="web", rev="34d0f99", env="prod", job="cluster-manager"}
instance_cpu_time_ns{app="elephant", proc="worker", rev="34d0f99", env="prod", job="cluster-manager"}
instance_cpu_time_ns{app="turtle", proc="api", rev="4d3a513", env="prod", job="cluster-manager"}
instance_cpu_time_ns{app="fox", proc="widget", rev="4d3a513", env="prod", job="cluster-manager"}
...

根据应用和产品分组的前3名的CPU使用

topk(3, sum(rate(instance_cpu_time_ns[5m])) by (app, proc))

统计实例数量:

count(instance_cpu_time_ns) by (app)

HTTP API

官方链接: https://prometheus.io/docs/prometheus/latest/querying/api/

Prometheus的HTTP API都位于 /api/v1下。API响应都是JSON格式的。

返回的JSON格式:

{
  "status": "success" | "error",
  "data": <data>,

  // Only set if status is "error". The data field may still hold
  // additional data.
  "errorType": "<string>",
  "error": "<string>"
}


AA


如无特殊说明,文章均为本站原创,转载请注明出处