k6 标签和分组的使用
(Grafana k6 登堂入室, Part 11)
发表于 2026-03
标签和分组 -> Tags and Groups
为什么需要标签和分组
一次负载测试通常会涉及多个 API 端点和业务流程。当测试结果全部汇总在一起时,很难定位到底是哪个环节出了问题。k6 通过标签(Tags)和分组(Groups)来帮你切分和过滤结果。
- 标签:给请求、检查、自定义指标打上标签,方便按标签维度分析
- 分组:把相关的操作归到一起,自动打上
group标签
之前介绍阈值时提到的按标签筛选,底层就是这套机制。
系统标签
k6 默认会自动给每个 HTTP 请求加上一组系统标签:
| 标签 | 说明 |
|---|---|
proto |
协议名(如 HTTP/1.1) |
status |
HTTP 状态码 |
method |
HTTP 方法(GET、POST 等) |
url |
请求 URL |
name |
请求名称(默认就是 URL) |
group |
所属分组的完整路径 |
check |
检查的名称 |
error |
非 HTTP 错误信息(如网络/DNS 错误) |
error_code |
错误码 |
tls_version |
TLS 版本 |
scenario |
所属场景的名称 |
expected_response |
根据状态码判断是否为预期响应,默认 2xx/3xx 为 true |
另外还有几个可选的系统标签,需要通过 systemTags 选项手动开启:
| 标签 | 说明 |
|---|---|
vu |
执行该请求的 VU ID |
iter |
迭代编号 |
ip |
远程服务器的 IP 地址 |
ocsp_status |
OCSP 状态 |
自定义标签
你可以在请求、检查和自定义指标上添加自己的标签:
import http from 'k6/http';
import { Trend } from 'k6/metrics';
import { check } from 'k6';
const myTrend = new Trend('my_trend');
export default function () {
// 给请求加标签
const res = http.get('https://quickpizza.grafana.com/', {
tags: {
my_tag: "I'm a tag",
},
});
// 给检查加标签
check(res, { 'status is 200': (r) => r.status === 200 }, { my_tag: "I'm a tag" });
// 给自定义指标加标签
myTrend.add(res.timings.connecting, { my_tag: "I'm a tag" });
}
全局标签
如果想给所有指标统一加上标签,有两种方式。
通过命令行:
k6 run --tag name=value script.js
或在脚本中配置:
export const options = {
tags: {
name: 'value',
},
};
代码动态标签
有时候标签的值需要根据运行时逻辑来决定。通过 k6/execution 模块可以动态设置和读取标签:
import http from 'k6/http';
import exec from 'k6/execution';
import { group } from 'k6';
export const options = {
thresholds: {
'http_reqs{container_group:main}': ['count==3'],
'http_req_duration{container_group:main}': ['max<1000'],
},
};
export default function () {
exec.vu.tags.containerGroup = 'main';
group('main', function () {
http.get('https://test.k6.io');
group('sub', function () {
http.get('https://quickpizza.grafana.com/');
});
http.get('https://quickpizza.grafana.com/api/headers');
});
delete exec.vu.tags.containerGroup;
}
也可以读取已有的标签:
import exec from 'k6/execution';
export default function () {
const tag = exec.vu.tags['scenario'];
console.log(tag); // default
}
给阶段打标签
如果你使用了 stages 选项(VU 数量逐步变化),可以借助 k6-jslib-utils 来标记当前处于哪个阶段:
import http from 'k6/http';
import { tagWithCurrentStageIndex } from 'https://jslib.k6.io/k6-utils/1.3.0/index.js';
export const options = {
stages: [
{ target: 5, duration: '2s' },
{ target: 10, duration: '5s' },
],
};
export default function () {
tagWithCurrentStageIndex();
// 所有请求都会带上 stage 标签,值为当前阶段的索引
http.get('https://test.k6.io'); // 比如 {stage: "1"}
}
还有一个 tagWithCurrentStageProfile 函数,会根据当前阶段的目标 VU 数相对于上一个阶段的变化,自动标记为:
| Profile 值 | 含义 |
|---|---|
ramp-up |
当前阶段目标高于上一阶段 |
steady |
当前阶段目标等于上一阶段 |
ramp-down |
当前阶段目标低于上一阶段 |
分组(Groups)
分组用来把一组操作归类在一起。典型场景是按用户操作流程来组织:
import { group } from 'k6';
export default function () {
group('visit product listing page', function () {
// ...
});
group('add several products to the shopping cart', function () {
// ...
});
group('checkout process', function () {
// ...
});
}
分组做了两件事:
- k6 会为每个
group()产生一个group_duration指标,记录该分组内所有操作的总耗时 - 分组内的请求、检查和自定义指标都会自动带上
group标签
分组可以嵌套,标签值用 :: 分隔。比如根分组名为空字符串,一个名为 cool requests 的分组,实际的 group 标签值是 ::cool requests。
避免每个请求包一层 group
如果你发现每个 HTTP 请求外面都套了一层 group(),那多半是用错了。比如:
// 不推荐
group('get post', function () {
http.get(`http://example.com/posts/${id}`);
});
group('list posts', function () {
http.get(`http://example.com/posts`);
});
更好的做法是:
- 对动态 URL 使用 URL grouping(通过
tags.name把相似 URL 合并) - 用普通函数或本地模块来组织代码
- 用场景来模拟不同的用户行为
lyyyuna 沪ICP备2025110782号-1