Elasticsearch 查询日志:每个查询一行协调器级别日志,适用于 ES|QL、DSL、SQL 和 EQL

0 阅读12分钟

作者:来自 Elastic Najwa Harif 及 Valentin Crettaz

通过 Elasticsearch 查询日志,可以轻松理解查询对集群性能的影响。每个请求由一条协调器级别日志记录,覆盖 ES|QL、DSL、SQL 和 EQL,并提供完整的查询文本、追踪信息、可选用户上下文以及 CCS 提示。

测试 Elastic 的前沿开箱即用能力。深入 Elasticsearch Labs 仓库中的示例 notebooks,开始免费云试用,或立即在本地机器上体验 Elastic。


你的 dashboard 超时并且 CPU 飙升,但到底是哪条查询在执行?slow logs 每个 shard 只提供一行;Elasticsearch 查询日志则是每个请求一条 JSON 日志行,其端到端耗时与 API 中你已经信任的 took(在查询返回内容中的 took 字段) 相同。这一条日志还会捕获完整查询文本(适用于 ES|QL、DSL、SQL 和 EQL)、执行结果、追踪信息、可选用户上下文,以及在相关情况下的跨集群(CCS)提示。

这些日志遵循 ECS 规范,可以直接在 Discover 中使用,并且在开箱即用的 dashboard 中可直接可视化,只要你写入日志即可,无需自定义 schema 项目。下面内容将介绍我们为什么构建它、它与 slow logs 的区别、每一行包含的信息,以及如何启用它。

为什么我们要构建这个(你们问得很多!)

协调器级别的查询日志一直是一个非常高频的需求;我们倾听了这些反馈并最终交付了它!同样的问题不断出现:你希望在服务等级目标(SLO)和仪表盘中看到响应时长;你希望了解集群中查询执行的耗时;你还希望能够看到完整的查询内容。

在使用跨集群搜索(cross-cluster search)时,一个跨多个集群扩展的搜索在应用或 Kibana 视角下看起来像一次操作,但在运维层面,它实际上是一条工作链:协调、远程执行、合并、超时处理以及部分结果返回。当出现慢查询或不稳定情况时,团队不仅需要知道请求总耗时,还需要知道哪些集群参与了执行,以及最终结果是成功、部分成功还是完全失败。

你将获得的是:一条日志流、每个查询一条记录!每条记录都包含协调器耗时(即与搜索 API 响应一致的 took 时间)、成功或失败状态以及完整查询文本。该日志符合 Elastic Common Schema(ECS),支持可选的延迟阈值与用户/审计字段,同时包含 X-Opaque-Id,可以将热点查询追溯到其来源的 saved object,并通过 trace ID 与 Kibana 或你自己的工具进行关联。

更重要的是:这些日志遵循稳定的 ECS 对齐 schema,这意味着你不需要设计自己的数据接入 pipeline 或字段映射。这种一致性使得开箱即用的 dashboard 和分析能力可以在日志写入后立即生效。

Slow logs vs. query logs:30 秒版本

slow logs 多年来一直是常用工具。它们可以告诉你哪个搜索操作变慢了,但它们是以 shard 为单位输出日志 —— 每个 shard 只会产生一行,且每一行只反映该 shard 执行的一部分工作。这意味着,它们无法提供一个从客户端视角出发的、描述整个查询执行耗时的单一记录。query logs 则正好相反:每个查询只输出一行,并提供端到端(wall clock)耗时,这个时间与 search API 响应中的 took 时间一致。这使得它们更适合理解工作负载模式,以及快速定位问题查询。

slow logs 和 query logs 在触发时机与覆盖范围上也不同。slow logs 只有在 shard 执行超过阈值时才会写入,也就是说,它们主要用于“发现异常慢的 shard 工作”。query logs 可以记录所有查询(或仅记录超过你在集群级别配置的阈值的查询),因此你可以根据分析或排障需求调节日志量。slow logs 仅支持 DSL 查询,而 query logs 覆盖 ES|QLDSLSQLEQL,这更符合现代技术栈中 “这个集群到底执行了什么” 的分析方式。两者在 header 关联、trace 和审计信息方面提供相同能力(当你开启用户上下文时)。

下面的表格总结了传统 slow logs 与新的 query logs 功能之间的主要差异。

Slow logs vs. Query logs

对比项Slow logsQuery logs
用途用于定位 “热点 shard” 或慢索引操作,以及在单集群内进行传统性能调优用于理解“执行了什么查询”、端到端耗时(协调器视角)、执行是否成功,更适合 SLO、分析与故障排查
粒度按 shard(以及 phase)记录:一次用户查询可能在多个 shard / replica 上产生多条日志按协调器级别查询记录:一个查询对应一条日志事件
覆盖范围查询 + 索引仅查询(索引日志未来才会支持)
可获得的信息“这个 index 上的这个 shard 在 query/fetch 阶段超过 N ms”“这条查询(完整文本)、耗时、结果状态,以及(在相关情况下)跨集群/联邦查询汇总信息”
支持的查询类型仅 DSLES
阈值模型通常是分层阈值(多个时间档位、按 index 配置)集群级单一时间阈值(例如:≥ 500ms 记录日志)

每条日志里包含什么

每一条日志都是一个 JSON 对象(对应一个请求),存放在独立文件中(例如 Elasticsearch 日志目录下的 *_querylog.json)。下面是你可以从这些数据中获得的信息:

是否成功、耗时多少、哪里出错?

包含 执行结果(是否成功)耗时(took / took_millis,与 API 返回一致),以及发生错误或超时时的清晰失败信息。

这是用于告警、SLO 和仪表盘的核心信号:“系统是否正常?如果不正常,原因是什么?”

同时还会提供返回的行数或命中数(result_count),用于区分:

  • “慢但结果很少”

  • “慢且返回量很大”

实际执行了什么查询?

包含查询类型(esqldslsqleql)以及完整查询文本

这可以回答问题:

  • 哪个 dashboard 规则 / saved search / 客户端请求在持续压系统?

结合耗时和结果状态,可以快速定位最 “昂贵” 的查询进行优化或限流。

谁发起的请求?如何端到端追踪?

通过 X-Opaque-Idtrace ID,可以将日志关联回 Kibana 或自定义请求头。

task 和可选的 parent task ID 可以追踪异步或嵌套执行链路。

跨集群搜索(CCS):谁参与了?有没有异常?

在启用跨集群搜索时,日志可以包含:

  • 远程集群别名

  • 每个集群的耗时

  • 执行状态(成功 / 失败 / 部分成功 / 跳过)

你可以快速判断:

  • 慢是本地问题还是远端集群拖慢了整体响应

DSL 可以记录是否来自 remote alias
ES|QL 提供更丰富的 cluster map
EQL 在涉及远端时提供更轻量视图(例如涉及哪些 remote 以及数量)

安全信息(可选)

当开启 elasticsearch.querylog.include.user 时,可以获得:

  • 用户身份信息

  • realm 信息

  • run-as 情况下的 effective user

  • API key 元数据

结合查询文本和耗时,可以用于治理和容量分析(不仅看 IP,也看“谁在用”)。

还有更多信息

此外还可能包含:

  • 更细粒度的执行细节

  • shard 级别结果

  • 可选 profiling 信息(取决于查询类型)

完整字段与配置请参考 Elasticsearch 官方 query logs 文档

日志存放位置(以及如何使用)

日志会以 *_querylog.json 的形式写入 Elasticsearch 的日志目录中(例如 mycluster_querylog.json),位于协调节点(coordinating node)上。

你可以通过 Filebeat Elasticsearch 模块中的 querylog fileset 来采集这些日志,然后在 Discover 中查看(通过 event.dataset: elasticsearch.querylog 过滤)。

在 Elastic Cloud 上,你需要先为 deployment 启用 Logs,一旦开启,query logs 就会自动开始收集与传输。


两种使用方式

如果你只是想做一次性排查,例如:

  • 谁在 “打爆” 集群

  • 当前查询类型分布是什么

  • 做一次快速审计

可以直接开启日志,设置一个 duration 阈值(例如 ≥ 1 秒或 ≥ 5 分钟),只记录有意义的慢查询,用完后关闭即可。

如果你需要持续性的查询分析,只需:

  • 启用 logging

  • 用 Filebeat 采集日志

  • 在监控集群上打开 dashboard

非常简单的两步:启用 + 采集,就完成了。

每条请求一行,每条请求一个耗时,无需任何自定义 pipeline。


Dashboard 概览

下面的 dashboard 基于新的 query logs 开箱即用。

在顶部一行,你可以看到:

  • P95 / P99 查询延迟(以及可选的 “可接受延迟” 参考线)

  • 查询类型分布

  • 成功 / 失败比例

  • 用户查询 vs 系统查询比例

  • (针对 DSL)hits 与 aggregations 的比例

在下方,你可以看到:

  • 延迟随时间变化(avg、p50、p95、p99、max),并带有参考线用于识别回归

  • 查询量随时间变化(按类型分层)

  • Top indices、Top users、Top error types 表格

通过 cluster、user 或 index 过滤器,你可以精确聚焦到你关心的范围。

提醒一下:查询日志是异步的,因此不会阻塞查询执行。你可以使用 duration 阈值来控制日志量。

另外需要注意,在非常高的 QPS(每秒查询数)情况下,我们可能会丢弃部分日志记录,而不是让集群性能受到影响。对于分析用途,建议将日志发送到独立的监控集群,这样可以避免正在排障的集群承担额外负载。

一些配置与代码示例

查询日志默认是关闭的。你可以在 elasticsearch.yml 中开启,或者通过 cluster settings API 开启。方法如下:

启用查询日志

elasticsearch.yml 中:

`elasticsearch.querylog.enabled: true`AI写代码

或者通过集群设置 API 动态开启:

`

1.  PUT _cluster/settings
2.  {
3.    "persistent": {
4.      "elasticsearch.querylog.enabled": "true"
5.    }
6.  }

`AI写代码

仅记录超过持续时间阈值的查询

如果你不希望记录每一个健康检查或极小请求,只需设置一个阈值,让系统仅在查询执行时间达到或超过该阈值时才写入日志。duration 的单位是时间单位:

`

1.  PUT _cluster/settings
2.  {
3.    "persistent": {
4.      "elasticsearch.querylog.enabled": "true",
5.      "elasticsearch.querylog.threshold": "1s"
6.    }
7.  }

`AI写代码

包含用户 / 审计信息

如果你使用 Security 插件,并且希望查看每条查询是由谁执行的:

`

1.  PUT _cluster/settings
2.  {
3.    "persistent": {
4.      "elasticsearch.querylog.enabled": "true",
5.      "elasticsearch.querylog.include.user": "true"
6.    }
7.  }

`AI写代码

记录仅命中系统索引的 DSL 查询

默认情况下,只针对系统索引(system indices)的搜索不会被记录。

如果你希望将这些查询也纳入日志,需要启用 query logging,并设置:

`

1.  PUT _cluster/settings
2.  {
3.    "persistent": {
4.      "elasticsearch.querylog.enabled": "true",
5.      "elasticsearch.querylog.include.system_indices": "true"
6.    }
7.  }

`AI写代码

示例日志条目

一行 = 一个 JSON 对象 = 一个请求,对 ES|QL、DSL、SQL、EQL 都具有相同结构。下面分别展示一个成功的 DSL 查询和一个失败的 EQL 查询,包括时间戳、耗时、查询类型和完整查询内容。成功时会包含结果数量和 shard 统计信息;失败时会包含错误信息块。当你启用相关配置后,还会包含用户信息和 X-Opaque-Id。

成功(DSL 查询):

`

1.  {
2.    "@timestamp": "2026-03-04T19:40:34.736Z",
3.    "log": {
4.      "level": "INFO",
5.      "logger": "elasticsearch.querylog"
6.    },
7.    "event": {
8.      "duration": 1000000,
9.      "outcome": "success"
10.    },
11.    "elasticsearch": {
12.      "querylog": {
13.        "type": "dsl",
14.        "query": "{\"size\":10,\"query\":{\"match_all\":{\"boost\":1.0}}}",
15.        "indices": ["query_log_test_index"],
16.        "result_count": 3,
17.        "search": { "total_count": 3 },
18.        "shards": { "successful": 1 },
19.        "took": 1000000,
20.        "took_millis": 1
21.      },
22.      "node": { "name": "node-1" },
23.      "cluster": { "name": "my-es-cluster" }
24.    },
25.    "http": {
26.      "request": {
27.        "headers": { "x_opaque_id": "opaque-1772653234" }
28.      }
29.    },
30.    "user": {
31.      "name": "elastic",
32.      "realm": "reserved"
33.    }
34.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

失败(EQL 查询):

`

1.  {
2.    "@timestamp": "2026-03-04T19:40:35.271Z",
3.    "log": {
4.      "level": "INFO",
5.      "logger": "elasticsearch.querylog"
6.    },
7.    "event": {
8.      "duration": 1326334,
9.      "outcome": "failure"
10.    },
11.    "elasticsearch": {
12.      "querylog": {
13.        "type": "eql",
14.        "query": "any where true",
15.        "indices": ["nonexistent_index_xyz"],
16.        "result_count": 0,
17.        "took_millis": 1
18.      },
19.      "node": { "name": "node-1" },
20.      "cluster": { "name": "my-es-cluster" }
21.    },
22.    "error": {
23.      "type": "org.elasticsearch.index.IndexNotFoundException",
24.      "message": "no such index [Unknown index [nonexistent_index_xyz]]"
25.    }
26.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

总结

Elasticsearch 查询日志为每个查询提供一条协调器级别日志(覆盖 ES|QL、DSL、SQL、EQL)。每个请求一行,包含协调器耗时、完整查询内容,以及可选的用户信息和 X-Opaque-Id。启用后,你可以设置持续时间阈值以及用户信息采集(如需要),即可完成配置。

日志存储在日志目录中(*_querylog.json),通过 Filebeat 采集后,可以在 Discover 中通过 elasticsearch.querylog 数据集查看。

完整配置项和字段说明请参考 Elasticsearch 查询日志官方文档。慢查询或异常查询也可以在 AutoOps 中查看,它利用 X-Opaque-Id 将长耗时搜索追溯到其来源,例如 dashboard、saved search 或告警规则。

最后需要注意的是,这个新的查询日志是 9.2 版本中仅支持 ES|QL 的查询日志的演进版本。我们建议使用新的查询日志,因为它不仅支持 ES|QL,还支持所有其他查询类型。

现在,可以去看看你的集群里到底在运行什么查询了。

原文:www.elastic.co/search-labs…