从 582 毫秒的延迟峰值追踪到负责该服务的团队:使用 Kibana Discover

55 阅读14分钟

作者:来自 Elastic Jeffrey Rengifo

一个结账服务的 p95 延迟为 582 毫秒,而 SLO 目标为 350 毫秒。在 Kibana 的 Discover 中使用一个 KQL 查询即可找到它。要确定哪个团队负责该服务,则需要使用一个 ES|QL 查询,通过 LOOKUP JOIN 将指标文档与一个小型服务目录索引进行连接。下面将按顺序进行这项调查。一个 数据视图 可以缩小范围,而 过滤条件标签 会让这些条件保持可见。当需要其他人重新还原你搜索过的内容时,这一点比听起来更加重要。KQL 完成了大部分工作。Lucene 查询语法用于处理唯一一个需要正则表达式的情况,而一旦过滤无法继续回答问题,就由 ES|QL 接手。

前提条件

要跟随本文进行操作,你需要:

  • 一个配有 KibanaElasticsearch 集群。从这里到 ES|QL 部分的所有内容都可以在任何较新的版本上运行;LOOKUP JOIN 在 Elasticsearch 9.1 中正式发布,在 9.0 中属于技术预览,因此最后一部分需要使用 9.1 或更高版本。

  • 不需要特殊的许可证层级。本文中的所有内容,包括 LOOKUP JOIN,都可以在免费的基础许可证下运行。

  • 下一部分创建的两个小型示例索引。

为什么生产环境中的结账延迟增加了

示例从一个常见的运维问题开始:

为什么生产环境中的结账延迟增加了,以及哪个团队负责这个服务?

指标索引包含三个区域中四个服务的 15 分钟服务测量数据。其中一个服务 checkout-api 在调查时间窗口内的 us-central1 中具有更高的 p95 延迟。目标是从所有指标中找到能够解释这个问题的少量文档。

整个操作按照以下步骤进行:

  1. 选择正确的数据视图和时间范围。

  2. 使用界面过滤条件进行包含、排除、停用和固定条件。

  3. 使用 KQL 进行主要字段和范围搜索。

  4. 当正则表达式语法有用时,切换到 Lucene。

  5. 使用带有 LOOKUP JOIN 的 ES|QL 模式,将指标与服务目录数据进行丰富。

设置示例指标索引

本操作会搜索名为 o11y-labs-discover-service-metrics 的指标索引。创建该索引时,为服务维度使用关键词字段,为测量值使用数值字段:

`

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![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

每个文档代表一个服务在一个区域中的一次 15 分钟测量:

`

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-apicheckout-workerpayments-apiinventory-api

  • 区域: us-central1us-east4europe-west1

  • 时间窗口: 2026 年 6 月 30 日 14:00 至 19:45 UTC,共 24 个 15 分钟时间间隔

  • 每个时间间隔的文档数: 12 个生产环境文档,另外加上两个 staging 文档(checkout-apipayments-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 数据视图指向:

`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 自动为你生成字段语法时,它们也很有帮助。

在文档表格中,使用字段操作(将鼠标悬停在某个值上时出现的 +/- 图标)来包含或排除该值。例如:

`

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 延迟:

`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 中添加环境条件:

`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 也非常适合组合多个字段:

`

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 毫秒的服务:

`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 的延迟很高。但它们无法告诉我们哪个团队负责该服务,也无法告诉我们该服务需要达到什么延迟目标。这些数据存储在一个小型的服务目录查找索引中。

创建用于服务目录数据的查找索引

`

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![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

一个目录文档可以为服务关联 负责人 信息和 SLO 目标:

`

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![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

运行 LOOKUP JOIN 查询

现在,Discover 可以使用 ES|QL 查询,通过 LOOKUP JOIN 将指标文档与该目录元数据进行连接。请记住,该命令需要 Elasticsearch 9.1 或更高版本,查找索引必须使用 index.mode: lookup 创建,并且连接字段(这里是 service.name)必须在查找索引中映射为 keyword

`

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 模式当搜索需要正则表达式时提供正则表达式语法
丰富或重新组织结果ESQL 模式

对于实际调查,从仍然包含所需数据的最小数据视图开始。为稳定的范围条件添加过滤条件标签。使用 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