K6 自定义指标输出
K6 自定义指标输出完整指南
在 K6 性能测试中,除了默认提供的 http_req_duration、http_reqs 等内置指标外,你通常还需要追踪与业务相关的自定义数据,比如某个接口处理了多少条订单、用户登录的成功率、特定操作的平均响应时间等。K6 支持多种自定义指标类型,并且可以通过脚本灵活地记录、聚合以及导出这些数据。
本教程将从零开始,带你掌握 K6 自定义指标的创建、记录与输出,即使你完全没有相关经验,也能轻松上手。
1. 理解 K6 的指标类型
K6 自定义指标共有四种,分别适用于不同的统计场景。
| 指标类型 | 用途说明 | 聚合方式 |
|---|---|---|
| Counter | 累加计数,只增不减。适合记录请求次数、错误次数、完成的业务数量等。 | 自动求和,可计算速率(如 per second) |
| Gauge | 存储当前最新的一个值。适合记录内存使用、并发用户数、队列长度等瞬时状态。 | 保留最小值、最大值和最终值 |
| Rate | 记录某个事件中“真”的比例。适合监控成功率、失败率等。 | 自动统计真值百分比 |
| Trend | 记录一组数值的分布。适合分析响应时间、处理耗时等需要查看百分位数的场景。 | 自动计算平均值、最小值、最大值、中位数、p(90)、p(95) 等百分位数 |
2. 创建你的第一个自定义指标
在 K6 脚本中,你需要先使用 k6/metrics 模块导入对应的类,然后实例化即可。
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
// 定义一个计数器,记录登录尝试次数
const loginAttempts = new Counter('login_attempts');
// 定义一个速率指标,记录登录成功率
const loginSuccessRate = new Rate('login_success_rate');
// 定义一个趋势指标,记录登录耗时
const loginDuration = new Trend('login_duration');
// 定义一个仪表盘,记录当前在线用户数(模拟)
const onlineUsers = new Gauge('online_users');
自定义指标在 K6 的输出中会以独立指标的形式出现,名称就是你传入的字符串。建议使用下划线命名,以便与内置指标风格保持一致。
3. 在测试逻辑中记录数据
指标创建之后,你需要在合适的时机调用它们的 add 方法(或对于 Rate 使用 add(true/false))来记录值。
3.1 Counter 示例
// 每次尝试登录时,计数加 1
export default function () {
loginAttempts.add(1);
// ... 实际登录逻辑
}
你也可以一次增加更多数值,例如批量记录 loginAttempts.add(10)。
3.2 Rate 示例
export default function () {
const res = http.post('https://test-api.com/login', payload);
const success = res.status === 200;
loginSuccessRate.add(success); // true 或 false
}
Rate 会自动统计 true 所占的比例,并在最终结果中显示为百分比。
3.3 Trend 示例
export default function () {
const start = Date.now();
http.get('https://test-api.com/dashboard');
const duration = Date.now() - start;
loginDuration.add(duration);
}
如果需要记录请求自身的响应时间,通常直接使用内置指标即可;自定义 Trend 更适合记录复合操作耗时或纯业务耗时。
3.4 Gauge 示例
// 在每次迭代开始时更新在线用户数
export default function () {
const currentUsers = __VU; // 虚拟用户编号可模拟简单并发数
onlineUsers.add(currentUsers);
// 业务代码...
}
Gauge 不会聚合,最终报告会显示该指标在测试期间的最小值、最大值以及最后一个记录的值。
4. 查看默认输出中的自定义指标
运行测试后,K6 会在终端打印完整的指标摘要。例如:
✓ login_success_rate.........: 0.981742
login_attempts................: 1650 20.49/s
login_duration...............: avg=125.36ms min=85.01ms med=117.83ms max=497.28ms p(90)=211.73ms p(95)=261.85ms
online_users.................: min=0 max=49 last=37
- login_success_rate 带有对勾符号,表示 Rate 指标已自动校验通过(当百分比超过系统设定阈值时标记为成功,可自定义阈值)。
- login_attempts 显示了总数和每秒速率。
- login_duration 显示了 Trend 的完整聚合信息。
- online_users 显示了 Gauge 的最小值、最大值和最终值。
5. 自定义摘要输出(handleSummary)
默认的纯文本摘要可能无法满足需求。例如,你希望将所有自定义指标导出为 JSON 文件,或单独提取 Trend 的百分位结果。K6 提供了 handleSummary() 回调函数,允许你完全控制测试结束时的输出。
5.1 输出 JSON 格式的完整结果
import { Counter, Rate, Trend } from 'k6/metrics';
import { handleSummary } from 'k6';
// 自定义指标定义...
export default function () { /* ... */ }
export function handleSummary(data) {
// data 包含所有内置和自定义指标的聚合结果
return {
'stdout': `${JSON.stringify(data, null, 2)}\n`, // 控制台打印完整 JSON
'summary.json': JSON.stringify(data), // 写入文件
};
}
此时你可以使用 jq 等工具解析 summary.json,提取感兴趣的字段。
5.2 提取特定自定义指标
如果你只想输出自定义指标,可以在 handleSummary 中过滤 data.metrics 对象。
export function handleSummary(data) {
const customMetrics = {};
for (const [key, value] of Object.entries(data.metrics)) {
if (key.startsWith('login_')) { // 只保留我们关心的指标
customMetrics[key] = value;
}
}
return {
'custom_metrics.json': JSON.stringify(customMetrics, null, 2),
};
}
5.3 生成自定义报表字符串
还可以生成格式化的命令行输出,例如只显示成功率和平均耗时:
export function handleSummary(data) {
const rate = data.metrics.login_success_rate;
const dur = data.metrics.login_duration;
const report = `
自定义指标报告
-----------------------------
登录成功率: ${(rate.values.rate * 100).toFixed(2)}%
登录平均耗时: ${dur.values.avg.toFixed(2)} ms
`;
return {
'stdout': report,
};
}
6. 设置指标阈值
你可以为自定义指标添加阈值(Threshold),用于在测试过程中自动判断指标是否符合预期。如果阈值未通过,K6 会在测试结束时报告失败。
import { Rate, Trend } from 'k6/metrics';
const loginSuccessRate = new Rate('login_success_rate');
const loginDuration = new Trend('login_duration');
export const options = {
thresholds: {
'login_success_rate': ['rate > 0.95'], // 成功率必须大于 95%
'login_duration': ['p(95) < 300'], // 95% 的登录请求要在 300ms 内完成
},
};
export default function () {
// ...
}
当某条规则不满足时,K6 将在输出中标记为 ✗,并说明当前指标值与阈值的比较结果。
7. 实际场景最佳实践
7.1 复合业务场景
假设你要测试一个电商下单流程,需要追踪:
- 添加到购物车的次数(Counter)
- 下单成功率(Rate)
- 从添加到下单完成的端到端耗时(Trend)
import { Counter, Rate, Trend } from 'k6/metrics';
import http from 'k6/http';
import { check } from 'k6';
const addToCartCount = new Counter('add_to_cart_total');
const orderPlacementRate = new Rate('order_success_rate');
const endToEndDuration = new Trend('checkout_time');
export default function () {
const start = Date.now();
const cartRes = http.post('https://api.shop.com/cart', { itemId: 123 });
check(cartRes, { 'cart added': (r) => r.status === 201 });
addToCartCount.add(1);
const orderRes = http.post('https://api.shop.com/orders');
const success = orderRes.status === 200;
orderPlacementRate.add(success);
endToEndDuration.add(Date.now() - start);
}
7.2 与外部系统集成
通过 handleSummary,你可以将自定义指标发送到监控系统(如 Datadog、Prometheus Pushgateway 等),只需在函数内编写发送逻辑即可。
export function handleSummary(data) {
const payload = {
successRate: data.metrics.order_success_rate.values.rate,
p95Checkout: data.metrics.checkout_time.values['p(95)'],
};
http.post('https://monitoring.internal/api/metrics', JSON.stringify(payload));
return {}; // 可以同时保留默认输出
}
8. 常见问题
问:为什么我的自定义指标没有出现在控制台报告里?
答:请确认脚本中至少调用了一次 add() 方法。如果指标从未被记录,它不会出现在输出中。
问:Rate 指标为什么显示对勾?
答:K6 会自动为 Rate 指标施加默认阈值 rate > 0.9,满足则显示 ✓。你可以通过自定义阈值覆盖此行为。
问:Trend 指标能不能不计算百分位数?
答:Trend 默认计算多个百分位数,无法关闭。如果你只需要平均值,可以考虑改用 Gauge 并在外部自行聚合,但会损失分布信息,不推荐。
问:如何在 Grafana 等工具中可视化自定义指标?
答:将 K6 结果输出到 InfluxDB 或 Prometheus(通过 -o 输出选项),自定义指标会像内置指标一样被存入时序数据库,然后由 Grafana 展示。这一过程无需修改脚本。
通过本教程,你已经学会了 K6 自定义指标的完整用法:创建指标、记录数据、解读默认输出、自定义摘要、设置阈值以及处理实际业务场景。合理运用自定义指标,可以让你从单纯的性能测试,转向更全面的业务质量监控。现在,马上在你的测试脚本中实践吧!