基本用法
过滤器
我们用 MetricsQL 获取指标foo_bar
的数据。只需在查询中写入指标名称,就能轻松完成:
foo_bar
一个简单的指标名称会得到拥有不同 Label Set 的多个 Timeseries 返回响应值。比如:
requests_total{path="/", code="200"}
requests_total{path="/", code="403"}
要选择具有特定 Label 的 Timeseries,需要在花括号{}
中指定匹配 Label 的过滤器:
requests_total{code="200"}
上面的查询语句返回所有名字是requests_total
并且 Label 带有code="200"
的所有Timeseries
。我们用=
运算符来匹配 Label 值。对于反匹配使用!=
运算符。过滤器也通过=~
实现正则匹配,用!~
实现正则反匹配。
requests_total{code=~"2.*"}
过滤器也可以被组合使用:
requests_total{code=~"200", path="/home"}
上面的查询返回所有名字是request_total
,同时带有code="200"
和path="/home"
Label 的所有 Timeseries。
使用名字过滤
有时我们可能需要同时返回多个监控指标。就如同数据模型中提到的,Metric 名称本质上也是一个普通的 Label 的值,其 Label 名是__name__
。所以可以通过对 Metric 名使用正则的方式,来过滤出多个指标的数据:
{__name__=~"requests_(error|success)_total"}
上面的查询语句会返回 2 个 Metric 的 Timeseries:requests_error_total
和requests_success_total
.
利用 or 使用多个过滤器
MetricsQL 支持查询至少满足多个过滤器中的一个方式来获取 Timeseries。这些过滤器必须在花括号内使用or
分割。 比如,下面的查询代表查询 Label 满足{job="app1",env="prod"}
或{job="app2",env="dev"}
的 Timeseries:
{job="app1",env="prod" or job="app2",env="dev"}
过滤器的个数是没有限制的。这个功能可以对查询到的 series 直接运用 rollup 函数(比如 rate),这样就不需要使用子查询了:
rate({job="app1",env="prod" or job="app2",env="dev"}[5m])
如果你需要对同一 Label 使用多个过滤器来查询 Timeseries,从性能角度来看,最好使用正则表达式{label=~"value1|...|valueN"}
而不是使用{label="value1" or ... or label="valueN"}
。
算数运算
MetricsQL 支持所有基本的算数运算:
- 加法 -
+
- 减法 -
-
- 乘法 -
*
- 除法 -
/
- 取模 -
%
- 指数 -
^
我们可以在多个指标之间进行各种计算。比如,下面的查询语句就是计算错误请求率:
(requests_error_total / (requests_error_total + requests_success_total)) * 100
合并多个 Timeseries
要使用算术运算合并多个 Timeseries ,我们需要了解匹配规则。否则,查询会出错或给出错误的结果。匹配规则的逻辑很简单:
- MetricsQL引擎在不影响 Label 的情况下,从算术操作左右两侧的所有 Timeseries 中去除指标名称。
- 对于左侧的每个 Timeseries,MetricsQL 引擎会在右侧搜索具有相同 Label Set 的 Timeseries,对每个数据点执行运算操作,并返回具有相同 Label Set 的结果时间序列。如果没有匹配项,则结果时间序列将从结果中删除。
- 匹配规则可以通过
ignore
、on
、group_left
和group_right
运算符进行扩展。详细信息请参阅这些文档。
比较运算
MetricsQL 支持下面这些比较运算符:
- 等于 -
==
- 不等于 -
!=
- 大于 -
>
- 大于等于 -
>=
- 小于 -
<
- 小于等于 -
<=
这些运算符可以像算术运算符一样应用于任意的 MetricsQL 表达式。比较运算的结果是只包含 value 匹配成功的的 Timeseries。例如,下面的查询将仅返回内存使用超过100MB
的进程列表。
process_resident_memory_bytes > 100*1024*1024
聚合与分组函数
MetricsQL 支持对 Timeseries 进行分组聚合。Timeseries 使用指定的一组 Label 进行分组,然后使用指定的聚合函数对每组 Timeseries 的 value 做聚合计算。 比如,下面的查询返回每个 job 的 内存使用率总和:
sum(process_resident_memory_bytes) by (job)
更多参见 MetricsQL 的聚合函数文档。
计算速率
对于 Counter 类型指标使用最广泛的的一个函数是 rate。
它对每一个 Timeseries 独立计算每秒的平均增长率。比如,下面的查询返回的是每一个 node_exporter 实例监控到的每秒平均入流量, node_network_receive_bytes_total
指标是node_exporter
暴露的一个指标。
rate(node_network_receive_bytes_total)
默认情况下,无论是 Instant Query 还是 Range Query,VictoriaMetrics 都使用step
参数指定的作用范围,对作用范围内的样本执行rate
计算。rate
需要计算的时间间隔可以在一个中括号中指定。比如:
rate(node_network_receive_bytes_total[5m])
在这个例子中,VictoriaMetrics 使用指定的回溯窗口5m
(5分钟)。来计算平均每秒增长。通常情况下回溯窗口越大,曲线图形就约平滑。
rate
会保留 timeseries 中除了 Metric 名称之外的所有 Label。如果你想要保留 Metric 名称,就需要在rate(...)
后面使用 keep_metric_names 修改器。比如,下面的语句就是在计算rate()
后保留 Metric 名称:
rate(node_network_receive_bytes_total) keep_metric_names
rate()
能且只能用于 Counter 类指标。对 Gauge 类型指标应用rate
是没意义的。
keep_metric_names
默认情况下,Metric 名称会在应用函数或算数运算后被丢弃,因为它们已经失去了gg原始指标的含义。当函数作用于多个名称不同的时间序列时,可能会导致duplicate time series
错误。这个错误可以使用keep_metric_names
修改器来解决。
例如:
rate({__name__=~"foo|bar"}) keep_metric_names
会在查询结算结果中保留foo
和bar
这 2 个 Metric 名称。({__name__=~"foo|bar"} / 10) keep_metric_names
会在查询结算结果中保留foo
和bar
这 2 个 Metric 名称。