跳转至

DQL 函数参考


DQL 提供了丰富的函数用于数据聚合、转换和匹配。本文档详细介绍每个函数的语义、参数和使用方法。

聚合函数

聚合函数用于将多行数据聚合为单个值,通常与时间窗口(time-expr)和分组(BY 子句)一起使用。

基础聚合

sum

计算字段值的总和。

语法:

sum(field)

参数:

  • field: 数值字段

示例:

// 计算总请求数
M::http_requests:(sum(request_count)) [1h]

// 按服务分组计算总请求数
M::http_requests:(sum(request_count)) [1h] BY service

avg

计算字段值的平均值。

语法:

avg(field)

参数:

  • field: 数值字段

示例:

// 计算平均响应时间
M::response_time:(avg(duration)) [1h] BY endpoint

// 计算平均 CPU 使用率
M::cpu:(avg(usage)) [1h] BY host

count

计算数据行数。

语法:

count(field)
count(*)

参数:

  • field: 任意字段,计算非空值的数量
  • *: 计算所有行数

示例:

// 计算日志条数
L::nginx:(count(*)) [1h]

// 计算有响应时间的请求数
M::response_time:(count(duration)) [1h] BY service

min / max

计算字段的最小值或最大值。

语法:

min(field)
max(field)

参数:

  • field: 数值字段

示例:

// 找出最大响应时间
M::response_time:(max(duration)) [1h] BY endpoint

// 找出 CPU 使用率的范围
M::cpu:(min(usage), max(usage)) [1h] BY host

first / last

获取第一个或最后一个值(按时间顺序)。

语法:

first(field)
last(field)
last_row(field)

参数:

  • field: 任意字段

说明:

  • first: 返回时间最早的值
  • last: 返回时间最晚的值,如果字段是数组类型会展开
  • last_row: 返回时间最晚的值,数组类型不展开

示例:

// 获取最新的状态值
M::system:(last(status)) [1h] BY host

// 获取初始值和最终值
M::counter:(first(value), last(value)) [1h] BY metric

any

返回任意一个非空值。适用于获取样本数据或不需要特定聚合顺序的场景。

语法:

any(field)

参数:

  • field: 任意字段

示例:

// 获取任意一个消息样本
L::logs:(any(message)) [1h] BY service

// 获取任意一个错误堆栈
L::error_logs:(any(stack_trace)) [1h] BY error_type

spread

计算极差(最大值与最小值的差)。

语法:

spread(field)

参数:

  • field: 数值字段

示例:

// 计算响应时间的波动范围
M::response_time:(spread(duration)) [1h] BY endpoint

stddev

计算标准差。

语法:

stddev(field)

参数:

  • field: 数值字段

示例:

// 计算响应时间的标准差
M::response_time:(stddev(duration)) [1h] BY endpoint

mode

计算众数(出现次数最多的值)。

语法:

mode(field)

参数:

  • field: 任意字段

示例:

// 找出最常见的响应状态码
M::http:(mode(status)) [1h] BY endpoint

count_series

计算时间序列(分组)的数量。返回当前查询范围内有多少个独立的时间序列。

语法:

count_series(field)

参数:

  • field: 任意字段(通常使用 * 或任意存在字段)

示例:

// 计算有多少个主机在报告 CPU 指标
M::cpu:(count_series(*)) [1h]

// 计算每个服务有多少个实例
M::http_requests:(count_series(*)) [1h] BY service

统计聚合(估算函数)

以下函数使用概率数据结构进行估算,适用于大数据量的场景,可以在精度和性能之间取得平衡。

count_distinct

计算字段的不同值数量(估算值)。

语法:

count_distinct(field)

参数:

  • field: 任意字段

算法说明:

使用 HyperLogLog 算法进行基数估算:

  • 寄存器数量:2¹⁶ = 65536
  • 使用 LogLog-Beta 估计方法
  • 标准误差:约 0.4%

适用场景:

  • 统计独立用户数(UV)
  • 计算不同 IP 地址数量
  • 分析唯一请求 ID 数量

示例:

// 统计独立用户数
L::access_logs:(count_distinct(user_id)) [1d] BY service

// 统计访问的不同 IP 数量
L::nginx:(count_distinct(client_ip)) [1h] BY endpoint

percentile

计算字段的百分位数(估算值)。

语法:

percentile(field, n)
pXX(field)  // 简写形式

参数:

  • field: 数值字段
  • n: 百分位数,范围 0-100

简写形式:

  • p50(field) 等价于 percentile(field, 50)
  • p95(field) 等价于 percentile(field, 95)
  • p99(field) 等价于 percentile(field, 99)

算法说明:

使用对数线性插值直方图进行估算: - 桶范围:10⁻⁹ 到 10¹⁸,覆盖绝大多数数值场景 - 每个数量级划分为 128 个桶 - 使用对数空间的线性插值提高精度

适用场景:

  • 计算响应时间的 P99、P95
  • 分析性能指标的尾部延迟
  • 评估服务等级协议(SLA)达成情况

示例:

// 计算响应时间的 P99
M::response_time:(percentile(duration, 99)) [1h] BY service

// 使用简写形式
M::response_time:(p99(duration)) [1h] BY service

// 同时计算多个百分位数
M::response_time:(p50(duration), p95(duration), p99(duration)) [1h] BY service

median

计算中位数,等价于 percentile(field, 50)

语法:

median(field)

示例:

// 计算响应时间的中位数
M::response_time:(median(duration)) [1h] BY service

直方图函数

DQL 提供三种直方图相关的函数,适用于不同的数据源和场景:

函数 适用场景 数据源类型 推荐度
histogram_auto 日志、Trace 等明细数据的数值分布统计 明细模型(日志/Trace) ⭐⭐⭐ 推荐
histogram 需要固定桶边界的直方图 明细模型(日志/Trace) ⭐⭐ Deprecated
histogram_quantile 从 Prometheus 直方图指标计算分位数 Prometheus 指标 ⭐⭐⭐ 推荐

histogram_auto(推荐)

自动生成分布直方图,专为日志、Trace 等明细数据的数值分布统计设计。

特点:

  • 无需指定桶边界,自动适应数据分布
  • 使用对数线性插值直方图算法,覆盖 10⁻⁹ 到 10¹⁸ 的数值范围
  • 同时返回分位数统计和桶分布信息

语法:

histogram_auto(field)

参数:

  • field: 数值字段

返回值:

列名 说明
lower_bounds 各桶的下边界数组
upper_bounds 各桶的上边界数组
counts 各桶的计数数组
min 最小值
p50 中位数
p75 75分位数
p90 90分位数
p95 95分位数
p99 99分位数
max 最大值

算法说明:

使用估算直方图(对数线性插值),每个数量级划分为 128 个桶,适合大数据量的分布统计。

适用场景:

  • 分析日志中的响应时间分布
  • 统计 Trace 中的耗时分布
  • 探索性数据分析,无需预设桶边界

示例:

// 分析 Nginx 访问日志的响应时间分布
L::nginx:(histogram_auto(response_time)) [1h]

// 按服务统计请求耗时分布
L::app_logs:(histogram_auto(duration)) [1h] BY service

// 统计 Trace 调用的耗时分布
T::http_client:(histogram_auto(elapsed)) [1h] BY operation

结果示例:

lower_bounds upper_bounds counts min p50 p75 p90 p95 p99 max
[0, 10, 100] [10, 100, 1000] [1000, 500, 100] 0.5 45 120 280 450 850 1200
注意

lower_boundsupper_boundscounts 为数组类型,表示各桶的边界和计数。


histogram(Deprecated)

生成指定桶边界的直方图。此函数 Deprecated,推荐使用 histogram_auto 替代。

说明:

histogram 需要手动指定桶的边界参数,使用起来不够灵活。histogram_auto 可以自动适应数据分布,覆盖更广泛的数值范围,且返回更丰富的统计信息。

语法:

histogram(field, left_bound, right_bound, bucket_size [, threshold])

参数:

  • field: 数值字段
  • left_bound: 左边界
  • right_bound: 右边界
  • bucket_size: 桶大小
  • threshold(可选): 单桶最小计数,低于此值的桶不返回

返回值:

返回两列:bucket_le(桶的右边界)和 count(计数)

示例:

// 生成 0-1000ms 范围内、每 100ms 一个桶的直方图
M::response_time:(histogram(duration, 0, 1000, 100)) [1h]

// 推荐使用 histogram_auto 替代
M::response_time:(histogram_auto(duration)) [1h]

结果示例:

bucket_le count
100 1500
200 2800
300 3500
... ...
1000 5000

histogram_quantile

Prometheus 直方图指标计算分位数。

特点:

  • 专门用于处理 Prometheus 上报的直方图类型指标
  • 依赖 le 标签(或 VictoriaMetrics 的 vmrange 标签)识别 bucket 边界
  • 输入数据应为累积计数(cumulative)

语法:

histogram_quantile(field, q)

参数:

  • field: 直方图计数字段(如 http_request_duration_bucket
  • q: 分位数,范围 0-1(如 0.99 表示 P99)

使用场景对比:

场景 推荐函数 说明
分析日志中的响应时间分布 histogram_auto 日志是明细数据,无预聚合直方图
分析 Prometheus 直方图指标的 P99 histogram_quantile 指标已按 le 标签预聚合
统计 Trace 调用的耗时分布 histogram_auto Trace 是明细数据

le 标签处理机制:

histogram_quantile 依赖 le 标签(less than or equal)来识别直方图 bucket 的边界:

  1. Prometheus 格式(默认):使用 le 标签直接表示 bucket 上边界

    • le 值为数值(如 "0.1", "1", "10")或 "+Inf"(无穷大)
    • 数据应为累积计数(cumulative)
  2. VictoriaMetrics 格式:使用 vmrange 标签表示范围

    • 格式为 "下限...上限"(如 "0.1...0.2"
    • 数据为范围计数(非累积)
    • 函数会自动将范围计数转换为累积计数

计算过程:

  1. le 值排序所有 bucket
  2. 如果是 vmrange 格式,累加计数转换为累积分布
  3. 确保 bucket 计数单调递增(修复可能的异常数据)
  4. 使用线性插值计算目标分位数

与 PromQL 的差异:

特性 DQL PromQL
函数类型 聚合函数 转换函数
输入数据 直接读取带 le 标签的指标 需要配合 sum(rate(...)) by (le)
使用方式 histogram_quantile(field, 0.99) histogram_quantile(0.99, sum(rate(...)) by (le))
数据格式 支持 levmrange 两种标签 仅支持 le 标签
分组方式 通过 DQL 的 BY 子句 通过 by (le) 显式分组

等价示例:

假设有直方图指标 http_request_duration_bucket,包含 le 标签(如 0.1, 0.5, 1, 5, +Inf)和 service 标签。

场景 1:计算 P99 延迟

DQL:

M::http_request_duration:(histogram_quantile(duration_bucket, 0.99)) [1h] BY service

PromQL 等价:

histogram_quantile(0.99, sum(rate(http_request_duration_bucket[1h])) by (le, service))

场景 2:计算各服务的 P95 延迟(多分组)

DQL:

M::http_request_duration:(
    histogram_quantile(duration_bucket, 0.95)
) [1h] BY service, endpoint

PromQL 等价:

histogram_quantile(0.95, sum(rate(http_request_duration_bucket[1h])) by (le, service, endpoint))

场景 3:计算 P50(中位数)和 P99

DQL:

M::http_request_duration:(
    histogram_quantile(duration_bucket, 0.50) as p50,
    histogram_quantile(duration_bucket, 0.99) as p99
) [1h] BY service

PromQL 等价:

label_join(
  histogram_quantile(0.50, sum(rate(http_request_duration_bucket[1h])) by (le, service)), "quantile", "", "0.50"
)
or
label_join(
  histogram_quantile(0.99, sum(rate(http_request_duration_bucket[1h])) by (le, service)), "quantile", "", "0.99"
)

注意

PromQL 需要 label_joinlabel_replace 来区分不同分位数的结果。

注意事项:

  • 输入数据必须包含 levmrange 标签,否则无法计算
  • 如果没有 +Inf bucket,最后一个 bucket 的上边界将作为最大值
  • 计数为 0 或 NaN 的 bucket 会被跳过
  • 当分位数 < 0 时返回 -Inf,> 1 时返回 +Inf

TopN 函数

top

获取前 N 个最大的值。

语法:

top(field, n)

参数:

  • field: 数值字段
  • n: 返回值的数量

示例:

// 获取响应时间最长的 5 个请求
M::response_time:(top(duration, 5)) [1h] BY service

// 获取流量最大的 10 个主机
M::network:(top(bytes, 10)) [1h]

结果示例:

service top(duration, 5)
api 1250
api 1180
api 1050
api 980
api 920
注意

返回多行,每行包含一个 TopN 值。


bottom

获取前 N 个最小的值。

语法:

bottom(field, n)

参数:

  • field: 数值字段
  • n: 返回值的数量

示例:

// 获取响应时间最短的 5 个请求
M::response_time:(bottom(duration, 5)) [1h] BY service

结果示例:

service bottom(duration, 5)
api 12
api 18
api 25
api 32
api 45
注意

返回多行,每行包含一个 BottomN 值。


值收集函数

distinct

返回字段的所有不同值。

语法:

distinct(field)

示例:

// 获取所有不同的状态码
M::http:(distinct(status)) [1h] BY endpoint

结果示例:

endpoint distinct(status)
/api/v1 200
/api/v1 404
/api/v1 500
/health 200
注意

返回多行,每行包含一个不同的值。


distinct_by_collapse

按折叠策略获取字段的不同值,并在去重时保留其他字段的最后一个值。

语法:

distinct_by_collapse(field, [last_field1, last_field2, ...])

参数:

  • field: 去重依据的字段
  • last_fields(可选): 需要保留最后一个值的字段列表

说明:

distinct 不同,distinct_by_collapse 在去重时会保留其他相关字段的信息(取最后一个值),适用于需要保留上下文信息的场景。

示例:

// 获取不同的用户 ID,并保留每个用户最后访问的时间
L::access_logs:(distinct_by_collapse(user_id, [timestamp])) [1h]

// 获取不同的主机,并保留最后的状态和消息
O::HOST:(distinct_by_collapse(host, [status, message])) [1h]

结果示例:

user_id last(timestamp) last(path)
user001 1704067200000 /checkout
user002 1704067100000 /product
user003 1704067000000 /home
注意

返回去重后的主字段值,以及 last_fields 指定的其他字段的最后一个值。


collect

收集所有值(包含重复)。

语法:

collect(field [, limit])

参数:

  • field: 任意字段
  • limit(可选): 最多收集的数量

示例:

// 收集所有响应时间
M::response_time:(collect(duration)) [1h] BY service

// 最多收集 100 个值
M::response_time:(collect(duration, 100)) [1h] BY service

结果示例:

service collect(duration)
api [120, 135, 98, 142, ...]
web [45, 52, 48, 61, ...]
注意

返回数组类型,包含收集到的所有值(可能包含重复值)。


collect_distinct

收集所有不同的值。

语法:

collect_distinct(field [, limit])

参数:

  • field: 任意字段
  • limit(可选): 最多收集的数量

示例:

// 收集所有不同的错误类型
L::error_logs:(collect_distinct(error_type)) [1h] BY service

结果示例:

service collect_distinct(error_type)
api ["timeout", "connection refused", "404"]
web ["200", "301", "404"]
注意

返回数组类型,包含去重后的所有值。


field_values

获取字段的所有值,返回数组类型。

语法:

field_values(field)

示例:

// 获取所有标签值
M::metrics:(field_values(tags)) [1h] BY metric_name

结果示例:

metric_name field_values(tags)
cpu_usage ["host:A", "env:prod", "team:backend"]
memory_used ["host:B", "env:staging", "team:frontend"]
注意

返回数组类型,包含字段的所有值。


筛选聚合

count_filter

统计字段值在指定列表中的数量。

语法:

count_filter(field, [value1, value2, ...])

参数:

  • field: 任意字段
  • values: 值列表

示例:

// 统计特定状态码的请求数
M::http:(count_filter(status, [200, 201, 204])) [1h] BY endpoint

// 统计错误级别日志
L::logs:(count_filter(level, ["error", "critical"])) [1h] BY service

辅助函数

default

为字段设置默认值,当字段为空时返回默认值。

语法:

default(field, default_value)

参数:

  • field: 任意字段
  • default_value: 默认值(可以是数值、字符串、布尔值或 null)

示例:

// 为空值设置默认的响应时间
M::response_time:(default(duration, 0)) [1h] BY service

时间序列函数

时间序列函数用于处理随时间变化的数据,特别是 Counter 类型的指标。

Rollup 函数

Rollup 函数用于在时间窗口中对原始时间序列数据进行预处理,详细说明请参考 本文中的 Rollup 函数

写法说明:

  • Rollup 写在时间子句中,例如 [rate][1h::5m:rate]
  • 写在查询外层(如 rate(DQL))属于外层函数,不是 Rollup。

支持的 Rollup 函数:

函数 说明
rate 计算增长率(每秒)
irate 计算瞬时增长率
increase 计算增长量
deriv 计算导数(变化率)
difference 计算差值
non_negative_derivative 计算非负导数
non_negative_difference 计算非负差值
rate_over_sum 计算每秒平均值
rate_over_count 计算每秒计数
sum 求和
avg 平均值
min 最小值
max 最大值
count 计数
first 第一个值
last 最后一个值
stddev 标准差
mode 众数
spread 极差
any 任意一个值

示例:

// 计算请求 QPS
M::http_requests:(sum(request_count)) [1h::5m:rate] BY service

// 简写形式
M::cpu:(max(usage)) [rate]

增长率计算

rate

计算指标的增长率(每秒)。

语法:

rate(field)

说明:

rate 计算的是 Counter 指标在时间窗口内的平均增长率。对于单调递增的 Counter 类型指标,直接使用原始值进行聚合没有意义,需要先计算增长率。

适用场景:

  • 计算请求 QPS
  • 计算数据写入速率
  • 分析流量增长趋势

示例:

// 计算请求 QPS
M::http_requests:(sum(request_count)) [rate] BY service

// 计算数据写入速率
M::data_ingestion:(sum(bytes)) [rate] BY source

irate

计算指标的瞬时增长率。

语法:

irate(field)

说明:

rate 不同,irate 只使用最后两个数据点计算增长率,反映的是瞬时变化率,更适合用于告警场景。

示例:

// 计算瞬时请求 QPS
M::http_requests:(sum(request_count)) [irate] BY service

increase

计算指标的增长量。

语法:

increase(field)

说明:

increase 返回的是时间窗口内的总增长量,而不是增长率。

示例:

// 计算总请求数增长
M::http_requests:(sum(request_count)) [increase] BY service

rate_over_sum

计算每秒的平均值(sum / 时间窗口秒数)。

语法:

rate_over_sum(field)

说明:

等效于 sum(field) / 时间窗口(秒),用于计算每秒的平均值。常用于 Rollup 阶段将累计值转换为每秒速率。

与 rate 的区别:

  • rate:计算 Counter 的增长率(处理重置)
  • rate_over_sum:简单地将 sum 除以时间窗口秒数

示例:

// 计算每秒平均请求数
M::http_requests:(rate_over_sum(request_count)) [1h] BY service

rate_over_count

计算每秒的计数(count / 时间窗口秒数)。

语法:

rate_over_count(field)

说明:

等效于 count(field) / 时间窗口(秒),用于计算每秒的发生次数。

示例:

// 计算每秒错误日志条数
L::error_logs:(rate_over_count(*)) [1h] BY error_type

差值计算

本节描述的是函数语义。相同函数既可作为 Rollup 使用(如 [rate][increase]),也可写在查询内表达式中(如 rate(field)increase(field));两者执行阶段不同,优先按业务需求选择位置。

rate / deriv

计算变化率(导数)。rate 用于 Counter 类型指标(忽略负值),deriv 用于 Gauge 类型指标(保留负值)。

别名: rate 的别名是 non_negative_derivativederiv 的别名是 derivative(PromQL 风格)。

语法:

// Counter 指标:计算非负变化率(忽略重置导致的负值)
rate(field)

// Gauge 指标:计算完整变化率(包括负值)
deriv(field)

函数选择:

函数 说明 适用场景
rate 只计算非负变化率 Counter 类型指标(单调递增)
deriv 计算完整变化率(包括负值) Gauge 类型指标(可增可减)

示例:

// Counter 指标:计算请求 QPS
M::requests:(rate(count)) [1h::5m] BY service

// Gauge 指标:计算内存使用变化率
M::memory:(deriv(used)) [1h::5m] BY host

increase / difference

计算相邻值的差值。increase 用于 Counter 类型指标(忽略负值),difference 用于 Gauge 类型指标(保留负值)。

说明: increasedifference 是两个独立的函数,行为不同,不是别名关系。

语法:

// Counter 指标:计算非负差值(忽略重置导致的负值)
increase(field)

// Gauge 指标:计算完整差值(包括负值)
difference(field)

函数选择:

函数 说明 适用场景
increase 只计算非负差值 Counter 类型指标(单调递增)
difference 计算完整差值(包括负值) Gauge 类型指标(可增可减)

示例:

// Counter 指标:计算请求增长量
M::requests:(increase(count)) [1h::5m] BY service

// Gauge 指标:计算请求数变化(可能增加或减少)
M::requests:(difference(count)) [1h::5m] BY service

移动计算

moving_average

计算移动平均值。

语法:

moving_average(field, n)

参数:

  • field: 数值字段
  • n: 窗口大小(数据点数量)

示例:

// 计算 5 点移动平均
M::cpu:(moving_average(usage, 5)) [1h::1m] BY host

cumsum

计算累积和。

语法:

cumsum(field)

示例:

// 计算累积请求数
M::requests:(cumsum(count)) [1h::5m] BY service

转换函数

转换函数用于对字段值进行数学运算、类型转换或字符串处理。

数学函数

abs

计算绝对值。

语法:

abs(field)

示例:

// 计算温度偏差的绝对值
M::temperature:(abs(deviation)) [1h] BY sensor

round / ceil / floor

取整函数。

语法:

round(field)  // 四舍五入
ceil(field)   // 向上取整
floor(field)  // 向下取整

示例:

// 响应时间向上取整
M::response_time:(ceil(duration)) [1h]

// 百分比四舍五入
M::cpu:(round(usage)) [1h] BY host

log / log2 / log10

对数函数。

语法:

log(field)    // 自然对数
log2(field)   // 以 2 为底
log10(field)  // 以 10 为底

示例:

// 计算对数变换后的值
M::metrics:(log(value)) [1h] BY metric_name

类型转换

int / uint / float / string / bool

类型转换函数。

语法:

int(field)    // 转为有符号整型
uint(field)   // 转为无符号整型
float(field)  // 转为浮点型
string(field) // 转为字符串
bool(field)   // 转为布尔型

示例:

// 将字符串转为数值
L::logs:(int(response_time)) [1h] BY service

// 将数值转为字符串进行拼接
M::metrics:(string(value)) [1h] BY metric_name

字符串函数

substr

截取子字符串。

语法:

substr(field, start)
substr(field, start, length)

参数:

  • field: 字符串字段
  • start: 起始位置(从 0 开始,支持负数表示从末尾开始)
  • length(可选): 子字符串长度

返回值:

返回截取后的子字符串。

示例:

// 截取消息前 100 个字符
L::logs:(substr(message, 0, 100)) [1h]

// 截取最后 10 个字符
L::logs:(substr(message, -10)) [1h]

结果示例:

message substr(message, 0, 10) substr(message, -5)
"Error: connection timeout" "Error: con" "eout"

regexp_extract

正则表达式提取。

语法:

regexp_extract(field, pattern)
regexp_extract(field, pattern, n)

参数:

  • field: 字符串字段
  • pattern: 正则表达式
  • n(可选): 提取第 n 个捕获组,默认为 0(整个匹配)

返回值:

返回单个字符串,提取第 n 个捕获组的内容。如果没有匹配返回 null。

示例:

// 提取错误码
L::logs:(regexp_extract(message, 'error_code: (\d+)', 1)) [1h] BY service

// 提取 IP 地址
L::nginx:(regexp_extract(message, '(\d+\.\d+\.\d+\.\d+)', 1)) [1h]

结果示例:

service regexp_extract(message, 'error_code: (\d+)', 1)
api "404"
api "500"
web null

regexp_extract_all

提取所有匹配的结果。

语法:

regexp_extract_all(field, pattern)
regexp_extract_all(field, pattern, n)

返回值:

返回字符串数组,包含所有匹配的子串。

示例:

// 提取所有数字
L::logs:(regexp_extract_all(message, '\d+', 0)) [1h]

// 提取所有 IP 地址
L::logs:(regexp_extract_all(message, '\d+\.\d+\.\d+\.\d+', 0)) [1h]

结果示例:

message regexp_extract_all(message, '\d+.\d+.\d+.\d+', 0)
Request from 192.168.1.1 to 10.0.0.1 ["192.168.1.1", "10.0.0.1"]

md5

计算 MD5 哈希值。

语法:

md5(field)

返回值:

返回 32 位十六进制字符串(小写)。

示例:

// 计算消息的 MD5
L::logs:(md5(message)) [1h] BY service

结果示例:

service md5(message)
api 5d41402abc4b2a76b9719d911017c592
web 098f6bcd4621d373cade4e832627b4f6

concat

字符串连接。

语法:

concat(field, ...)

返回值:

返回连接后的单个字符串。

示例:

// 连接多个字段
L::logs:(concat(service, ":", level)) [1h]

// 结果:"api:error"、"web:info" 等

结果示例:

service level concat(service, ":", level)
api error "api:error"
web info "web:info"

set

对数组字段去重并排序。

语法:

set(field)

返回值:

返回去重并排序后的数组。

示例:

// 获取所有不同的标签
M::metrics:(set(tags)) [1h] BY metric_name

// 对 collect 的结果去重
M::http:(set(collect(status))) [1h] BY endpoint

结果示例:

metric_name set(tags)
cpu_usage ["env:prod", "host:A", "team:backend"]
memory_used ["env:staging", "host:B", "team:frontend"]

日志聚类

drain

使用 Drain 算法对日志进行聚类,生成日志模板。

语法:

drain(field, similarity_threshold, max_clusters)

参数:

  • field: 字符串字段(通常是 message)
  • similarity_threshold: 相似度阈值,范围 (0, 1],值越大聚类越严格
  • max_clusters: 最大聚类数量,范围 [1, 10000]

算法说明:

Drain 是一种基于解析树的日志聚类算法,能够自动识别日志中的常量和变量部分,生成日志模板。

适用场景:

  • 日志模式识别
  • 异常日志聚类分析
  • 日志降噪

示例:

// 对日志进行聚类,相似度 0.7,最多 1000 个聚类
L::logs:(drain(message, 0.7, 1000)) [1h] BY service

// 更严格的聚类
L::logs:(drain(message, 0.9, 500)) [1h] BY service

结果示例:

service drain(message, 0.7, 1000)
api "Request from to took
db "Query executed in
注意

返回字符串类型的日志模板,其中 <...> 表示变量部分。


匹配函数

匹配函数用于在 WHERE 子句中进行文本匹配,也可以作为返回布尔值的表达式使用。

子串匹配

match

检查字段是否包含指定子串。

语法:

match(pattern)
match(field, pattern)

参数:

  • pattern: 要匹配的子串
  • field: 字段名(可选,在 WHERE 子句中可省略)

示例:

// 在 WHERE 中使用
L::logs:(message) {match(message, "error")} [1h]

// 简写形式
L::logs:(message) {match("error")} [1h]

// 作为表达式
L::logs:(match(message, "timeout")) [1h] BY match_result

短语匹配

分词短语匹配,支持中英文混合。

语法:

phrase(query)
phrase(field, query)
search(query)
search(field, query)

参数:

  • query: 查询短语
  • field: 字段名(可选)

匹配规则:

  • 中文:按字符分词匹配
  • 英文:按词边界匹配(空格、标点分隔)
  • 大小写不敏感

示例:

// 匹配包含 "connection timeout" 的日志
L::logs:(message) {phrase("connection timeout")} [1h]

// 中文匹配
L::logs:(message) {phrase("连接超时")} [1h]

// 中英文混合
L::logs:(message) {search("error 错误")} [1h]

正则匹配

re / regex / regexp

正则表达式匹配。

语法:

re(pattern)
re(field, pattern)
regex(pattern)
regex(field, pattern)
regexp(pattern)
regexp(field, pattern)

参数:

  • pattern: 正则表达式(支持 PromRegex 语法)
  • field: 字段名(可选)

示例:

// 匹配以 error 开头的日志
L::logs:(message) {re("error.*")} [1h]

// 匹配特定格式的错误码
L::logs:(message) {regexp(message, "ERR-\d{4}")} [1h]

// 在数据源中使用正则
M::re('cpu.*'):(usage) [1h]

通配符匹配

wildcard

通配符模式匹配。

语法:

wildcard(pattern)
wildcard(field, pattern)

参数:

  • pattern: 通配符模式

    • *: 匹配任意多个字符
    • ?: 匹配单个字符
  • field: 字段名(可选)

示例:

// 匹配以 error 开头的消息
L::logs:(message) {wildcard("error*")} [1h]

// 匹配特定格式
L::logs:(message) {wildcard(message, "ERR-????")} [1h]

CIDR 匹配

cidr

IP 地址网段匹配。

语法:

cidr(cidr)
cidr(field, cidr)

参数:

  • cidr: CIDR 表示的网段,如 192.168.1.0/24
  • field: IP 地址字段(可选)

示例:

// 匹配内网 IP
L::nginx:(*) {cidr(client_ip, "10.0.0.0/8")} [1h]

// 匹配特定网段
L::nginx:(*) {cidr(client_ip, "192.168.1.0/24")} [1h]

字段存在检查

exists

检查字段是否存在。

语法:

exists

示例:

// 查找有 error_type 字段的日志
L::logs:(message) {exists(error_type)} [1h]

查询字符串语法

query_string

使用查询字符串语法进行复杂匹配。

语法:

query_string(query)
query_string(field, query)

参数:

  • query: 查询字符串
  • field: 字段名(可选,默认匹配全文)

查询字符串语法:

1. 词项匹配
foo              # 匹配包含 foo 的内容
"foo bar"        # 精确短语匹配,必须连续出现
foo\ bar         # 转义空格,匹配 "foo bar" 这个整体
2. 通配符
foo*             # 匹配以 foo 开头的内容
foo?bar          # ? 匹配单个字符
"foo*bar"        # 引号内的通配符不解析,作为字面量匹配
3. 正则表达式
/foo.*bar/       # 斜线包裹的正则表达式
/joh?n(ath[oa]n)/  # 复杂正则
4. 布尔操作符
foo AND bar      # 逻辑与,两者都必须包含
foo OR bar       # 逻辑或,至少包含一个
NOT foo          # 逻辑非,不包含 foo

# 简写形式
foo && bar       # 等价于 foo AND bar
foo || bar       # 等价于 foo OR bar
!foo             # 等价于 NOT foo
5. 分组
(foo OR bar) AND baz       # 使用括号改变优先级
!(status 429 reading)      # 否定整个表达式
6. 默认操作符

当空格分隔多个词项时,默认使用 OR 连接(可配置为 AND):

foo bar          # 等价于 foo OR bar

示例:

// 简单词项匹配
L::logs:(message) {query_string("error timeout")} [1h]

// 布尔组合
L::logs:(message) {query_string("error AND NOT timeout")} [1h]

// 正则表达式
L::logs:(message) {query_string("/ERR-\d{4}/")} [1h]

// 复杂查询
L::logs:(message) {query_string("(error OR warn) AND service")} [1h]

// 指定字段
L::logs:(*) {query_string(message, "error AND timeout")} [1h]

// 中文查询
L::logs:(message) {query_string("错误 AND 超时")} [1h]

外层函数

使用建议

外层函数是遗留设计。能用 Rollup + 聚合函数(如 [rate][last][increase] 等)解决的场景,优先使用 Rollup 方式。外层函数仅在不适用 Rollup 的场景下使用(如需要对聚合结果进行二次计算)。

外层函数作用于整个 DQL 查询结果之上,用于对查询输出的时间序列数据进行二次计算。外层函数包裹整个 DQL 表达式,而不是写在 Select 子句内部。

查询内函数与外层函数

  • 查询内函数:在 DQL 表达式内部使用,如 sumavgmax
  • 外层函数:包裹整个 DQL 查询结果,对输出的时间序列进行后处理

写法对比:

// Rollup(时间子句):先对每条时间线做增长率,再聚合
M::http_requests:(sum(request_count)) [rate] BY service

// 外层函数:先得到查询结果,再做二次计算
rate(M::http_requests:(sum(request_count)) [1h::1m] BY service)

语法:

outer_function(DQL_expression)

示例:

// 查询内函数:对原始数据求平均
M::cpu:(avg(usage)) [1h::5m] BY host

// 外层函数:对查询结果计算移动平均
moving_average(M::cpu:(avg(usage)) [1h::5m] BY host, 5)

累积计算

cumsum

计算累积和,对时间序列的每个点计算前面所有点的累加值。

语法:

cumsum(DQL_expression)

示例:

// 计算累积请求数
cumsum(M::requests:(sum(count)) [1h::5m] BY service)

差值与导数

推荐使用

这些函数优先作为 Rollup 函数使用(如 [rate][deriv]),外层函数形式仅用于对聚合结果进行二次计算。

以下函数可作为外层函数使用:

函数 说明
derivative(DQL) 计算导数(变化率)
difference(DQL) 计算与前一个值的差
non_negative_derivative(DQL) 计算非负导数
non_negative_difference(DQL) 计算非负差值
rate(DQL) 计算增长率(每秒)
irate(DQL) 计算瞬时增长率

示例:

// 外层函数:对查询结果计算导数
derivative(M::cpu:(avg(usage)) [1h::5m] BY host)

// 推荐:使用 Rollup 方式
M::cpu:(deriv(usage)) [1h::5m:last] BY host

移动计算

moving_average

对查询结果计算移动平均。

推荐使用

优先使用 Rollup 方式 moving_average(field, n),外层函数形式仅用于对聚合结果进行二次平滑。

语法:

moving_average(DQL_expression, n)

参数:

  • DQL_expression: DQL 查询表达式
  • n: 窗口大小(数据点数量)

示例:

// 外层函数:对查询结果计算移动平均
moving_average(M::cpu:(avg(usage)) [1h::1m] BY host, 5)

// 推荐:使用 Rollup 方式
M::cpu:(moving_average(usage, 5)) [1h::1m] BY host

TopN

top / bottom

推荐使用

优先使用 Rollup 方式 top(field, n)bottom(field, n),外层函数形式仅用于对聚合结果进行二次筛选。

对查询结果获取 TopN 或 BottomN。

语法:

top(DQL_expression, n)
bottom(DQL_expression, n)

示例:

// 外层函数:对查询结果获取 TopN
top(M::response_time:(max(duration)) [1h::5m] BY service, 5)

// 推荐:使用 Rollup 方式
M::response_time:(top(duration, 5)) [1h::5m] BY service

空值填充

fill

对查询结果中的空值进行填充。

详细说明请参考 fill 函数

示例:

// 用 0 填充空值
fill(M::cpu:(avg(usage)) [1h::5m] BY host, 0)

// 线性插值填充
fill(M::cpu:(avg(usage)) [1h::5m] BY host, LINEAR)

其他外层函数

以下函数同样可作为外层函数使用:

函数 说明
abs(DQL) 取绝对值
round(DQL) 四舍五入
ceil(DQL) 向上取整
floor(DQL) 向下取整
log(DQL) / log2(DQL) / log10(DQL) 对数变换
set(DQL) 去重并排序
concat(DQL, ...) 字符串连接

组合使用

外层函数可以组合使用:

// 计算移动平均后四舍五入
round(moving_average(M::cpu:(avg(usage)) [1h::1m] BY host, 5))

// 计算增长率的移动平均
moving_average(rate(M::requests:(sum(count)) [1h::5m] BY service), 3)

eval 表达式计算

eval 是一个特殊的函数,允许在查询外部进行表达式计算,可以引用多个子查询的结果进行组合运算。

语法

eval(expression, name1=query1, name2=query2, ..., alias="result_name")

参数:

  • expression: 数学表达式,使用 name.field 引用子查询结果
  • name=query: 命名的子查询
  • alias: 结果别名(可选)

工作原理

  1. 执行所有命名的子查询
  2. 按时间对齐各个子查询的结果
  3. 对每个时间点计算表达式
  4. 返回计算结果

适用场景

  • 计算多个指标的比率(如错误率、利用率)
  • 对比不同时间段的指标
  • 组合多个数据源的计算结果

示例

计算错误率

// 计算错误率 = 错误数 / 总请求数 * 100
eval(a / b * 100,
     a=M::http:(sum(error_count)) [1h] BY service,
     b=M::http:(sum(request_count)) [1h] BY service,
     alias="error_rate")

计算 CPU 使用率

// 使用率 = used / total * 100
eval(used / total * 100,
     used=M::memory:(sum(used_bytes)) [1h] BY host,
     total=M::memory:(sum(total_bytes)) [1h] BY host,
     alias="memory_usage_percent")

计算同比增长

// 计算本周与上周的对比
eval(this_week / last_week - 1,
     this_week=M::sales:(sum(amount)) [7d],
     last_week=M::sales:(sum(amount)) [7d offset 7d],
     alias="week_over_week_growth")

引用子查询的字段

// 引用子查询的特定字段
eval(a.usage / b.total * 100,
     a=M::cpu:(avg(usage)) [1h] BY host,
     b=M::cpu:(avg(total)) [1h] BY host,
     alias="cpu_percent")

注意事项

  • 所有子查询的时间窗口必须兼容
  • 子查询的分组维度应当一致
  • 表达式中引用的字段名使用 name.field 格式
  • 如果只有一个子查询,可以直接使用字段名

其他函数

fill

为查询结果中的空值填充指定值。

推荐使用

fill 建议作为外层函数使用,作用于整个查询结果之上:

fill(M::cpu:(avg(usage)) [1h::5m] BY host, 0)

虽然在 Select 子句中也支持 fill(avg(usage), 0) 的写法,但 fill 实际是在聚合完成后对结果进行填充,因此外层函数形式更符合其工作机制。

语法(外层函数):

fill(DQL_expression, value)
fill(DQL_expression, LINEAR)
fill(DQL_expression, PREVIOUS)

参数:

  • DQL_expression: DQL 查询表达式
  • value: 填充值,支持多种模式:
  • 具体值:数值、字符串、null
  • LINEAR:线性插值
  • PREVIOUS:填充前一个非空值

示例:

// 推荐:作为外层函数使用
fill(M::cpu:(avg(usage)) [1h::5m] BY host, 0)

// 线性插值填充
fill(M::cpu:(avg(usage)) [1h::5m] BY host, LINEAR)

// 用前一个值填充
fill(M::cpu:(avg(usage)) [1h::5m] BY host, PREVIOUS)

now

返回当前时间戳(毫秒)。

语法:

now()

示例:

// 查询最近更新的数据
O::HOST:(*) {last_update_time > now() - 600000}  // 10 分钟内更新

unwrap

展开聚合结果的包装。

语法:

unwrap(field)

示例:

// 展开聚合后的字段
M::cpu:(unwrap(usage)) [1h] BY host

Show 函数

Show 函数用于查看元数据(如 measurement、tag、field、基数与系列计数),常用于建模排查与查询前探查。

通用语法

show_xxx(arg1=..., arg2=...){ where_conditions } [time_window] LIMIT n OFFSET m
  • wheretime_windowLIMITOFFSET 都是可选项;

  • LIMIT/OFFSET 不能为负数。

M 命名空间内置 Show 函数

函数 参数 返回列 说明
show_measurement 可选 re('pattern') name 列出 measurement
show_tag_key 可选 from=['measurement'] tagKey 列出 tag key
show_field_key 可选 from=['measurement'] fieldKey, fieldType 列出 field key(当前 fieldType 为 float
show_tag_value keyin=['tagKey'](必填),可选 from key, value 列出 tag value
show_measurement_cardinality 无强制参数 count measurement 数量
show_series_cardinality 无强制参数 count series 基数(估算)
show_tag_key_cardinality 无强制参数 count tag key 基数(估算)
show_tag_value_cardinality keyin=['tagKey'](必填) count 指定 tag key 的 value 基数(估算)
show_field_key_cardinality 无强制参数 count field key 基数(估算)
show_series_count_by_field_key from=['measurement'](建议) name, count 按 field key 统计 series 数
show_series_count_by_tag_key from=['measurement'](建议) name, count, value_count 按 tag key 统计 series 数与 value 数
show_series_count_by_tag_value keyin=['tagKey'](必填),from=['measurement'](建议) name, count 按指定 tag key 的 value 统计 series 数

基数(cardinality)相关函数底层使用 HyperLogLog 合并,返回值为估算值。

非 M 命名空间 Show 函数(后缀模式)

对于非 M 命名空间,支持以下后缀模式:

  • show_<namespace>_source
  • show_<namespace>_class
  • show_<namespace>_type
  • show_<namespace>_field
  • show_<namespace>_label

其中 <namespace> 由函数名中间段自动映射得到,例如:

  • show_logging_source -> L
  • show_tracing_field -> T
  • show_object_source -> O

常见示例:

show_logging_source()
show_tracing_field('mysql')
show_logging_field('*')
show_logging_label(name='env')
show_logging_label(names=['env', 'team'])

参数与行为说明

  • from:measurement 列表,支持字符串或字符串数组;
  • keyin:tag key 列表,支持字符串或字符串数组;
  • field:field 列表,支持字符串或字符串数组(用于 metric show 的 field 过滤);
  • 对于 show_*_field

    • 无名参数(如 'mysql')通常作为 source 过滤
    • '*' 等价于不指定 source
    • 命名参数会被转成 where 过滤条件
  • 对于 show_*_label

    • 需要命名参数;names 会被视作 name 的别名处理。

约束与注意事项

  • show_tag_valueshow_tag_value_cardinality 必须提供 keyin
  • show_series_count_by_tag_value 必须提供 keyin
  • show_series_count_by_* 必须提供 from,或在 where 中提供等价的 source 约束(例如 @__source__ 条件);
  • show_<namespace>_sourceshow_<namespace>_classshow_<namespace>_type 当前共享同一条执行路径,返回 source 去重列表;
  • 目前 parser 不支持 show_<namespace>_index 语法(即使执行层存在对应分支);
  • 在 Query API 未提供 show 时间范围时,部分日志 show 查询会回落到最近 30 分钟窗口执行。

返回示例

以下示例仅展示典型列结构与示例行,实际结果会受租户数据、过滤条件、时间范围和 LIMIT/OFFSET 影响。

查询 典型列 示例行(示意)
show_measurement() name cpudiskmemory
show_tag_value(from=['cpu'], keyin=['host']) key, value host, web-01host, web-02
show_series_count_by_tag_key(from=['cpu']) name, count, value_count host, 3200, 120service, 2800, 35
show_tag_value_cardinality(keyin=['host']) count 120
show_logging_field('*') fieldKey, fieldType, fieldIndices service, keyword, ["idx_service"]
show_logging_source() source nginxmysqlredis

函数分类速查表

基础聚合

函数 说明 精确/估算
sum 求和 精确
avg 平均值 精确
count 计数 精确
count_distinct 去重计数 估算 (HyperLogLog, 误差≈0.4%)
min / max 最小/最大值 精确
first / last 首个/最后一个值 精确
any 任意一个值 精确

统计聚合

函数 说明 精确/估算
percentile / pXX 百分位数 估算 (对数直方图)
median 中位数 估算
stddev 标准差 精确
mode 众数 精确
spread 极差 精确
count_series 时间序列数 精确

筛选聚合

函数 说明 精确/估算
top / bottom TopN / BottomN 精确
count_filter 条件计数 精确

直方图函数

函数 说明 适用数据源 精确/估算
histogram_auto 自动直方图(推荐 日志、Trace 明细数据 估算
histogram 固定桶边界直方图(已过时) 日志、Trace 明细数据 精确
histogram_quantile 从 Prometheus 直方图计算分位数 Prometheus 指标 估算

集合函数

函数 说明 精确/估算
distinct 去重值列表 精确
distinct_by_collapse 折叠去重(保留其他字段) 精确
collect 收集所有值 精确
collect_distinct 收集去重值 精确

辅助函数

函数 说明 精确/估算
default 设置默认值 精确

时间序列函数

函数 说明
rate 增长率(每秒)
irate 瞬时增长率
increase 增长量
derivative 导数
difference 差值
non_negative_derivative 非负导数
non_negative_difference 非负差值
moving_average 移动平均
cumsum 累积和

Rollup 函数

函数 说明
rate 计算增长率(每秒)
irate 计算瞬时增长率
increase 计算增长量
rate_over_sum 计算每秒平均值
rate_over_count 计算每秒计数
deriv 计算导数(derivative)
difference 计算差值(difference)
sum 求和
avg 平均值
min 最小值
max 最大值
count 计数
first 第一个值
last 最后一个值
stddev 标准差
mode 众数
spread 极差
any 任意一个值

转换函数

函数 说明
abs 绝对值
round / ceil / floor 取整
log / log2 / log10 对数
int / uint / float / string / bool 类型转换
substr 子字符串
regexp_extract 正则提取
regexp_extract_all 正则提取全部
md5 MD5 哈希
concat 字符串连接
set 数组去重排序
drain 日志聚类

匹配函数

函数 说明
match 子串匹配
phrase / search 分词短语匹配
re / regex / regexp 正则匹配
wildcard 通配符匹配
cidr CIDR 网段匹配
query_string 查询字符串语法
exists 字段存在检查

外层函数(优先使用 Rollup)

函数 说明
cumsum 累积和
rate / irate 增长率(非负)
deriv 导数(允许负值)
increase 增长量(非负)
difference 差值(允许负值)
moving_average 移动平均
top / bottom TopN
fill 空值填充(推荐外层使用)
abs / round / ceil / floor 数学运算
set 去重排序
concat 字符串连接

表达式计算

函数 说明
eval 多查询表达式计算

文档评价

文档内容是否对您有帮助? ×