作者:来自 Elastic Sergey Sidorov,Felix Barnsteiner,Kostas Krikellas,Costin Leau

Elasticsearch 现在在 ES|QL 中原生支持 PromQL,作为一等 source 命令。你可以直接在 Kibana 中对时间序列数据运行熟悉的 Prometheus 查询。
许多团队在日常工作中已经依赖 PromQL。我们正在让 PromQL 成为 Elasticsearch 中一等公民的体验。
ES|QL 中的新 PROMQL 命令让你可以用 PromQL 查询 Elasticsearch 中的时间序列数据,无论这些数据来自 Prometheus Remote Write、OpenTelemetry,还是其他来源。
指标、日志和追踪数据------全部统一在一个地方,并可在 Kibana 中直接进行探索。

PROMQL 源命令
PROMQL 是 ES|QL 中的一个 source 命令,类似于 FROM 或 TS。它接受标准的 PromQL 参数和一个 PromQL 表达式,执行查询,并将结果作为普通的 ES|QL 列返回,之后你可以继续使用其他命令对其进行处理。
其通用语法如下:
PROMQL [index=<pattern>] [step=<duration>] [start=<timestamp>] [end=<timestamp>]
[<value_column_name>=](<PromQL expression>)
这些参数与 Prometheus HTTP API 的查询参数(step、start、end)一致,因此如果你之前使用过 Prometheus 查询 API,会感觉非常熟悉。
基础范围查询
该查询计算在滑动 5 分钟窗口内 HTTP 请求的每秒速率,并按 instance 分组:
PROMQL index=metrics-*
step=1m
start="2026-04-01T00:00:00Z"
end="2026-04-01T01:00:00Z"
sum by (instance) (rate(http_requests_total[5m]))
结果包含三列:
| 列名 | 类型 | 描述 |
|---|---|---|
| sum by (instance) (rate(http_requests_total[5m])) | double | 计算得到的指标值 |
| step | date | 每个评估步的时间戳 |
| instance | keyword | 来自 by (instance) 的分组标签 |
当 PromQL 表达式包含跨时间序列聚合(例如 sum by (instance))时,每个分组标签都会成为一个独立的输出列。
当不存在跨时间序列聚合时,所有标签会作为一个 _timeseries 列返回,并以 JSON 字符串形式表示。
命名 value 列
默认情况下,value 列的名称就是 PromQL 表达式本身。你可以指定一个自定义名称,以便在后续命令中更方便地引用:
PROMQL index=metrics-*
step=1m
start="2026-04-01T00:00:00Z"
end="2026-04-01T01:00:00Z"
http_rate=(sum by (instance) (rate(http_requests_total[5m])))
| SORT http_rate DESC
这与在 STATS 中命名聚合的方式相同,例如:STATS avg_cpu = avg(system.cpu.usage)。
索引模式
index 参数支持与 FROM 和 TS 相同的模式,包括通配符和逗号分隔的列表。如果未指定,则默认使用 *,即查询所有配置了 index.mode: time_series 的索引。在生产环境中,建议显式指定索引模式,以避免扫描无关数据。
底层是如何工作的
PROMQL 命令并不会运行一个独立的查询引擎。相反,PROMQL 命令是在 ES|QL 计算引擎内部执行的,并且复用了通过 TS source 命令实现的时间序列聚合逻辑。
考虑下面这个 PromQL 查询:
PROMQL index=metrics-*
step=1m
start="2026-04-01T00:00:00Z"
end="2026-04-01T01:00:00Z"
sum by (host.name) (rate(http_requests_total[5m]))
在内部,PROMQL 命令会将该查询转换为一个等价的 ES|QL 查询,并使用 TS source 来执行:
TS metrics-*
| WHERE TRANGE("2026-04-01T00:00:00Z", "2026-04-01T01:00:00Z")
| STATS SUM(RATE(http_requests_total, 5m)) BY TBUCKET(1m), host.name
两个查询会产生相同的结果。
PROMQL 命令会解析 PromQL 语法,将函数映射为 ES|QL 中的等价实现(例如 rate 转换为 RATE,sum 转换为 SUM,avg_over_time 转换为 AVG_OVER_TIME 等),并构建一个逻辑执行计划,由 ES|QL 引擎执行。
这种转换方式的一个实际好处是:PromQL 查询可以自动受益于 ES|QL 引擎的所有优化能力,包括 segment 级并行处理以及时间序列感知的数据访问模式。
目前已有 19 个时间序列函数可用,覆盖速率(rates)、差值(deltas)、导数(derivatives)以及多种 *_over_time 聚合函数。
简化查询的智能默认值
在 Prometheus 中,PromQL 查询需要显式指定 start、end 和 step 参数。在 Kibana 中,这些参数通常由时间选择器和面板大小决定。PROMQL 命令提供了三个特性,使查询能够自动适配这些上下文。
自动 step
如果你省略 step 参数,系统会根据时间范围和目标桶数量自动推导 step(默认:100 个桶)。你也可以通过设置 buckets=<n> 来显式指定目标桶数量。
PROMQL index=metrics-*
start="2026-04-01T00:00:00Z"
end="2026-04-01T01:00:00Z"
sum by (instance) (rate(http_requests_total[5m]))
在 1 小时时间范围内,如果使用默认的 100 个桶目标,step 将为 1m,从而生成 60 个桶。这使用的是与 ES|QL BUCKET 函数相同的日期取整逻辑。
推断 start 和 end
Kibana 会通过对 @timestamp 的 Query DSL range filter,在每个 ES|QL 请求中自动添加时间范围过滤条件。PROMQL 命令会提取这些边界,并在查询未显式指定时,将其作为 start 和 end 使用。该命令可以直接从请求上下文中读取 date picker 的范围,无需额外配置。
隐式范围选择器
在标准 PromQL 中,像 rate 这样的函数需要显式的范围选择器,例如:rate(http_requests_total[5m])。而 PROMQL 命令允许省略该范围选择器:
PROMQL sum by (instance) (rate(http_requests_total))
当范围选择器缺失时,窗口会自动确定为 max(step, scrape_interval)。scrape_interval 默认值为 1m,如果你的数据有不同的采集间隔,可以通过 scrape_interval 参数覆盖,例如:PROMQL scrape_interval=15s sum(rate(http_requests_total))。
最终结果
结合这三个默认行为,在 Kibana 中一个完全自适应的查询如下所示:
PROMQL sum(rate(http_requests_total))
这个查询会响应 date picker 的时间范围选择,根据所选时间范围自动调整 step 大小,并相应地设置范围选择器窗口大小,无需手动调优。
使用 ES|QL 进行后处理
由于 PROMQL 是一个 ES|QL source 命令,它的输出会继续流入 ES|QL 的其余处理管道。你可以使用任意 ES|QL 命令对 PromQL 的结果进行过滤、排序、增强和转换。
过滤结果
PROMQL index=metrics-*
http_rate=(sum by (instance) (rate(http_requests_total[5m])))
| WHERE http_rate > 100
排序与限制(limit)
PROMQL index=metrics-*
http_rate=(sum by (instance) (rate(http_requests_total[5m])))
| SORT http_rate DESC
| LIMIT 10
使用 lookup 进行数据增强
PROMQL index=metrics-*
http_rate=(sum by (instance) (rate(http_requests_total[5m])))
| LOOKUP JOIN instance_metadata ON instance
这在 Prometheus 中是无法实现的。PromQL 的结果是自包含的,没有办法将其与外部数据进行 join,也无法进行任意的后处理。在 Elasticsearch 中,PromQL 的输出只是查询的第一阶段,之后可以继续使用任何 ES|QL 操作进行处理。
当前覆盖范围与后续计划
在 9.4 中,PROMQL 命令将作为技术预览提供,并且在对主流 Grafana 开源仪表盘进行基准测试时,查询覆盖率超过 80%。
当前技术预览中最主要的缺失包括:
-
尚不支持 group 修饰符,例如
on(chip) group_left(chip_name) -
尚未支持布尔集合运算符(
or、and、unless) -
部分函数仍未支持,包括
histogram_quantile、predict_linear和label_join
这些功能都已在后续版本规划中。路线图包括更完整的 PromQL 函数与操作符覆盖、与 Prometheus 对齐的 step 语义,以及对原生 histogram 的支持。
体验方式
PromQL 支持在 Elasticsearch Serverless 中作为技术预览直接使用,无需额外配置。对于自管理集群,从 9.4 版本开始提供支持。
在 Kibana 中体验方式如下:
-
进入 Dashboards,创建一个新的 panel,并选择 ES|QL 作为查询类型
-
输入 PromQL 查询,例如:
PROMQL index=metrics-* sum by (host.name) (rate(http_requests_total))
该命令会自动从 Kibana 的 date picker 推断时间范围,因此无需额外参数。
你也可以在 Discover 的 ES|QL 模式中运行 PromQL 查询,以表格或 XY 图表形式查看结果。后续将在专门的 Kibana 博客中详细介绍 PromQL 在 Dashboards、Discover 和 Alerting 中的完整使用方式。
完整命令参考(包括所有选项与示例)请查看 PROMQL command 文档。
如果你想在自管理集群中体验,可以使用 start-local 快速启动环境。
如果遇到问题或有反馈,可以在 Elasticsearch 仓库中提交 issue。
原文:https://www.elastic.co/observability-labs/blog/elasticsearch-supports-promql