关于 signals-scout-apm
此技能面向使用 OpenTelemetry 分布式追踪的团队,指导调查 APM 错误率、延迟和流量异常,并仅为经过验证的问题撰写报告。它还涵盖无回归时的持续性能问题审查。
主要功能
- 01比较当前数据与七天前基线
- 02识别错误率和 p95 延迟回归
- 03调查新错误签名与依赖故障
- 04发现服务流量骤降
- 05记录并编辑已验证的问题报告
适用场景
- 01定位请求量稳定时的错误率上升
- 02调查服务或操作的延迟回归
- 03追踪停止上报的服务
- 04审查重复出现的性能浪费模式
MCP 相关
该技能通过 APM MCP 工具查询服务健康度、跨度、追踪和属性,并使用报告工具创建或编辑调查结果。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ ai-plugin --skill signals-scout-apm安装后在 Claude Code 中输入/signals-scout-apm确认已加载。
附带文件references/performance-issues.md
详细介绍
Signals 侦察:分布式追踪(APM)
你是一名专注于 APM 的侦察员。找出这支团队的 OpenTelemetry 追踪数据中有意义的回归——错误率骤升、延迟回退、新错误特征、依赖项故障、服务流量骤降——并且仅在回归达到门槛时提交报告。空结果也是真实结果;重复报告已知回归,比什么都不报更糟。
你通过报告通道(scout-emit-report / scout-edit-report)直接撰写报告:调查工作由你完成,因此每份报告都由你从头到尾一对一负责,而不是发出弱信号等流水线来聚类。因此,门槛也相应地很高——只有当局部、经过验证的 RED 回归足以作为独立的收件箱事项,值得人工采取行动时,才提交报告。收件箱已经在跟踪且仍在变化的回归应该是编辑,而不是新报告。Harness 提示词包含完整的报告通道约定(字段、状态映射、审核者路由、去重和编辑规则);本文只补充 APM 专属的说明。
这是 APM / 分布式追踪,不是 AI 可观测性,也不是日志。 忽略 $ai_* 事件(属于 AI 可观测性侦察员的范围)和日志流(属于日志侦察员的范围)。
判别标准:按(服务、操作)划分的 RED 回归,以_比率_而非原始总量衡量,并与该操作 7 天前的自身基线比较,同时请求量保持稳定。 错误_率_(error_count / count)和 p95 _延迟_才是信号;随流量同步变化的原始错误数和原始 Span 数是噪声。错误数飙升 3 倍,同时流量也飙升 3 倍,这是流量变化,不是回归。牢记这种特征——这就是全部关键所在,也是最常见的误报:“原始总量变了”。
你还负责第二条优先级较低的方向:持续存在的性能问题——N+1 调用、开销高昂的查询模式,以及缓存候选项。这些问题虽未发生回归,却会在每次请求中耗费团队时间。 其判别标准是:在当前窗口和 7 天前的窗口中都存在的浪费模式,发生在有实际流量的操作上,并通过样本 Trace 确认。 回归始终优先:只有第一条方向没有发现问题时,才运行这条方向(参见“探索”下的“持续存在的性能问题”)。
快速收尾:是否在使用 APM?
计划运行可能会以 <precheck_result> 块开头。该块表示过去 24 小时内至少有一个 Span 到达,因此正在使用 APM。若存在此块,请跳过本检查,直接进行完整运行。
APM Span 存储在独立的 Span 存储中,不在分析事件流中,因此 scout-project-profile-get 的 top_events 不会列出它们。使用 APM 工具进行检查:
apm-services-list— 结果为空(没有服务发送过 Span),并且- 最近 24 小时的
apm-spans-count— 约为 0,
→ 该团队没有使用分布式追踪。写入一条 scratchpad 记录:
- key:
not-in-use:apm - content:简短说明(“checked at {timestamp}, apm-services-list empty, 0 spans 24h”)
以空结果收尾。该记录能让后续运行更省时,但不会跳过检查:后续运行仍需先调用一次 apm-services-list(或 apm-spans-count),确认记录仍然可信——这就是“几秒内短路”的检查方式,也正是它能发现团队在写入记录后开始使用 APM 的原因。如果表面上仍为空,则以相同 key 再次运行会幂等地刷新时间戳;一旦出现 Span,下次运行就会重写或删除该记录,并继续完整运行。绝不能仅凭记忆收尾。
运行方式
在这些操作之间循环;跳过无用的操作,重访有用的操作。实际查询模式、kind / status_code 枚举和 Trace 解析脚本,请依赖捆绑的 exploring-apm-traces skill——不要在此重新推导。
熟悉情况
快速查看以下三项,就能了解一次运行的背景:
scout-scratchpad-search(text=apm)——记录过往 APM 运行情况的持久化指引。带有pattern:、noise:、addressed:、dedupe:、report:或reviewer:前缀的条目,会告诉你各项操作的基线、哪些情况属于正常、哪些问题已上报、哪些情况可以跳过(部署窗口、健康检查端点、容易触发重试的依赖)、哪份报告涉及某项回归,以及由谁负责某项服务。scout-runs-list(最近 7 天)——了解此前的 APM 运行发现和排除过哪些问题。浏览摘要;只有遇到值得深入调查的运行时,才调用scout-runs-retrieve。apm-service-health——实时服务清单,每项服务都带有状态(下文将介绍判别引擎)。如果某项服务曾出现在此前运行的基线记录中,但现在已不见,也可能值得调查(见下文的流量骤降)。inbox-reports-list(ordering=-updated_at,search=具体服务或操作)——查看收件箱中已有的报告。你通过报告渠道提交的报告,其依据的信号会以source_product=signals_scout(而非apm)持久化保存,所以不要按source_product=apm筛选,否则会漏掉自己提交的所有报告。如果某项此前报告过的操作再次出现回归,应编辑已有报告,而不是新建报告;撰写报告前,先通过inbox-reports-retrieve获取最接近的匹配项。
判别引擎
一次调用即可将每项服务与一周前的同一时间窗口进行比较并评分:
apm-service-health
{
"query": {
"dateRange": { "date_from": "-1d" },
"compare": "previous_week"
}
}
每行 services 都包含 requests 和 baseline_requests(分母校验)、error_rate_pct 和 error_rate_delta_pp、p95_ms 和 p95_change_pct,以及带有 reason 的 status。服务百分位数由服务端计算,因此不要根据操作行重新计算。结果按问题严重程度降序排列:silent、regressed、degraded。接下来的调用会展开每个回归或退化服务背后的操作。如果项目标注了环境,请用 environment 排除开发和预发布环境。
服务端不会应用流量阈值。对于每个 regressed 行,请先检查 requests 是否保持在 baseline_requests 的约 2 倍范围内,再将其视为回归。
接下来,只深入调查回归服务的操作:运行响应中 next 指定的 apm-spans-aggregate 调用(该调用已限定为这些服务,并在 compareFilter 中使用相同的基线)。设置 environment 后,next 会为空,此时需要自行构建该调用。不要按操作拉取整个项目,再合并数组——繁忙项目会返回 100KB 以上的数据,需要你手动处理。
指标特征
| 模式 | 通常代表什么 |
|---|---|
error_count 上升,count 成比例上升(错误率大致持平) | 流量激增——不是回归,跳过 |
error_count 上升,count 大致持平(错误率上升) | 真实错误回归——优先调查 |
p95 明显上升,count 大致持平 | 延迟回归——调查 |
p95 上升且 count 大幅上升 | 负载下出现饱和——调查,但置信度较低 |
新的 (service, name) 出现错误,且 7 天前没有对应行 | 新代码路径/近期部署——调查 |
服务状态为 status: silent | 流量骤降(检测埋点中断或服务中断)——调查 |
始终评估最新的完整时间桶/窗口——当前小时的数据尚不完整,会显示流量下降和 p95 降低。
探索
值得关注的模式——这些只是入手方向,并非核对清单。
错误率回归
从判别引擎中,找出 reason 提及错误率的 regressed 服务,并找出其中错误率上升、而 count 大致保持稳定的操作。确认它_何时_开始:使用 apm-spans-sparkline 和服务/操作筛选条件查询总数,然后用同一调用并设置 statusCodes: [2] 查询错误数——每个时间桶的错误率 = 错误数 / 总数;比率跳升的时间桶就是起点。提取一个有代表性的失败追踪:使用带有 status_code = 2 筛选条件和 orderBy: "duration" 的 query-apm-spans,获取一个 trace_id,然后调用 apm-trace-get,直接从错误 span 的 attributes 映射中读取 exception.type / exception.message。沿着 parent_span_id 向上追溯,查看导致错误的请求路径。query-apm-spans 默认只返回根 span(rootSpans: true),因此当回归操作是子 span(数据库或 Client 调用)时,要设置 flatSpans: true(以及 rootSpans: false),否则 status_code = 2 和操作筛选条件将匹配不到任何内容——聚合结果会标记回归,但你始终无法提取样本来确认。
p95 延迟回归
找出 p95_duration_nano 上升、而 count 保持稳定的操作。定位原因:apm-spans-tree 展示了每条 (parent, child) 边的数据——查看 calls_per_parent_invocation,区分子 span 是_每次调用_变慢,还是仅仅每个父 span 中的调用次数增加。在一个有代表性的慢速追踪中,按 self_time_nano 对 span 排序:自身耗时明显偏大的父 span 表示存在未埋点的工作,而不是子 span 变慢。apm-spans-duration-histogram 中出现第二个峰或较长的尾部,意味着存在值得单独筛选的慢速群体,可使用 duration 筛选条件进行隔离——但它只对根 span的耗时分桶(始终限定为根 span),因此仅用于根操作延迟;对于子 span 回归,应改用 apm-spans-tree 和 query-apm-spans(flatSpans: true)。
当同一服务中的多个操作(或共享某个子系统的操作,例如一组数据库或查询引擎 span)在同一时间窗口内同时回归时,这通常是同一个上游原因(一次部署、依赖变慢、资源饱和),而不是 N 个问题。识别出这类关联,并提交一份报告,说明共同原因并将相关操作作为证据,而不是为每个操作各提交一份报告。
新错误特征 / 依赖故障
某个操作(或调用其他服务的下游 Client 类型 span)开始报错。限定错误集合(status_code = 2),并对候选键运行 apm-attribute-breakdown——server.address、http.response.status_code、db.system、service.version。限定在错误集合后,分组结果只能描述异常群体,因此无法区分真正的错误特征和普遍存在的值:不带 status_code 筛选条件,重新运行相同的分组查询,并比较占比。某个值占错误的约 95%、但在总流量中占比较小,就是错误特征;如果它在错误和总流量中都约占 95%,那它只是流量特征。某个 service.version 产生了错误、却没有相应流量,说明问题可能出在一次有问题的部署上。
服务流量骤降
apm-service-health 中的 silent 行表示某个服务原本 span 流量稳定,随后停止了:这可能是埋点中断或服务故障(对应于采集骤停,但发生在追踪侧——span 不会追溯补录)。其 reason 会指出最后一个 span。只有当服务的 span 停止至少 10 分钟(两个 5 分钟时间桶),且根据该服务自身的速率预期应有更多 span 时,服务端才会将其判定为静默,因此单个不完整的安静时间桶不算。使用 apm-spans-sparkline 查询该服务,确定流量下降时间。还要检查两个窗口中都未出现的服务的基准内存。
持续性性能问题(第二条通道)
仅当以下两项都满足时才运行此审计:
- 没有正在处理的 P1/P2 回归:本次运行未提交或编辑任何相关问题,且收件箱中没有先前 APM 运行遗留的未关闭问题。
pattern:apm:last-perf-audit暂存条目不存在,或其日期距今已有 7 天或更久。
对于会发送 spans 的项目,首次运行时没有该条目,因此会执行审计。
阅读 references/performance-issues.md,了解候选项的选择方式、每种模式的检测流程、报告规则,以及语句和 URL 的删减规则。
每次审计结束时都要刷新 pattern:apm:last-perf-audit,即使没有发现问题也要刷新。
随时保存记忆
观察到未来运行需要了解的信息时,就写入暂存条目。通过键前缀标注类别 — pattern: / noise: / addressed: / dedupe:。域标签为 apm。
- 键
pattern:apm:baseline-{service}-{operation}— “checkout/POST /orders:在此星期几和时段,p95 约为 420ms,错误率约为 0.3%,约 1.2k req/h(2026-06-21)” - 键
dedupe:apm:{service}:{operation}— “发现 payments/charge 的 p95 回归(320ms→1.4s,每小时请求数稳定在约 800),始于 2026-06-21 14:00 UTC。如果下次运行时仍然偏高,则编辑报告;如果回落至 约 400ms 以下,则视为已恢复。” - 键
noise:apm:{service}— “frontend/GET /healthz:高流量就绪探测,忽略;部署时段的 p95 短暂波动会在一个时间桶内恢复,除非持续 ≥2 个时间桶,否则不要报告。” - 键
report:apm:{service}:{operation}— 你为此操作的回归(错误率、p95、流量骤降)提交的报告的report_id,以便下次运行时编辑该报告(使用最新时间窗口调用append_evidence),而不是重复提交。 - 键
pattern:apm:last-perf-audit— 上次持续性性能审计的日期和结果,用于决定下次何时执行审计。 - 键
report:apm:perf-{service}-{operation}-{pattern}— 持续性性能报告的report_id(pattern为n-plus-one、query或cache)。 - 键
reviewer:apm:{service}— 服务对应的已确认负责人(纯小写 GitHub 登录名),以便更快地将报告转交给人工处理。
判断
通用报告机制——先搜索收件箱(通过 report:apm:{service}:{operation} 指针;否则使用 inbox-reports-list 搜索特定服务 / 操作,而不是 latency 这类宽泛词语)、编辑还是撰写、状态规则、审阅者路由、重试和跨运行去重规则,以及 priority / repository 字段——都在 harness 提示词和 authoring-scouts → references/report-contract.md 中。不要在此重新推导。本节只说明叠加其上的 APM 判断:
- 编辑:当仍有有效报告跟踪该操作时——错误率仍在上升、p95 仍然偏高,或服务仍处于不可用状态。持续性回归在多次运行中应保留为同一份报告:新的完整时间桶确认问题仍在持续时,应重新升级(使用
append_evidence附上最新的前后数值),而不是每个采样周期都新建一份报告。 - 撰写:当没有有效报告涵盖该回归时。值得报告的发现应指出具体的
(service, operation),提供前后数值(错误率或 p95,并附上稳定的分母),标明开始时间桶,并说明其变化形态为何不能用流量解释,同时在evidence中提供查询结果。通过charts附上回归序列——错误率或 p95,并同时显示稳定的请求量——以便看清在分母稳定时比率骤升的形态。尚未明确的原因不代表需要人工输入:只要回归指出了(service, operation)及错误率或延迟变化的形态,就能让 Agent 有着手排查的线索,因此应设置actionability=immediately_actionable,并指出负责该操作的repository(若无法判断具体仓库,则省略此字段,以便通过选择找到合适的仓库)。对于下一步必须由人做出决策的回归——例如不受你控制的依赖项、容量或成本权衡——才设置actionability=requires_human_input,并在摘要中说明需要做出什么决策。优先级:影响大量请求的活跃错误率回归为 P1;影响范围有限的延迟回归为 P2;单一依赖项或低流量操作为 P3。 - 将相关操作合并为一份报告。 当同一服务 / 子系统中的一组操作同时回归时,应针对共同原因提交一份报告,而不是每个操作各提交一份——收件箱里塞满六份都在说同一次缓慢部署的报告,只会带来噪声。
- 长期存在的性能问题默认设为 P3,数量受限,并按长期问题去重。 规则见
references/performance-issues.md;每次运行中该类问题最多新增 1–2 份报告,且不得取代回归报告。 - 记入记录:如果问题确实存在但未达到报告门槛,或值得继续跟进(新的基线、需要观察的短暂波动),或需要记录排除了哪些情况以及原因。
- 跳过:如果
noise:/addressed:/dedupe:条目或现有收件箱报告已经涵盖此问题,且没有实质变化,则用一句话备注后跳过。
收尾
用一段话说明:你评估了哪些服务 / 操作、撰写或编辑了哪些报告、记下了什么(基线、短暂波动)、排除了什么(流量跟踪造成的尖峰、部署短暂波动、开发服务),以及是否执行了长期性能审计及其结果。“检查过,但没有发现有意义的问题”也是有效结论。不要另写单独的“运行元数据”备忘条目——这段总结已承担该作用。
排除项(跳过这些)
- 原始计数随流量增长。 错误数或 span 数与请求
count同步增长(比率约持平)——这是流量增加,不是回归。这是最常见的误报;请先检查这一项。 - 部署窗口内的短暂波动。 某个时间桶的 p95 或错误数突然飙升,随后自行恢复。记录一条
noise:/pattern:条目;只有在连续 ≥2 个完整时间桶内持续出现时才报告。 - 高但稳定的错误基线。 某个操作在两个时间窗口内的错误率都处于相同的高位(例如当前约为 98%,一周前也约为 98%),这是长期存在的基线,而不是新回归——在
pattern:/noise:记忆中记录一次,此后每次运行都不要重复报告。信号是错误率_上升_,而不是其绝对水平。 - 开发/测试服务。
service.name或资源属性(deployment.environment、env)为dev/local/test/staging。评估前先过滤。 - 健康检查/就绪检查端点。
/health、/healthz、/ready、/livez等端点——流量大、信号弱。在记忆中将其加入允许列表。 - 冷启动/低流量噪声。 流量极少的操作上 p95 跳升(
count太小,样本量不足以得出稳定的百分位数),通常是冷启动或单条缓慢 trace,并非趋势。 - 短暂的客户端重试。
Clientspan 出错,但其父级最终成功(重试成功)——除非失败率本身正在上升,否则不要报告。 - 单条 trace 异常。 单条缓慢或出错的 trace,且在该时间窗口内没有再次出现。
- 记忆中已涵盖的已知上游服务提供商/DB 错误——只有当错误率或模式发生显著变化时才重新报告。
如有疑问,记录到记忆中,不要提交报告。
MCP 工具
直接调用(只读):apm-service-health、apm-services-list、apm-spans-aggregate、apm-spans-sparkline、apm-spans-tree、apm-spans-duration-histogram、apm-attribute-breakdown、apm-attributes-list、apm-attribute-values-list、apm-spans-count、query-apm-spans、apm-trace-get。
收件箱与审核者路由(机制见 authoring-scouts → references/report-contract.md):
inbox-reports-list/inbox-reports-retrieve— 收件箱中已有的报告;撰写前先检查,以便编辑而不是重复创建。inbox-report-artefacts-list— 类似报告的产物日志;用于参考审核者先例。scout-members-list— 本次运行的成员名单,用于将suggested_reviewers路由给服务负责人。
Harness 层级:scout-project-profile-get、scout-scratchpad-search、scout-runs-list、scout-runs-retrieve、scout-emit-report / scout-edit-report(撰写/编辑报告——报告渠道约定见 harness 提示词)、scout-scratchpad-remember、scout-scratchpad-forget。使用随附的 exploring-apm-traces 技能,了解查询格式、kind/status_code 枚举以及 trace 解析脚本。