mcpField
R
root-cause-analysis

root-cause-analysis

github.com/kopai-app云与 DevOps1044 次安装1 天前更新
代码仓库

关于 root-cause-analysis

root-cause-analysis 是面向 Kopai 的技能,指导使用 OpenTelemetry 链路、日志和指标排查生产问题。它通过 TypeScript SDK 查询定位错误、关联证据、量化影响并整理可能原因。

主要功能

  1. 01使用类型安全的 TypeScript SDK 查询
  2. 02分析链路、日志和指标
  3. 03按错误率与吞吐量排序
  4. 04通过时间序列分析影响
  5. 05关联链路与日志
  6. 06说明 SQLite 查询限制

适用场景

  1. 01事件分诊时对服务排序
  2. 02沿链路追查相关日志中的错误
  3. 03衡量问题开始时间与影响范围
  4. 04调查延迟和指标变化

MCP 相关

这是使用 Kopai SDK 与 CLI 的技能,并非 MCP 服务或客户端。README 未说明 MCP 集成。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kopai-app/kopai-mono --skill root-cause-analysis

安装后在 Claude Code 中输入/root-cause-analysis确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

tile.json
references/
log-filters.md
metric-filters.md
trace-filters.md
rules/
_sections.md
pattern-distributed.md
pattern-http-errors.md
pattern-log-driven.md
pattern-slow-requests.md
workflow-check-metrics.md
workflow-correlate-logs.md
workflow-find-errors.md
workflow-get-context.md
workflow-identify-cause.md

详细介绍

使用 Kopai 进行根因分析

根据遥测数据(追踪、日志、指标)排查生产环境问题。Kopai 的分析能力——错误率、吞吐量、延迟、分组、时间序列分桶——位于 SDK 查询 API 中,CLI 并未提供这些能力。因此,每次排查都应先编写一段简短的 TypeScript 脚本;CLI 则保留为快速查询的备用方式。

前提条件

  • 服务正在向 Kopai 发送 OpenTelemetry 数据(参见 otel-instrumentation 技能)。
  • 项目中已安装 @kopai/sdk:npm i @kopai/sdk(其中包含查询 API 和 .kopairc 读取器)。

代码模式(推荐)

连接 — clientFromConfig() 的读取 .kopairc 的方式与 CLI 完全一致:

import { clientFromConfig } from "@kopai/sdk/node";
// Reads ./.kopairc then ~/.kopairc; defaults to http://localhost:8000.
// Override any field: clientFromConfig({ url, token, configPath, timeout }).
const client = clientFromConfig();

运行 — npx tsx rca.mts。使用 .mts 扩展名:它始终是 ES 模块,因此顶层 await 无需依赖宿主项目的 package.json "type" 即可正常工作。 (如果没有安装 tsx:node --experimental-strip-types rca.mts。)

使用 kq 构建查询,并通过 client.query(q) 运行。 client.query(q) 是运行任何已构建查询的唯一简洁方式,并且具有完整的类型定义——行数据支持自动补全,拼写错误会导致编译错误。聚合查询返回 { data };原始查询返回 { data, nextCursor }。结果行具有完整的类型定义——直接遍历 data,绝不要将其转换为 any/any[]。 聚合度量值的类型为 number(因此 row.error_rate * 100 可直接使用——无需 String(...)/类型转换),分组维度也包含在内(row["service.name"]),而 .timeSeries() 的行还会添加 bucket_start:

const { data } = await client.query(q); // typed rows — do NOT write `data as any[]`
for (const row of data) {
  console.log(
    row["service.name"],
    `${(row.error_rate * 100).toFixed(1)}%`,
    row.rps
  );
}

输出 — stdout 就是你的结果。以 console.log(JSON.stringify(data, null, 2)) 结束,并将 .build() 和查询调用包在 try/catch 中:

import { kq, KopaiQueryBuildError } from "@kopai/sdk";
try {
  const q = kq.traces
    .aggregate() /* … */
    .build();
  const { data } = await client.query(q);
  console.log(JSON.stringify(data, null, 2));
} catch (e) {
  if (e instanceof KopaiQueryBuildError)
    console.error(e.issues); // {path,message}[]
  else throw e;
}

后端注意事项与易踩坑点(查询前请阅读)

  • 每次查询都需要指定时间范围——.timeRelative("1h") 或 .timeAbsolute(startISO, endISO)。回溯范围/粒度必须匹配 ^[1-9]\d*[smhdw]$("30s"、"15m"、"2h"、"7d")。
  • StatusCode 的取值严格为 "Unset" | "Ok" | "Error"(首字母大写)。成功的 span 通常是 "Unset",而不是 "Ok"。此枚举会进行类型检查:像 "ERROR" 这样的错误值会导致编译错误,因此大小写问题会自动被发现。无论如何,优先使用 errorRate 度量(在服务端统计错误数量),而不是筛选原始值。
  • 请使用 service.name(带点),绝不要使用 ServiceName。 ServiceName 不是可查询列——按它筛选会静默匹配不到任何内容。(在结果行中,值会按你分组时使用的键返回,例如 row["service.name"]。)
  • 繁忙系统中出现空结果,通常意味着列名/取值有误,而非确实没有数据。 在得出“没有错误/没有数据”的结论前,请重新检查列名和取值的大小写——静默返回空结果是得出“系统一切正常”这一错误结论的最常见原因。
  • 百分位数(p50–p999)仅适用于 ClickHouse。 在 SQLite 上会在查询时失败(KopaiError: Percentile measures … not yet supported on the sqlite backend)。延迟分析请先使用 Duration 的 avg/max;将百分位数视为 ClickHouse 升级选项,并放在 try/catch 中处理。
  • Duration 筛选器接受带单位 s/m/h/d/w 的时长字符串——f.gt("Duration", "1s")、f.lte("Duration", "2h")(也支持 gte/lt)。不支持亚秒级单位;亚秒级阈值请传入纳秒数值。(结果行中的 Duration 仍以纳秒为单位——Duration 的 avg/max 也会以 ns 返回:1ms = 1e6,1s = 1e9。)
  • 指标查询会预先选择类型: kq.metrics("Gauge")…、kq.metrics("Sum")…(类型 ∈ "Gauge" | "Sum" | "Histogram" | "ExponentialHistogram" | "Summary")。构建器参数会自动固定 MetricType,因此无需手动调用 .where(f => f.eq("MetricType", …))。值列按类型确定:Gauge/Sum → "Value";Histogram/ExponentialHistogram → "Count" | "Sum" | "Min" | "Max";Summary → "Count" | "Sum"。
  • searchTraces/searchLogs/searchMetrics 是异步可迭代对象(会自动分页)——请使用 for await (const row of client.searchLogs({ … })) { … } 消费,不要将它们 await 为数组。若只需单页,请使用 searchTracesPage/searchLogsPage/searchMetricsPage → { data, nextCursor }。限制:kq 的 .limit() 上限为 10000;search* 筛选器上限为 1000。

RCA 工作流

  1. 找出故障服务 — 按错误率和吞吐量对服务排序。errorRate 会在服务端处理 StatusCode,因此无需猜测其值:

    const q = kq.traces
      .aggregate()
      .measure((m) => m.errorRate("error_rate"))
      .measure((m) => m.throughput("rps"))
      .measure((m) => m.count("spans"))
      .dimension("service.name")
      .timeRelative("1h")
      .summary()
      .orderByMeasure("error_rate", "desc")
      .build();
    const { data } = await client.query(q);
    

    如需优先从日志入手进行排查,请提取错误级别日志,即 SeverityNumber >= 17(无论文本大小写如何,都能匹配 ERROR/FATAL): client.query(kq.logs.raw().where(f => f.gte("SeverityNumber", 17)).timeRelative("1h").limit(50).build())。 请参阅 workflow-find-errors。

  2. 获取完整的 Trace 上下文 — const spans = await client.getTrace(traceId)。检查 Duration(瓶颈)、ParentSpanId(调用链)、StatusMessage、SpanKind。 请参阅 workflow-get-context。

  3. 将日志与 Trace 关联起来 — client.query(kq.logs.raw().where(f => f.eq("TraceId", traceId)).timeRelative("1h").build()) (或遍历 client.searchLogs({ traceId }))。查找最早的错误及其堆栈跟踪。 请参阅 workflow-correlate-logs。

  4. 量化影响 / 定位开始时间 — 这是 CLI 无法完成的操作。按时间对指标分桶,查看问题何时开始,以及影响范围有多大。注意数据保留期限的下限:如果最早的分桶已经升高,真实的开始时间就在该时间点或更早——应如实说明,而不要把这个下限称为“突变”:

    const q = kq.traces
      .aggregate()
      .measure((m) => m.errorRate("error_rate"))
      .measure((m) => m.avg("Duration", "avg_ns"))
      .measure((m) => m.max("Duration", "max_ns"))
      .dimension("service.name")
      .timeRelative("3h")
      .timeSeries("5m")
      .orderByMeasure("error_rate", "desc")
      .build();
    const { data } = await client.query(q);
    

    当信号是指标而非 Trace 时,请预先选择类型,让系统自动固定 MetricType——例如,按时间对 Gauge 分桶:

    const q = kq
      .metrics("Gauge")
      .aggregate()
      .measure((m) => m.avg("Value", "avg_value"))
      .where((f) => f.eq("MetricName", "process.cpu.utilization"))
      .timeRelative("3h")
      .timeSeries("5m")
      .build();
    const { data } = await client.query(q);
    

    请参阅 workflow-check-metrics。

  5. 呈现调查结果 — 提供有证据支持的根因(具体的 TraceId、日志条目、指标变化)、影响范围以及建议的修复方案。可以提出创建事件仪表板(请参阅 create-dashboard 技能)。请参阅 workflow-identify-cause。

快速示例

// rca-triage.mts — run: npx tsx rca-triage.mts
import { kq, KopaiQueryBuildError } from "@kopai/sdk";
import { clientFromConfig } from "@kopai/sdk/node";
const client = clientFromConfig();

try {
  const q = kq.traces
    .aggregate()
    .measure((m) => m.errorRate("error_rate"))
    .measure((m) => m.throughput("rps"))
    .measure((m) => m.avg("Duration", "avg_ns"))
    .measure((m) => m.max("Duration", "max_ns"))
    .measure((m) => m.count("spans"))
    .dimension("service.name")
    .timeRelative("1h")
    .summary()
    .orderByMeasure("error_rate", "desc")
    .build();

  const { data } = await client.query(q); // typed rows
  console.log(JSON.stringify(data, null, 2));
} catch (e) {
  if (e instanceof KopaiQueryBuildError) console.error(e.issues);
  else throw e;
}

规则

1. 工作流(关键)
  • workflow-find-errors - 查找错误 Trace 和错误级别日志
  • workflow-get-context - 获取完整的 Trace 上下文
  • workflow-correlate-logs - 将日志与 Trace 关联起来
  • workflow-check-metrics - 使用聚合 / 时间序列查询量化影响
  • workflow-identify-cause - 确定根因并呈现调查结果
2. 模式(高优先级)
  • pattern-http-errors - HTTP 错误调试
  • pattern-slow-requests - 慢请求分析
  • pattern-distributed - 分布式故障跟踪
  • pattern-log-driven - 日志驱动的调查

阅读 rules/<rule-name>.md 了解详情。

提示

  1. 从聚合数据入手(按服务查看错误率 / 延迟),然后深入查看一条 Trace。
  2. 优先使用 errorRate 度量,而不是筛选 StatusCode(在服务端计数)。
  3. 使用 client.query(q) 执行任何构建好的查询 — 查询具有完整类型支持(行可自动补全,拼写错误会导致编译错误)。
  4. 使用字符串筛选 Duration(f.gt("Duration", "1s"));结果行中的 Duration 仍以纳秒为单位。Trace 调用链中最早的错误通常最接近根因。
  5. 使用 .timeSeries(granularity) 查找回归问题的 开始时间 — 不要将数据保留期限的下限误认为开始时间。
  6. 对于指标,请预先选择类型 — kq.metrics("Gauge")…(自动固定 MetricType,并为值列提供类型)。
  7. 在 SQLite 上,延迟 = Duration 的 avg / max;在 ClickHouse 上改用 p95 / p99。

CLI 回退方案(快速单次查询)

CLI 适用于单次查询,但没有查询 / 聚合命令。注意,StatusCode 的值是字面量 "Error"。

npx @kopai/cli traces search --status-code Error --limit 20 --json
npx @kopai/cli traces get <traceId> --json
npx @kopai/cli logs search --trace-id <traceId> --severity-min 17 --json
npx @kopai/cli metrics discover --json

参考资料

评论

支持 Markdown