为 Elasticsearch 带来火力:增加原生 Prometheus API 支持
作者来自 Elastic Felix BarnsteinerElasticsearch 正在在早期 PromQL 和 Remote Write 工作之上添加原生 Prometheus 查询、发现和元数据 APIs并提供不断演进的元数据支持。Elasticsearch具有与行业领先的 Gen AI 工具和提供商的原生集成。查看我们关于 Beyond RAG Basics 的网络研讨会或构建生产级应用 Elastic 向量数据库。为了为你的用例构建最佳搜索解决方案请启动免费的云试用或立即在本地机器上尝试 Elastic。Prometheus-compatible 客户端依赖于一个用于查询、指标发现和摄取的标准 HTTP API。Elasticsearch 正在其现有的时间序列数据流之上添加 Prometheus-compatible APIs使这些客户端可以直接与 Elasticsearch 通信。这包括通过 Prometheus Remote Write 摄取的指标以及已经通过 OpenTelemetry、Bulk API 或其他摄取路径存储在 Elasticsearch 中的指标。本文解释了查询、发现和元数据 endpoints 如何基于早期的摄取和查询工作构建从而形成这一 API 表面。几篇配套文章会更深入地讲解各个部分Elasticsearch 中的 Native PromQL 支持在 ES|QL 中介绍了 PromQL 查询如何被转换为 ES|QL 执行计划。通过 Remote Write 向 Elasticsearch 发送 Prometheus 指标介绍了摄取设置。Prometheus Remote Write 在 Elasticsearch 中的工作原理介绍了 remote write 的内部机制。这仍然是一个正在进行中的工作。下面的部分会指出当前已支持的内容以及仍在演进中的部分。API 接口目前Prometheus-compatible API 表面分为三组。查询 endpoints查询 endpoints 允许 Prometheus-compatible 客户端评估 PromQL 表达式GET /_prometheus/api/v1/query_range 在一个时间窗口内评估 PromQL 表达式matrix 结果。GET /_prometheus/api/v1/query 在单个时间点评估vector 结果。当前通过短时间范围查询实现并返回最后一个样本。目前查询 endpoints 只支持 GET。一些客户端默认使用 POST因此你可能需要配置它们使用 GET。Prometheus 的 POST 约定使用 application/x-www-form-urlencoded 请求体而 Elasticsearch 的 HTTP 层会在请求到达 handler 之前将其拒绝以作为 CSRF 防护措施。关于 PromQL 覆盖范围的完整状态请参见 ES|QL 中 PromQL 的配套文章。元数据 endpoints元数据 endpoints 提供客户端用于自动补全、变量下拉列表以及指标浏览所需的发现信息。series、labels 和 label values endpoints 都支持 match[] 选择器以及时间范围start/end。match[] 参数接受类似 http_requests_total{jobapi} 这样的 Prometheus 序列选择器并将响应限制为匹配的时间序列。这使得在拥有大量指标的集群上响应仍然保持快速且相关。例如GET /_prometheus/api/v1/series?match[]http_requests_total{jobapi}GET /_prometheus/api/v1/labels?match[]http_requests_totalGET /_prometheus/api/v1/label/instance/values?match[]http_requests_total{jobapi}第一条返回所有 http_requests_total 且 jobapi 的 series以及它们完整的 label 集合。第二条只返回 http_requests_total series 上存在的 label 名称。第三条只返回匹配 series 上出现的 instance 值。GET /_prometheus/api/v1/metadata 是不同的它返回每个 metric 的 type 和 unit并且可以通过 metric 参数按名称进行过滤。GET /_prometheus/api/v1/metadata?metrichttp_requests_total它不接受 match[] 选择器或时间范围。在 Prometheus 中元数据是从活跃的 scrape targets 收集的它们暴露的 HELP、TYPE 和 UNIT 行因此响应不涉及数据扫描。Elasticsearch没有像那样的专用元数据存储因此当前实现通过访问最近 24 小时内的时间序列数据来发现指标元数据。这使查询保持快速而不需要完整索引扫描。这个 24 小时回看窗口目前是固定的Prometheus metadata API 不暴露 start 或 end 参数因此 Elasticsearch 无法将其做成用户可调整。元数据 endpoints 在底层如何工作包括支撑它们的 TS_INFO 和 METRICS_INFO 命令将在下文介绍。索引预过滤所有查询和元数据 endpoints 都支持在 /_prometheus/ 之后添加一个可选的 {index} 路径段GET /_prometheus/metrics-prod-*/api/v1/query_range?queryupstart...end...这会在任何表达式评估开始之前先限制查询运行的 Elasticsearch 索引范围。在拥有大量跨团队或跨环境数据流的集群中这可以避免扫描无关索引并显著降低查询延迟。你可以按索引模式配置独立的数据源从而为不同团队提供各自的指标访问范围。关于 Remote Write 的说明在摄取方面Elasticsearch 也提供标准 Prometheus Remote Write endpointPOST /_prometheus/api/v1/write 通过 Prometheus Remote Write v1 协议写入时间序列目前尚不支持 v2。Remote Write 会写入 Elasticsearch 现有的时间序列数据流TSDS而不是一个独立的 Prometheus 专用存储层。Prometheus labels 会变成 TSDS dimensions而 metric names 会成为索引 mapping 中的字段。remote write 架构文章会更详细说明完整映射方式包括 metric 类型如何推断以及 labels 如何以 labels. 前缀存储。工作原理在底层所有 endpoints 的工作方式一致解析传入的 HTTP 参数构建 ES|QL 查询计划在时间序列数据流上执行并将列式结果转换回 Prometheus 客户端期望的 JSON 格式。TS_INFO 和 METRICS_INFO元数据 endpoints 需要回答诸如 “存在哪些 label” 或 “定义了哪些 metric 类型” 这样的问题而且这些问题可能涉及数百万条时间序列但不能扫描每一个数据点。在内部Prometheus metadata endpoints 通过围绕两个新的处理命令构建 ES|QL 计划来回答这些问题METRICS_INFO 和 TS_INFO。你不需要直接使用这些命令来使用 Prometheus API但它们是 metadata responses 背后的核心执行原语。这两者都通过只访问每个时间序列中的一个文档来提取其元数据而不是扫描所有 samples。因此它们的成本只随“不同时间序列的数量”增长而不是随“数据点数量”增长。METRICS_INFO 会为每个不同 metric 返回一行包括 metric 名称、类型、单位以及相关的 dimension 字段。TS_INFO 则更细粒度它为每个metric时间序列组合返回一行并包含以 JSON 对象形式表示的实际 dimension 值。TS metrics-* | METRICS_INFO | SORT metric_name一篇专门介绍 TS_INFO 和 METRICS_INFO 的博客即将发布其中会涵盖双阶段执行模型、它们如何扩展以及如何在 ES|QL 查询中直接使用它们超越 Prometheus API。metadata endpoints 如何使用它们每个 metadata endpoint 都会以其中一个命令为核心来构建 ES|QL 计划。/api/v1/labels 和 /api/v1/series 使用 TS_INFO因为它们需要按时间序列粒度的信息哪些 label 存在、哪些 dimension 值标识每条 series。/api/v1/metadata 和 /api/v1/label/__name__/values 使用 METRICS_INFO因为它们只需要按 metric 粒度的信息metric 名称、类型、单位。对于普通 label除了 __name__之外/api/v1/label/{name}/values 不使用这两个命令中的任何一个。像 job 或 instance 这样的常规 label 在索引中本身就是 dimension 字段因此该 endpoint 可以直接通过 group-by 聚合来查询。当提供 match[] 选择器时它们会被转换为 WHERE 子句在聚合执行前先过滤时间序列。__name__label 需要不同的策略因为它并不总是以 dimension 字段的形式存在。Prometheus Remote Write 确实会存储 labels.__name__但通过 OpenTelemetry、Bulk API 等其他路径摄取的 metrics 并不一定包含它。metric 名称通常被编码在字段名中例如 metrics.http_requests_total。虽然可以通过索引 mapping 枚举字段名但 mapping 并不能告诉你每个 metric 对应哪些 dimensions也无法基于 match[] 的 label 条件进行过滤。METRICS_INFO 可以同时解决这两个问题它在跨索引枚举 metric 名称的同时也能遵循上游 WHERE 过滤条件。在所有情况下API 层都会负责将结果转换回 Prometheus 约定去掉 labels. 和 metrics. 这些存储前缀并为那些没有 __name__的非 Prometheus metrics 合成name。总结Elasticsearch 正在逐步在 API 层实现 Prometheus 兼容性这建立在此前 Remote Write 摄取和 PromQL 查询执行工作的基础之上。其目标是让 Prometheus-aware 工具可以通过它们已经理解的 API 来查询和探索 Elasticsearch 的 metrics。这项工作仍在进行中目前在 Elasticsearch Serverless 以及 9.4 版本的自管理集群和 Elastic Cloud Hosted 部署中以技术预览形式提供但 GET /_prometheus/api/v1/metadata 除外。要在本地进行实验请使用 start-local。原文https://www.elastic.co/search-labs/blog/elasticsearch-native-prometheus-api#ts-info-and-metrics-info