lyyyuna 的小花园

动静中之动, by

RSS

k6 标签和分组的使用

发表于 2026-03
标签和分组 -> Tags and Groups

为什么需要标签和分组

一次负载测试通常会涉及多个 API 端点和业务流程。当测试结果全部汇总在一起时,很难定位到底是哪个环节出了问题。k6 通过标签(Tags)和分组(Groups)来帮你切分和过滤结果。

之前介绍阈值时提到的按标签筛选,底层就是这套机制。

系统标签

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 () {
    // ...
  });
}

分组做了两件事:

  1. k6 会为每个 group() 产生一个 group_duration 指标,记录该分组内所有操作的总耗时
  2. 分组内的请求、检查和自定义指标都会自动带上 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`);
});

更好的做法是:

lyyyuna 沪ICP备2025110782号-1