mcpField
K
k6-cloud-investigate-test

k6-cloud-investigate-test

github.com/grafana测试与质量2952.7k 次安装1 天前更新
代码仓库

关于 k6-cloud-investigate-test

通过九步流程调查 Grafana Cloud k6 测试和运行结果的工作流型技能。它结合运行元数据、指标、日志和实际执行的脚本快照,并检查日期范围以及运行结果与脚本内检查的区别。

主要功能

  1. 01九步调查工作流
  2. 02分页发现测试运行
  3. 03核对日期范围是否匹配
  4. 04三层通过与失败分析
  5. 05检查指标、日志和脚本快照

适用场景

  1. 01调查失败或异常的测试运行
  2. 02比较通过与失败的运行
  3. 03确认近期运行是否符合指定时间范围
  4. 04追踪多次运行间的指标或脚本变化

MCP 相关

它通过 Grafana 插件代理调用 gcx API:REST 端点使用 v6,指标查询使用 v5。输入未说明它与 MCP 的关系。

安装

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

$npx skills add https://github.com/grafana/skills --skill k6-cloud-investigate-test

安装后在 Claude Code 中输入/k6-cloud-investigate-test确认已加载。

附带文件references/worked-example.md

详细介绍

k6 Cloud 测试调查

用于调查 Grafana Cloud k6 测试或运行的结构化 9 步工作流。

此技能仅包含工作流。所有 API 调用都通过 gcx api,针对插件代理执行;REST 使用 v6,指标使用 v5。有关底层机制(gcx 身份验证、路径约定、端点发现、日志查询、脚本编辑、阈值语义和注意事项),请参阅 k6-manage 技能——以下每个步骤都会引用它。

此技能独有的内容:

  • 按顺序排列的调查流程(下文的步骤 1-9)
  • 日期对齐检查(“过去 7 天” ≠ “最近 7 次运行”)
  • 3 层通过/失败判定(result 与 status,以及按检查项查询 checks)
  • 一个包含实际数字的示例(references/worked-example.md)

核心原则

  1. 先读后写。 执行任何 PUT 之前,务必先 GET 脚本。gcx k6 load-tests update-script 是一项写入操作,会用你传入的文件替换线上脚本——有用户仅仅为了“看看它访问的 URL”而运行该命令,结果导致生产脚本被覆盖。如果需要了解 URL,请改用带有 -vvv --log-http-payload 的任何非变更命令。
  2. 列举运行时要分页。 /test_runs 端点最多返回 1000 行,而且 gcx k6 runs list --limit 0 不会自动跟进 @nextLink。请使用 k6-manage §3 中记录的 gcx api 循环。
  3. 核实日期范围。 用户提到“过去 7 天”“本周”或“最近的运行”时,确认最新运行的 created 是否确实落在该时间范围内。如果不符,指出这一差距。
  4. check() 不会导致运行失败;只有 thresholds 才会。 而且,没有观测数据的阈值会报告为 ✓ 通过。完整说明请参阅下文的“阈值语义”;步骤 5 中按检查项查询 checks 指标可以捕获这两种情况。

前提条件

已安装 gcx,并已针对用户的堆栈完成身份验证。请参阅 k6-manage §1。使用以下命令验证:

gcx --context <stack> config check    # expect "✔ Connectivity: online"

调查工作流

步骤 1:确定测试和目标运行

根据用户提供的 URL:

  • /a/k6-app/tests/<id> → 负载测试(许多运行的父级)
  • /a/k6-app/runs/<id> → 某次特定运行

要从运行查找测试:通过 gcx api 获取运行;路径格式规则请参阅 k6-manage §2:

gcx --context <stack> api /api/plugins/k6-app/resources/cloud/cloud/v6/test_runs/<run_id>

然后从响应中读取 .test_id。要列出某个测试的运行,请参阅步骤 3。

步骤 2:获取测试元数据和脚本
gcx --context <stack> k6 load-tests get <test_id> -o json

获取脚本时,请按照 k6-manage §5 中安全编辑方法的 GET 部分操作——如果之后要编辑,请保存备份。

脚本有两个端点,这一区别对调查很重要。 k6-manage §5 对两者都有说明:当前负载测试脚本,以及每次运行实际执行的脚本快照。只要运行后编辑过脚本,两者就会出现差异。如果问题涉及“发生了什么变化”“为什么这次运行失败”,或者你要检查几天前的运行,也要通过 k6-manage §5 中的运行脚本端点获取运行捆绑的快照,并与当前负载测试脚本(或另一次运行的快照)进行差异比较。当前负载测试脚本并不是分析过去某次运行的正确依据。

步骤 3:列出运行并进行分页

针对 /cloud/v6/load_tests/<test_id>/test_runs,使用 k6-manage §3 中记录的 gcx api + @nextLink 循环模式。收集完 all_runs 后:

print(f"Total: {len(all_runs)}")
runs_sorted = sorted(all_runs, key=lambda r: r['created'], reverse=True)
for r in runs_sorted[:10]:
    print(f"  {r['created']:30s} id={r['id']:>8} status={r['status']:<10} result={r.get('result','?')}")

向用户报告:运行总数、日期范围、最近一次运行的日期。如果“最近一次运行”距今超过一天,请明确指出——用户可能以为定时任务仍在触发,实际上并没有。

步骤 4:确认日期范围符合用户意图

如果用户询问“过去 7 天”/“本周”/“最近”,应按日期范围筛选,而不是按行数筛选——“最近 7 次运行”可能涵盖一天,也可能涵盖一年,具体取决于测试运行的频率。

last7 = [r for r in all_runs if r['created'] >= '<today_minus_7_days_iso>']

如果 len(last7) == 0:立即告知用户。不要继续使用过时数据。

第 5 步:确定通过/失败状态

对于每次运行,检查以下三个相互独立的层面:

层面字段含义
运行级结果result(passed / failed / error / aborted)是否超出阈值
运行级状态status(completed / aborted)运行是否正常结束
脚本内检查v5 checks 指标,按 check 标签聚合每项检查的成功率

如果用户认为某次运行“失败”,但报告的结果是 result: passed,请检查第三个层面。常见情况是:每次迭代的 check() 都返回 false,但由于没有为 checks 定义阈值,运行仍然“通过”。有关详细说明,请参阅下文的“阈值语义”(零观测陷阱、abortOnFail 的云端延迟、运算符支持)。

通过 v5 查询每项检查的细分结果(query_aggregate_k6 的参数格式见 k6-manage/references/metrics.md §7):

gcx --context <stack> api \
  "/api/plugins/k6-app/resources/cloud/cloud/v5/test_runs/<run_id>/query_aggregate_k6(query='ratio by (check)',metric='checks')"

响应中的每个结果条目都带有一个 check 标签,其中包含检查名称和一个值:成功率(0.0–1.0)。如需获取原始成功/失败计数,也可查询 increase_nz by (check)(成功次数)和 increase_z by (check)(失败次数)。

第 6 步:获取运行指标

使用 k6-manage/references/metrics.md 中记录的 v5 指标端点。典型工作流:

# 6a. List metrics available for the run (metrics.md §1)
gcx --context <stack> api /api/plugins/k6-app/resources/cloud/cloud/v5/test_runs/<run_id>/metrics

# 6b. List labels for a metric to know what's available to filter/group by (metrics.md §4)
gcx --context <stack> api \
  "/api/plugins/k6-app/resources/cloud/cloud/v5/test_runs/<run_id>/labels?match[]=http_req_duration"

# 6c. Time-series — pick a query method that matches the metric's type (metrics.md §6)
gcx --context <stack> api \
  "/api/plugins/k6-app/resources/cloud/cloud/v5/test_runs/<run_id>/query_range_k6(query='histogram_quantile(0.95) by (name,status)',metric='http_req_duration',step=10)"

# 6d. Scalar aggregate over the whole run (metrics.md §7)
gcx --context <stack> api \
  "/api/plugins/k6-app/resources/cloud/cloud/v5/test_runs/<run_id>/query_aggregate_k6(query='increase',metric='http_reqs')"

根据指标类型选择合适的查询方法很重要,详见 k6-manage/references/metrics.md 中的“查询方法”表格。对于浏览器测试,URL/状态细分来自 labels + label/{name}/values(metrics.md §4/§5),而不是单独的标签端点。

第 7 步:获取运行日志

遵循 k6-manage §4 中的 Loki 操作说明(使用 gcx api 请求 /api/plugins/k6-app/resources/logs/...,选择器为 {test_run_id="<id>"},必须带上 X-K6TestRun-Id 标头,将 start/end 范围限定在 run.created/run.ended)。将响应保存到 /tmp/run_<id>_logs.json,并按其中的说明根据该文件撰写摘要。

第 8 步:(如有要求)安全地编辑脚本

使用 k6-manage §5 中完整的安全编辑操作说明(GET → 备份 → 编辑 → k6 inspect → 1 次迭代的冒烟测试 → 使用 Content-Type: application/octet-stream 执行 PUT → 验证 sha256)。

如果编辑涉及阈值,还需阅读下文的“阈值语义”,了解零观测陷阱、abortOnFail 的云端延迟以及运算符支持情况(尽管文档未说明,==/!= 仍然有效)。

第 9 步:报告

根据问题类型选择模板。

单次运行调查(“运行 X 怎么了”):

Test: <name> (id <test_id>)
Run:  <run_id> @ <created> → <ended>, load_zone=<zone>, result=<result>

Logs (<n> streams, <m> lines):
  - <stream summary>

Metrics (key indicators):
  - <metric>: <method> = <value> (n=<count>)
  ...

Per-check breakdown:
  - <check name>: <success_rate> (succ=<n>, fail=<n>)
  ...

Diagnosis: <one-paragraph>

多次运行对比(“通过和失败的运行之间有哪些不同”“这个改动导致了失败吗”):

Question: <one-line restatement of what the user is trying to attribute>

Run timeline (relevant window):

| Run ID | Created (UTC) | Result | exec_duration | processing_duration | k6 build | error code | key check ratios |
|---|---|---|---|---|---|---|---|
| ... | ... | passed | 60s | 195s | <build> | — | 1.0/1.0/1.0 |
| ... | ... | failed | 27s | 193s | <build> | — | 0.0/n=0/n=0 |
| ... | ... | error  | 51s | 3601s aborted | <build> | 8016 | 1.0/1.0/1.0 |

Differences that matter:
  - <field>: <value-in-passing> vs <value-in-failing> — <interpretation>
  ...

Script diff (if relevant): <bundled-script diff between a representative passing and failing run, summarised>

Diagnosis: <one-paragraph attributing the change to test-side, SUT-side, or platform-side, with the supporting evidence>

该表格能清楚展示并排异常(例如,通过和失败的运行中某列的值相同,就能排除该维度是原因;某列的值在两者之间变化,就可能是原因)。

如果用户要求导出原始数据,也请将其保存到 /tmp/k6inv/run<id>/,并告知相应路径。

阈值语义

决定运行 result 的是阈值,而不是 check() 调用。这里有几个容易误导初次调查者、不太直观的情况,因此集中说明如下。第 5 步(“确定通过/失败状态”)和第 8 步(“安全地编辑脚本”)都依赖本节内容。

result 的含义
result 值含义
passed所有阈值均通过(或未定义任何阈值)
failed至少有一个阈值未通过
error脚本在完成前崩溃(例如,浏览器无法启动),或者 k6 Cloud 在平台端中止了运行。要判断是哪种情况,请检查该次运行中的 status_history[*].extra.code — 非空代码表示平台中止(例如,在 processing_metrics 期间,8016 = “测试运行超过最长持续时间”)。平台中止并非代码的问题,尽管它们会显示为 error。
aborted用户或系统中止了运行

check() 调用不会直接影响 result。它们会将观测结果写入内置的 checks 速率指标,之后阈值可以对其进行评估。如果没有阈值引用 checks,检查失败不会反映在运行级别的 result 中。

“零观测 = 通过”陷阱

当底层指标没有样本时,k6 会将阈值报告为 ✓ 通过 — 即使阈值表达式本应求值为 false:

checks{check:response is 200}
✓ 'rate==1.0' rate=0.00%       ← ✓ pass!?

如果脚本在执行到相关的 check() 调用之前抛出异常,就会遇到这个问题。在 catch 块中强制记录一次检查观测,让阈值能够看到一些内容:

try {
  const r = await page.goto(URL);
  check(r, { "response is 200": x => x.status() === 200 });
  // ... rest of iteration body
  check(true, { "script completed without exception": () => true });
} catch (e) {
  console.error(e);
  check(null, { "script completed without exception": () => false });
} finally {
  await page.close();
}

然后将 'checks{check:script completed without exception}': ['rate==1.0'] 添加到阈值中。这样既能捕获导航失败,也能捕获后续阶段的异常。

abortOnFail 云端延迟

k6 在云端运行时,每 60 秒评估一次阈值。abortOnFail 功能最多可能延迟 60 秒。

对于短于 60 s 的运行,迭代可能自然结束,导致 abortOnFail 尚未触发。阈值仍会在运行结束时进行评估,且 result 会变为 failed — 只是中止无法节省执行时间。

运算符

文档中展示了 <、>、<=、>=。== 和 != 也可用,尽管文档中没有列出。对于 rate 指标(值为 0.00–1.00),rate==1.0 表示“每次观测都非零”,而 rate==0 表示“所有观测均为零”。

特定工作流的注意事项

规范注意事项列表(认证过期、重复的 cloud/cloud/、脚本 PUT 返回 415、Loki 缺少 X-K6TestRun-Id、脚本 PUT 不会更新 updated、gcx k6 runs list --limit 0 不会跟进 @nextLink)请参阅 k6-manage §7。以下条目仅适用于本次调查工作流:

症状原因解决方法
“最新一次运行是 6 个月前”,但计划显示为每天运行你没有对 /test_runs 进行分页使用 k6-manage §3(步骤 3)中的 @nextLink 循环
“最近 7 天”报告只包含较早的运行记录按行数而非日期进行筛选按 created >= <iso_date> 重新筛选(步骤 4)
阈值报告显示 ✓ 通过,但检查失败检查观测数为零;迭代在运行 check() 前已中止请参阅上文“阈值语义”
result: error,但脚本日志/指标看起来正常很可能是平台中止(例如 processing_metrics 超过 1 小时上限,code 8016)。执行本身已正常完成。检查该次运行中的 status_history[*].extra.code。平台代码非空 → 不是你的代码导致的。请参阅“阈值语义”
通过读取当前负载测试脚本来调查过去的运行运行执行后脚本可能已被编辑——你读到的并非当时实际运行的内容通过每次运行对应的端点获取该次运行打包后的脚本(k6-manage §5),并与当前负载测试脚本进行差异比较后再下结论
刚刚覆盖了用户的脚本调用了 update-script 来“查看 URL”从步骤 2 中创建的备份恢复。若要在不写入的情况下了解 URL,请对任何非变更命令使用 -vvv --log-http-payload。
CLI --iterations 1 破坏了浏览器场景它会完全覆盖场景块改用 sed 在文件中编辑 iterations:

参考资料

评论

支持 Markdown