作者:来自 Elastic Jeffrey Rengifo

一个结账服务的 p95 延迟为 582 毫秒,而 SLO 目标为 350 毫秒。在 Kibana 的 Discover 中使用一个 KQL 查询即可找到它。要确定哪个团队负责该服务,则需要使用一个 ES|QL 查询,通过 LOOKUP JOIN 将指标文档与一个小型服务目录索引进行连接。下面将按顺序进行这项调查。一个 数据视图 可以缩小范围,而 过滤条件标签 会让这些条件保持可见。当需要其他人重新还原你搜索过的内容时,这一点比听起来更加重要。KQL 完成了大部分工作。Lucene 查询语法用于处理唯一一个需要正则表达式的情况,而一旦过滤无法继续回答问题,就由 ES|QL 接手。
前提条件
要跟随本文进行操作,你需要:
-
一个配有 Kibana 的 Elasticsearch 集群。从这里到 ES|QL 部分的所有内容都可以在任何较新的版本上运行;
LOOKUP JOIN在 Elasticsearch 9.1 中正式发布,在 9.0 中属于技术预览,因此最后一部分需要使用 9.1 或更高版本。 -
不需要特殊的许可证层级。本文中的所有内容,包括
LOOKUP JOIN,都可以在免费的基础许可证下运行。 -
下一部分创建的两个小型示例索引。
为什么生产环境中的结账延迟增加了
示例从一个常见的运维问题开始:
为什么生产环境中的结账延迟增加了,以及哪个团队负责这个服务?
指标索引包含三个区域中四个服务的 15 分钟服务测量数据。其中一个服务 checkout-api 在调查时间窗口内的 us-central1 中具有更高的 p95 延迟。目标是从所有指标中找到能够解释这个问题的少量文档。
整个操作按照以下步骤进行:
-
选择正确的数据视图和时间范围。
-
使用界面过滤条件进行包含、排除、停用和固定条件。
-
使用 KQL 进行主要字段和范围搜索。
-
当正则表达式语法有用时,切换到 Lucene。
-
使用带有
LOOKUP JOIN的 ES|QL 模式,将指标与服务目录数据进行丰富。
设置示例指标索引
本操作会搜索名为 o11y-labs-discover-service-metrics 的指标索引。创建该索引时,为服务维度使用关键词字段,为测量值使用数值字段:
bash
`
1. PUT o11y-labs-discover-service-metrics
2. {
3. "mappings": {
4. "properties": {
5. "@timestamp": { "type": "date" },
6. "service": {
7. "properties": {
8. "name": { "type": "keyword" },
9. "environment": { "type": "keyword" },
10. "version": { "type": "keyword" }
11. }
12. },
13. "cloud": { "properties": { "region": { "type": "keyword" } } },
14. "host": { "properties": { "name": { "type": "keyword" } } },
15. "metrics": {
16. "properties": {
17. "latency": { "properties": { "p95_ms": { "type": "float" } } },
18. "cpu": { "properties": { "pct": { "type": "float" } } },
19. "error": { "properties": { "rate": { "type": "float" } } }
20. }
21. }
22. }
23. }
24. }
`Lobster AI
每个文档代表一个服务在一个区域中的一次 15 分钟测量:
less
`
1. POST o11y-labs-discover-service-metrics/_bulk
2. { "index": {} }
3. { "@timestamp": "2026-06-30T16:15:00.000Z", "service": { "name": "checkout-api", "environment": "production", "version": "2026.06.30-1" }, "cloud": { "region": "us-central1" }, "host": { "name": "checkout-api-us-central1-01" }, "metrics": { "latency": { "p95_ms": 582.6 }, "cpu": { "pct": 0.81 }, "error": { "rate": 0.041 } } }
4. { "index": {} }
5. { "@timestamp": "2026-06-30T16:15:00.000Z", "service": { "name": "payments-api", "environment": "production", "version": "2026.06.29-7" }, "cloud": { "region": "us-central1" }, "host": { "name": "payments-api-us-central1-01" }, "metrics": { "latency": { "p95_ms": 231.4 }, "cpu": { "pct": 0.31 }, "error": { "rate": 0.008 } } }
`Lobster AI
为了复现截图,请针对每个服务、区域和 15 分钟时间间隔建立一个文档:
-
服务:
checkout-api、checkout-worker、payments-api、inventory-api -
区域:
us-central1、us-east4、europe-west1 -
时间窗口: 2026 年 6 月 30 日 14:00 至 19:45 UTC,共 24 个 15 分钟时间间隔
-
每个时间间隔的文档数: 12 个生产环境文档,另外加上两个
staging文档(checkout-api和payments-api,两者都位于us-central1) -
总计: 24 个时间间隔 × 14 个文档 = 336 个文档
具体数值并不重要,只要 us-central1 中的 checkout-api 在 15:45 至 18:45 UTC 期间报告的 metrics.latency.p95_ms 高于 500,并且在其他所有时间都稳定低于 500 毫秒即可。
你不需要手动建立所有文档,可以运行 配套笔记本,它会生成完整的 336 个文档数据集,创建两个索引,并验证最终的 ES|QL 查询。
ES|QL 部分还会使用第二个包含四个文档的查找索引,用于存储服务目录数据。我们将在进行到那里时创建它。
在 Kibana Discover 中选择数据视图
数据视图是 Discover 中的第一个过滤条件。它决定要搜索哪些 Elasticsearch 索引、哪个时间字段用于驱动直方图,以及左侧字段列表中有哪些可用字段。

在本操作中,Discover 数据视图指向:
c
`o11y-labs-discover-service-metrics`Lobster AI
时间字段是 @timestamp。这一点很重要,因为时间选择器会在你添加查询、过滤条件标签或选择字段之前,就先限制文档范围。
在条件允许的情况下,使用范围较窄的数据视图。例如,当你已经知道问题与指标有关时,只针对服务指标的数据视图,比使用范围较广的 logs-*、metrics-* 数据视图更容易在 Discover 中快速浏览。
选择数据视图后,添加支持调查的字段:
-
service.name -
service.environment -
cloud.region -
metrics.latency.p95_ms -
metrics.cpu.pct -
metrics.error.rate
Discover 中的过滤条件标签:包含、排除、停用和固定
当你希望看到一个清晰、可编辑的条件列表时,界面过滤条件非常有用。当你从文档表格中探索字段,并希望 Discover 自动为你生成字段语法时,它们也很有帮助。
在文档表格中,使用字段操作(将鼠标悬停在某个值上时出现的 +/- 图标)来包含或排除该值。例如:
yaml
`
1. service.environment: production
2. NOT cloud.region: us-east4
3. service.version: 2026.06.29-7 (disabled)
`Lobster AI

这三个过滤条件展示了 主要的 过滤控制方式:
-
当你只需要匹配的文档时,包含某个值。
-
当某个维度与问题无关时,排除某个值。
-
当你想暂时保留某个过滤条件,但将其从当前查询中移除时,可以暂时停用该过滤条件。
-
当你在不同 Kibana 应用之间切换时,如果某个过滤条件应该始终保持生效,可以将其固定。
固定的过滤条件对于跨应用进行调查非常有用。例如,在从 Discover 转到 仪表板、Lens 或其他视图之前,你可以固定 service.environment: production。停用过滤条件则适合用于验证某个假设,同时又不删除引导你进行到这一步的上下文。
关键习惯是让过滤条件保持可读。如果一个查询包含很长的搜索表达式以及许多隐藏的假设,其他工程师就需要重新推断你的思路。过滤条件标签可以让主要的范围决策清晰可见。
用于字段、范围和布尔搜索的 KQL 查询语法
KQL,即 Kibana 查询语言,是 Discover 搜索的一个很好的默认选择。它以易读的形式支持字段名称、精确值、范围、通配符和布尔逻辑。
对于结账延迟示例,下面这个 KQL 查询会将视图缩小到一个服务、一个区域以及较高的 p95 延迟:

arduino
`service.name : "checkout-api" and cloud.region : "us-central1" and metrics.latency.p95_ms >= 500`Lobster AI
从左到右阅读:
service.name : "checkout-api"保留一个服务。cloud.region : "us-central1"保留一个云区域。metrics.latency.p95_ms >= 500保留大于或等于 500 毫秒的延迟样本。
你可以在 KQL 中添加环境条件:
arduino
`service.environment : "production" and service.name : "checkout-api" and cloud.region : "us-central1" and metrics.latency.p95_ms >= 500`Lobster AI
或者,你也可以将 service.environment: production 保留为界面过滤条件。两种方式都有效。对于需要共享的调查,我们更倾向于将稳定的范围条件,例如环境和服务,作为过滤条件标签,而将当前假设,例如延迟阈值,放在搜索栏中。
KQL 也非常适合组合多个字段:
less
`
1. service.environment : "production" and
2. (service.name : "checkout-api" or service.name : "payments-api") and
3. metrics.error.rate > 0.02
`Lobster AI
当一个面向用户的流程跨越多个服务时,这非常有用。你可以在不切换数据视图或先创建仪表板的情况下,对一小组服务进行比较。
Kibana 中的 Lucene 查询语法:使用正则表达式进行搜索
Lucene 查询语法是 Kibana 中支持正则表达式的选项。KQL 不支持正则表达式,因此当你需要在搜索栏中使用正则表达式时,打开搜索栏右侧的查询菜单,并将语言切换为 Lucene。

例如,下面这个 Lucene 查询会搜索生产环境中名称以 checkout- 开头且 p95 延迟高于 500 毫秒的服务:
bash
`service.name:/checkout-.*/ AND service.environment:production AND metrics.latency.p95_ms:>500`Lobster AI
Lucene 语法更加简洁,但也更容易被误读。当它能够表达一些你无法用 KQL 清晰表达的内容时,可以使用它,例如针对某个字段使用正则表达式模式。对于日常的字段、值和范围过滤,KQL 通常更容易让团队成员进行审查。
如何在 Discover 中使用 ES|QL 的 LOOKUP JOIN 连接两个索引
经典的 Discover 模式适合用于搜索、过滤、检查字段以及查看原始文档。Discover 中的 ES|QL 更适合那些需要先进行转换才能让结果变得有用的问题。使用 Discover 工具栏中的 使用 ES|QL 查询按钮即可切换模式。

在这个示例中,原始指标告诉我们 checkout-api 的延迟很高。但它们无法告诉我们哪个团队负责该服务,也无法告诉我们该服务需要达到什么延迟目标。这些数据存储在一个小型的服务目录查找索引中。
创建用于服务目录数据的查找索引
markdown
`
1. PUT o11y-labs-service-catalog-lookup
2. {
3. "settings": {
4. "index.mode": "lookup"
5. },
6. "mappings": {
7. "properties": {
8. "service": {
9. "properties": {
10. "name": {
11. "type": "keyword"
12. }
13. }
14. },
15. "owner": {
16. "properties": {
17. "team": {
18. "type": "keyword"
19. }
20. }
21. },
22. "slo": {
23. "properties": {
24. "latency_target_ms": {
25. "type": "long"
26. }
27. }
28. },
29. "runbook": {
30. "properties": {
31. "url": {
32. "type": "keyword"
33. }
34. }
35. }
36. }
37. }
38. }
`Lobster AI
一个目录文档可以为服务关联 负责人 信息和 SLO 目标:
bash
`
1. POST o11y-labs-service-catalog-lookup/_doc/checkout-api
2. {
3. "service": {
4. "name": "checkout-api"
5. },
6. "owner": {
7. "team": "checkout-platform"
8. },
9. "slo": {
10. "latency_target_ms": 350
11. },
12. "runbook": {
13. "url": "https://runbooks.example.com/checkout-api/latency"
14. }
15. }
`Lobster AI
运行 LOOKUP JOIN 查询
现在,Discover 可以使用 ES|QL 查询,通过 LOOKUP JOIN 将指标文档与该目录元数据进行连接。请记住,该命令需要 Elasticsearch 9.1 或更高版本,查找索引必须使用 index.mode: lookup 创建,并且连接字段(这里是 service.name)必须在查找索引中映射为 keyword。
sql
`
1. FROM o11y-labs-discover-service-metrics
2. | WHERE @timestamp >= "2026-06-30T15:00:00.000Z" AND @timestamp <= "2026-06-30T18:45:00.000Z"
3. | WHERE service.environment == "production"
4. | LOOKUP JOIN o11y-labs-service-catalog-lookup ON service.name
5. | WHERE owner.team == "checkout-platform" AND metrics.latency.p95_ms > slo.latency_target_ms
6. | KEEP @timestamp, service.name, cloud.region, metrics.latency.p95_ms, slo.latency_target_ms, owner.team
7. | SORT @timestamp DESC
`Lobster AI
这正是经典模式无法覆盖的部分。经典 Discover 可以过滤指标文档,但 ES|QL 可以在显示结果之前,使用另一个索引中的数据丰富这些行。

结果表回答的是一个比最初搜索更加偏向运维的问题。它在一个视图中展示了受影响的服务、区域、延迟值、目标值以及负责该服务的团队。
这种模式不仅适用于确定负责人。你可以为服务层级、部署环、升级渠道、业务能力或运行手册 URL 保留小型查找索引。然后在调查时,将这些上下文连接到指标搜索中。
如何选择正确的 Discover 搜索方式
最有用的工作流程并不是对所有内容都使用一种搜索语言,而是从宽泛的范围逐步缩小到具体证据。
| 使用场景 | Discover 功能 | 作用 |
|---|---|---|
| 限制可搜索的数据 | 数据视图和时间选择器 | 在查询运行之前移除无关索引和旧文档 |
| 保持范围可见 | 界面过滤条件 | 让包含、排除、停用和固定的条件易于查看 |
| 搜索精确字段和值范围 | KQL | 让常见的指标搜索保持可读 |
| 使用正则表达式匹配字段值 | Lucene 模式 | 当搜索需要正则表达式时提供正则表达式语法 |
| 丰富或重新组织结果 | ES | QL 模式 |
对于实际调查,从仍然包含所需数据的最小数据视图开始。为稳定的范围条件添加过滤条件标签。使用 KQL 进行当前搜索。只有当正则表达式语法值得增加额外复杂度时,才切换到 Lucene。当问题需要数据丰富、聚合或重新组织结果时,再转向 ES|QL。
让指标更容易搜索的字段命名约定
当字段名称能够提供足够的上下文时,指标搜索效果最佳。上面的示例尽可能使用 Elastic 通用模式 风格的字段:
-
service.name用于标识受监控的服务。 -
service.environment用于标识生产、预发布或开发环境。 -
cloud.region用于标识部署区域。 -
host.name用于深入查看主机级别的信息。 -
数值型指标字段位于
metrics.*下。
你不需要使用完全相同的模式才能使用 Discover,但一致且可预测的字段名称会让搜索栏和过滤条件标签更容易使用。它们也能让已保存的搜索和截图在交接过程中更容易理解。
对于服务目录数据,应保持查找索引小型且稳定。服务负责人、服务层级、SLO 目标和运行手册 URL 等字段的变化频率低于原始指标。这使它们非常适合在分析期间使用 LOOKUP JOIN。
在你自己的集群上运行整个操作
将 Discover 用作深入分析的路径,而不仅仅是一个文档表格。在这个操作中,我们:
-
在编写任何查询之前,通过较窄的数据视图和时间选择器限定搜索范围。
-
使用包含、排除、停用和固定的过滤条件标签,让调查范围保持可见且易于共享。
-
使用 KQL 进行易读的字段、范围和布尔搜索。
-
只有在 KQL 无法表达正则表达式的情况下,才切换到 Lucene。
-
使用 ES|QL 的
LOOKUP JOIN,从查找索引中获取负责人和 SLO 数据,对指标文档进行丰富。
如果想在自己的集群上尝试完整流程,可以运行配套笔记本,它会创建两个索引以及所有示例中使用的故障事件数据。
相关文档:
相关 Observability Labs 文章:
原文:Kibana Discover search: KQL, Lucene query syntax, and ES|QL | Elastic Observability Labs