从五个仪表板到一个提示词:Elastic Agent Builder 的红/黄/绿 APM 判断结果
作者:来自 Elastic Naga Putta 及 Stephen Brown

五个 ES|QL 工具通过评估延迟、错误、吞吐量和依赖关系来定位根本原因,因此在发生 APM 事件时,你无需在多个仪表板之间来回切换。
询问 Elastic 新推出的 APM 服务健康监控器,你的服务是否健康。它会针对现有的 traces-* 数据分发执行五个 ES|QL 查询,并在一次响应中给出红色、黄色或绿色状态,同时附带根本原因,无需切换仪表板,也无需手动进行任何关联分析。它运行在 Elastic Agent Builder 上,已在 Elasticsearch 和 Kibana 9.3 中完成测试,并且一次部署即可覆盖你整个服务集群中的所有服务,无需针对每个服务进行单独配置。下面介绍它的构建方式。

我的服务健康吗?一个问题,一个 agent,一个答案
在一次故障事件中,每位工程师都害怕听到这样一个问题:“服务健康吗?”
听起来很简单。但实际上并非如此。要正确回答这个问题,需要在仪表板之间切换,执行多个查询,将延迟峰值与错误日志进行关联,并检查下游依赖是否正在导致问题,而这一切通常都需要在压力之下完成,甚至是在不方便的时间进行。
如果整个调查过程能够简化为一次对话,会怎样?
这正是我们希望构建的东西:一个像坐在你身边的资深 SRE 一样工作的 AI agent。它知道应该提出哪些问题,知道如何查询你的 APM 数据,并返回清晰的红色、黄色或绿色健康判断,同时提供上下文信息和建议。我们称它为 APM 服务健康监控器( APM Service Health Monitor ),它完全运行在 Elastic 之上。
为什么 APM 健康状态是一个派生信号,而不是单一指标
关于 APM 数据,有一点很重要:你已经拥有了所需的一切。延迟百分位数、错误率、吞吐量以及 span 级别的依赖追踪,都已经存在于你的 traces-* 索引中,并且已经完成索引,可以直接使用。
缺少的并不是数据,而是能够将这些信号连接起来形成完整判断的推理层。
单独来看,890 ms 的 p95 延迟几乎没有太大意义。但是,如果 890 ms 的 p95 延迟比 24 小时基线高出 38%,同时你的 postgres-primary 依赖存在 6% 的错误率,那么这就是一个完整的信息。这就是红色状态,它能够直接告诉工程师应该从哪里开始排查。
APM 服务健康监控器将这种推理能力(阈值逻辑、趋势比较以及依赖影响范围分析)编码到一个 Elastic AI agent 中,并能够按需运行,为任何服务、任何时间提供健康分析。
为什么 APM 健康状态是一个派生信号,而不是单一指标
关于 APM 数据,有一点很重要:你已经拥有了所需的一切。延迟百分位数、错误率、吞吐量以及 span 级别的依赖追踪,都已经存在于你的 traces-* 索引中,并且已经完成索引,可以直接使用。
缺少的并不是数据,而是能够将这些信号连接起来形成完整判断的推理层。
单独来看,890 ms 的 p95 延迟几乎没有太大意义。但是,如果 890 ms 的 p95 延迟比 24 小时基线高出 38%,同时你的 postgres-primary 依赖存在 6% 的错误率,那么这就是一个完整的信息。这就是红色状态,它能够告诉工程师应该从哪里开始排查。
APM 服务健康监控器将这种推理能力(阈值逻辑、趋势比较以及依赖影响范围分析)编码到一个 Elastic AI agent 中,并能够按需运行,为任何服务、任何时间提供分析。
APM 服务健康监控器架构如何工作?
该 agent 在 Elastic Agent Builder 中注册为一个聊天类型 agent,并连接到五个基于 ES|QL 的工具。每个工具都专注于完成一项明确的任务。该 agent 负责协调、比较,并基于这五个工具的结果进行推理。
POST kbn:/api/agent_builder/agents
{
"id": "apm_service_health_agent",
"type": "chat",
"name": "APM Service Health Monitor",
...
}
APM 服务健康监控器位于中心位置,向外分发到五个查询 traces-* 的 ES|QL 工具。
下面介绍工具层的组成方式。
工具 1:apm_metrics_overview_tool,24 小时基线
每次健康评估都从基线开始。该工具通过一个 ES|QL 查询,计算某个服务过去 24 小时内的整体情况(平均延迟、p95 和 p99 延迟、错误率以及吞吐量):
FROM traces-*
| WHERE service.name == ?service
| WHERE transaction.type == "request"
| WHERE @timestamp >= NOW() - 24 hours
| EVAL is_error = CASE(event.outcome == "failure", 1, 0)
| STATS
avg_latency_ms = AVG(transaction.duration.us / 1000),
p95_latency_ms = PERCENTILE(transaction.duration.us / 1000, 95),
p99_latency_ms = PERCENTILE(transaction.duration.us / 1000, 99),
error_rate = 100.0 * SUM(is_error) / COUNT(*),
throughput_rps = COUNT(*) / (24*3600)
这个快照成为基准点。后续每个趋势工具都会将最新读数与这些数值进行比较,因此 agent 始终拥有一个参考点,而不仅仅是一个原始数值。
工具 2:apm_latency_trend_tool,随时间变化的性能表现
平均值会隐藏关键变化点。延迟趋势工具会在过去 24 小时内,以 5 分钟为间隔对 p95、p75 和平均延迟进行分桶,为 agent 提供一个性能变化的时间序列视图:
| STATS
avg_latency_ms = AVG(transaction.duration.us / 1000),
p95_latency_ms = PERCENTILE(transaction.duration.us / 1000, 95),
p75_latency_ms = PERCENTILE(transaction.duration.us / 1000, 75)
BY time_bucket = DATE_TRUNC(5 minutes, @timestamp)
| SORT time_bucket ASC
Agent 会获取最近 5 分钟数据桶中的 p95_latency_ms,并将其与 apm_metrics_overview_tool 中的 p95_latency_ms(24 小时滚动平均值)进行比较。这个百分比差异就是用于计算绿色、黄色或红色状态的评分依据。
工具 3:apm_error_trend_tool,故障形态检测
错误率具有方向性。从 0.5% 缓慢上升到 1.2%,与突然升高到 8% 所代表的问题完全不同。错误趋势工具通过 5 分钟数据桶捕获这种变化形态:
| EVAL is_error = CASE(event.outcome == "failure", 1, 0)
| STATS
total_requests = COUNT(*),
error_count = SUM(is_error),
error_rate = 100.0 * SUM(is_error) / COUNT(*)
BY time_bucket = DATE_TRUNC(5 minutes, @timestamp)
Agent 会读取该趋势中最新数据桶的 error_rate,并根据固定阈值直接进行评分(低于 1% 为绿色,1% 到 5% 为黄色,高于 5% 为红色)。
工具 4:apm_throughput_trend_tool,作为健康信号的流量指标
吞吐量作为健康指标经常被低估。每秒请求量下降 40% 本身就是一次事件。它可能意味着部署回归、负载均衡器配置错误,或者上游服务发生了无声故障。
| STATS requests_count = COUNT(*)
BY time_bucket = DATE_TRUNC(5 minutes, @timestamp)
| SORT time_bucket ASC
Agent 会将每个 5 分钟数据桶中的请求数量标准化为每秒请求速率,并与 apm_metrics_overview_tool 中的 throughput_rps 进行比较。相同的 10% 和 30% 偏差阈值仍然适用。一个异常安静的服务,与一个正在发生严重故障的服务一样,都会被快速标记出来。
工具 5:apm_dependency_health_tool,影响范围视图
apm_dependency_health_tool 往往能够发现其他工具无法直接暴露的问题。一个服务自身看起来可能很健康,但下游数据库或外部 API 可能正在悄悄累积失败。该工具通过 span.destination.service.resource 映射每个依赖关系,并根据 span 数据计算其错误率:
FROM traces-*
| WHERE processor.event == "span"
AND span.destination.service.resource IS NOT NULL
| EVAL is_error = CASE(event.outcome == "failure", 1, 0)
| STATS
total_calls = COUNT(*),
failed_calls = SUM(is_error),
error_rate = 100.0 * SUM(is_error) / COUNT(*)
BY dependency_name = span.destination.service.resource
| SORT error_rate DESC
与其他四个工具不同,依赖健康状态会独立进行评分。每个依赖的 error_rate 会直接与固定阈值进行比较(低于或等于 1% 为绿色,高于 1% 为黄色,高于 5% 为红色),无需进行基线比较。
健康评分如何工作
当五个工具全部返回数据后,agent 会在一次推理步骤中为每个指标计算健康状态。没有轮询循环,也没有中间存储。下面是具体的比较方式:
| **指标 | 提供数值的工具 | 比较对象 | 评分方式** |
|---|---|---|---|
| 延迟(p95) | apm_latency_trend_tool | apm_metrics_overview_tool 提供的 24 小时 p95 | < 10% 绿色 · 10–30% 黄色 · > 30% 红色 |
| 错误率 | apm_error_trend_tool | 固定阈值 + 概览中的 24 小时 error_rate | < 1% 绿色 · 1–5% 黄色 · > 5% 红色 |
| 吞吐量 | apm_throughput_trend_tool | apm_metrics_overview_tool 提供的 24 小时 throughput_rps | < 10% 绿色 · 10–30% 黄色 · > 30% 红色 |
| 每个依赖 | apm_dependency_health_tool | 仅固定阈值(无基线) | 全部 ≤1% 绿色 · 任意 >1% 黄色 · 任意 >5% 红色 |
整体判断遵循一个简单规则:最差的单个指标决定最终结果。
任意指标为红色 → 总体状态 = 🔴 红色
任意指标为黄色(没有红色) → 总体状态 = 🟡 黄色
所有指标均为绿色 → 总体状态 = 🟢 绿色
红/黄/绿色评分逻辑存放在 agent 的自然语言指令中。它易于阅读、审计和调整,无需修改代码,也无需重新部署基础设施。
在 Agent Builder 中部署 APM 服务健康监控器
注册流程遵循 Elastic 标准的 Agent Builder API 模式,已在 Elasticsearch 9.3 和 Kibana 9.3 中完成测试。首先注册这些工具,然后将 agent 连接到全部五个工具 ID:
# Step 1: Register the five ES|QL tools
POST kbn:/api/agent_builder/tools # apm_metrics_overview_tool
POST kbn:/api/agent_builder/tools # apm_latency_trend_tool
POST kbn:/api/agent_builder/tools # apm_error_trend_tool
POST kbn:/api/agent_builder/tools # apm_throughput_trend_tool
POST kbn:/api/agent_builder/tools # apm_dependency_health_tool
# Step 2: Register the agent with tools wired in
POST kbn:/api/agent_builder/agents # apm_service_health_agent
# Step 3: Verify the agent is live
GET kbn:/api/agent_builder/agents/apm_service_health_agent
每个工具都通过服务绑定进行参数化,因此同一个 agent 可以服务你整个服务集群中的所有服务,无需针对每个服务进行单独配置。这些查询目标为 traces-*,并支持跨集群通配符,因此一次部署即可开箱即用地覆盖多集群环境。
试试看:向 agent 询问你的服务状态
部署完成后,在 Kibana 中打开该 agent,并输入:
过去 24 小时内我的 checkout-service 的健康状态如何?
Agent 会向所有五个工具分发请求,计算各项指标状态,一次性应用健康判断逻辑,并返回一份结构化报告。
Agent 无需任何手动关联分析,就识别出了根本原因:postgres-primary 的调用失败率达到 6.1%,并且这一问题正在直接导致 p95 延迟峰值。无需切换仪表板,无需手动编写 ES|QL。一个提示词,即可获得完整的态势感知。
你可以在同一个会话中继续提出后续问题:
-
哪些其他服务依赖 postgres-primary?
-
这与昨天的健康状态相比如何?
-
只显示过去 6 小时的错误趋势。
Agent 会针对每个后续问题调用相应的工具,同时保留原始健康评估的完整上下文。
为什么 Agent Builder 和 ES|QL 是实现这一方案的正确技术栈
一些经过深思熟虑的设计选择,让这个方案能够简洁地运行。
ES|QL 作为查询层
ES|QL 基于管道的语法使每个工具查询都易于阅读、测试和独立验证。用于趋势分析的 DATE_TRUNC 分桶、用于延迟分析的 PERCENTILE 聚合,以及用于依赖关系分析的 span.destination.service.resource 分组,都是精确且可审计的查询。你可以直接在 Kibana Dev Tools 中运行任意查询,并查看 agent 所看到的完整结果。
窄范围、无状态工具
每个工具只负责完成一件事情,并返回结构化数据。agent 负责编排和推理。添加新的指标维度只需要注册一个新的工具,并更新 agent 指令即可。其他内容无需改变。
将指令作为运行手册
agent 的健康判断逻辑通过自然语言表达,并存放在其配置中。团队中的任何人都可以阅读这些逻辑,无需代码部署即可进行调整,并且可以通过 Kibana 中的 Agent Builder 界面完整审计这些逻辑。
APM 服务健康监控器的下一步发展方向
APM 服务健康监控器是一个基础能力,而不是终点。自然的扩展方向包括:
-
由告警触发的健康检查:将 agent 连接到异常检测规则,使其能够在规则触发时自动运行,并将健康摘要直接附加到告警通知中。
-
部署关联分析:集成变更事件数据,使 agent 能够判断红色状态是否在某次特定部署之后开始出现。
-
基于 SLO 的阈值:使用每个服务的错误预算消耗替代固定百分比阈值,使红色、黄色和绿色状态能够根据定义好的 SLO 反映真实业务影响。
-
跨服务遍历:扩展依赖工具,使其能够递归评估上游和下游服务,通过一次查询构建完整的拓扑视图。
要求和部署
要求:
-
Elasticsearch 9.3 和 Kibana 9.3(测试版本)。
-
在 Kibana 中启用 Agent Builder。
-
通过任意 Elastic APM agent 将 APM 数据写入
traces-*索引。 -
使用 Agent Builder 和 ES|QL 跨集群搜索( ES|QL cross-cluster search)需要 Elastic Enterprise 许可证。
完整的 agent 和工具定义可以在[此代码仓库]中找到。一旦你的 traces 完成索引,全部五个 ES|QL 工具无需修改即可作用于你的数据,在查询时通过服务名称进行参数化,并通过一次部署覆盖整个服务集群。
下一次有人问“服务健康吗?”时,你将在事件频道中的问题结束回响之前,获得一个精确、有数据支持的答案。
有问题、扩展想法或反馈?欢迎加入 Elastic 社区论坛 讨论。
完整部署参考
以下是部署 APM 服务健康监控器所需的全部内容,按照执行顺序排列。先运行五个工具注册,然后运行 agent。
工具 1:依赖健康状态
POST kbn:/api/agent_builder/tools
{
"id": "apm_dependency_health_tool",
"type": "esql",
"description": "评估外部依赖(数据库、API、缓存等)的健康状态...",
"configuration": {
"query": "FROM traces-*\n| WHERE service.name == ?service\n| WHERE processor.event == \"span\"\n AND span.destination.service.resource IS NOT NULL\n| WHERE @timestamp >= NOW() - 24 hours\n| EVAL is_error = CASE(event.outcome == \"failure\", 1, 0)\n| STATS\n total_calls = COUNT(*),\n failed_calls = SUM(is_error),\n error_rate = 100.0 * SUM(is_error)/COUNT(*)\n BY dependency_name = span.destination.service.resource\n| SORT error_rate DESC | LIMIT 100"
}
}
工具 2:错误趋势
POST kbn:/api/agent_builder/tools
{
"id": "apm_error_trend_tool",
"type": "esql",
"description": "跟踪服务过去 24 小时内按 5 分钟分桶的错误率...",
"configuration": {
"query": "FROM traces-*\n| WHERE service.name == ?service\n| WHERE transaction.type == \"request\"\n| WHERE @timestamp >= NOW() - 24 hours\n| EVAL is_error = CASE(event.outcome == \"failure\", 1, 0)\n| STATS\n total_requests = COUNT(*),\n error_count = SUM(is_error),\n error_rate = 100.0 * SUM(is_error)/COUNT(*)\n BY time_bucket = DATE_TRUNC(5 minutes, @timestamp)\n| SORT time_bucket ASC | LIMIT 1000"
}
}
工具 3:延迟趋势
POST kbn:/api/agent_builder/tools
{
"id": "apm_latency_trend_tool",
"type": "esql",
"description": "提供过去 24 小时按 5 分钟分桶的延迟趋势(平均值、p95、p75)...",
"configuration": {
"query": "FROM traces-*\n| WHERE service.name == ?service\n| WHERE transaction.type == \"request\"\n| WHERE @timestamp >= NOW() - 24 hours\n| STATS\n avg_latency_ms = AVG(transaction.duration.us / 1000),\n p95_latency_ms = PERCENTILE(transaction.duration.us / 1000, 95),\n p75_latency_ms = PERCENTILE(transaction.duration.us / 1000, 75)\n BY time_bucket = DATE_TRUNC(5 minutes, @timestamp)\n| SORT time_bucket ASC | LIMIT 1000"
}
}
工具 4:指标概览
POST kbn:/api/agent_builder/tools
{
"id": "apm_metrics_overview_tool",
"type": "esql",
"description": "聚合过去 24 小时的关键服务指标:平均延迟、p95/p99、错误率、吞吐量...",
"configuration": {
"query": "FROM traces-*\n| WHERE service.name == ?service\n| WHERE transaction.type == \"request\"\n| WHERE @timestamp >= NOW() - 24 hours\n| EVAL is_error = CASE(event.outcome == \"failure\", 1, 0)\n| STATS\n avg_latency_ms = AVG(transaction.duration.us / 1000),\n p95_latency_ms = PERCENTILE(transaction.duration.us / 1000, 95),\n p99_latency_ms = PERCENTILE(transaction.duration.us / 1000, 99),\n error_rate = 100.0 * SUM(is_error) / COUNT(*),\n throughput_rps = COUNT(*) / (24*3600)"
}
}
工具 5:吞吐量趋势
POST kbn:/api/agent_builder/tools
{
"id": "apm_throughput_trend_tool",
"type": "esql",
"description": "提供过去 24 小时按 5 分钟间隔的服务吞吐量趋势...",
"configuration": {
"query": "FROM traces-*\n| WHERE service.name == ?service\n| WHERE transaction.type == \"request\"\n| WHERE @timestamp >= NOW() - 24 hours\n| STATS requests_count = COUNT(*)\n BY time_bucket = DATE_TRUNC(5 minutes, @timestamp)\n| SORT time_bucket ASC | LIMIT 1000"
}
}
Agent:APM 服务健康监控器
POST kbn:/api/agent_builder/agents
{
"id": "apm_service_health_agent",
"type": "chat",
"name": "APM 服务健康监控器",
"description": "提供过去 24 小时服务的红/黄/绿色健康状态和趋势。",
"labels": ["apm", "health", "service", "monitoring"],
"avatar_color": "#4CAF50",
"configuration": {
"instructions": "你是服务健康 Agent...",
"tools": [{
"tool_ids": [
"apm_dependency_health_tool",
"apm_error_trend_tool",
"apm_latency_trend_tool",
"apm_metrics_overview_tool",
"apm_throughput_trend_tool"
]
}]
}
}
更多推荐




所有评论(0)