You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让k6生成类Locust风格的按路径分组HTML测试报告?

实现k6按路径分组的HTML报告(仿Locust风格)

核心思路

要实现类似Locust的按路径分组报告,关键是给请求指标打路径标签,再通过自定义报告逻辑聚合标签数据并渲染成分组视图。以下是具体实现步骤:


1. 给请求指标添加路径标签

在k6脚本中定义带url_path标签的自定义指标,每个请求完成后将路径作为标签值传入指标:

import http from 'k6/http';
import { Trend, Counter } from 'k6/metrics';

// 定义带路径标签的性能指标
const reqDuration = new Trend('request_duration', { tags: ['url_path'] });
const reqCount = new Counter('request_count', { tags: ['url_path'] });

export const options = {
  vus: 10,
  duration: '30s',
};

export default function () {
  // 示例请求1:/public/crocodiles/
  let res = http.get('https://test-api.k6.io/public/crocodiles/');
  // 给指标绑定当前请求路径
  reqDuration.add(res.timings.duration, { url_path: '/public/crocodiles/' });
  reqCount.add(1, { url_path: '/public/crocodiles/' });

  // 示例请求2:/public/crocodiles/1/
  res = http.get('https://test-api.k6.io/public/crocodiles/1/');
  reqDuration.add(res.timings.duration, { url_path: '/public/crocodiles/1/' });
  reqCount.add(1, { url_path: '/public/crocodiles/1/' });
}

2. 自定义HTML报告渲染逻辑

利用k6的handleSummary钩子,提取按url_path分组的指标数据,编写自定义HTML模板渲染分组视图:

export function handleSummary(data) {
  // 聚合按路径分组的指标数据
  const pathMetrics = {};

  // 处理响应时长指标
  if (data.metrics.request_duration) {
    Object.keys(data.metrics.request_duration.tags).forEach(path => {
      pathMetrics[path] = {
        ...(pathMetrics[path] || {}),
        duration: {
          avg: Math.round(data.metrics.request_duration.tags[path].values.avg),
          p95: Math.round(data.metrics.request_duration.tags[path].values.p95),
          min: Math.round(data.metrics.request_duration.tags[path].values.min),
          max: Math.round(data.metrics.request_duration.tags[path].values.max),
        }
      };
    });
  }

  // 处理请求计数指标
  if (data.metrics.request_count) {
    Object.keys(data.metrics.request_count.tags).forEach(path => {
      pathMetrics[path] = {
        ...(pathMetrics[path] || {}),
        count: data.metrics.request_count.tags[path].values.count,
      };
    });
  }

  // 自定义HTML模板(仿Locust分组样式)
  const reportHtml = `
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
    <meta charset="UTF-8">
    <title>k6 按路径分组性能报告</title>
    <style>
      * { box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, sans-serif; }
      .container { max-width: 1200px; margin: 20px auto; padding: 0 20px; }
      .group-card { margin: 15px 0; padding: 18px; border: 1px solid #e0e0e0; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
      .group-title { font-size: 1.1em; font-weight: 600; color: #2c3e50; margin-bottom: 12px; }
      .metric-item { margin: 6px 0; color: #34495e; }
      .metric-label { display: inline-block; width: 120px; }
    </style>
  </head>
  <body>
    <div class="container">
      <h1 style="text-align: center; margin: 20px 0; color: #2c3e50;">k6 按路径分组性能报告</h1>
      ${Object.keys(pathMetrics).map(path => `
        <div class="group-card">
          <div class="group-title">请求路径:${path}</div>
          <div class="metric-item"><span class="metric-label">请求总数:</span>${pathMetrics[path].count || 0}</div>
          <div class="metric-item"><span class="metric-label">平均响应时长:</span>${pathMetrics[path].duration?.avg || 0}ms</div>
          <div class="metric-item"><span class="metric-label">P95响应时长:</span>${pathMetrics[path].duration?.p95 || 0}ms</div>
          <div class="metric-item"><span class="metric-label">最小响应时长:</span>${pathMetrics[path].duration?.min || 0}ms</div>
          <div class="metric-item"><span class="metric-label">最大响应时长:</span>${pathMetrics[path].duration?.max || 0}ms</div>
        </div>
      `).join('')}
    </div>
  </body>
  </html>
  `;

  return {
    'path-grouped-report.html': reportHtml, // 生成自定义分组报告
    'summary.json': JSON.stringify(data), // 可选:保留原始数据文件
  };
}

3. 添加图表扩展(可选)

如果需要给分组报告添加图表(比如响应时长对比柱状图),可在自定义HTML中内嵌Chart.js(若要避免外链,可将Chart.js代码本地挂载到Docker容器中引用),示例如下:

在HTML的<head>中添加Chart.js(本地挂载则替换为容器内路径):

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

在<body>末尾添加图表容器和渲染脚本:

<canvas id="durationChart" width="800" height="400" style="margin: 20px auto; display: block;"></canvas>
<script>
  const ctx = document.getElementById('durationChart').getContext('2d');
  const paths = ${JSON.stringify(Object.keys(pathMetrics))};
  const avgDurations = paths.map(p => pathMetrics[p].duration?.avg || 0);

  new Chart(ctx, {
    type: 'bar',
    data: {
      labels: paths,
      datasets: [{
        label: '平均响应时长(ms)',
        data: avgDurations,
        backgroundColor: 'rgba(30, 136, 229, 0.6)',
        borderColor: 'rgba(30, 136, 229, 1)',
        borderWidth: 1
      }]
    },
    options: {
      responsive: true,
      scales: {
        y: { beginAtZero: true, title: { display: true, text: '响应时长(ms)' } },
        x: { title: { display: true, text: '请求路径' } }
      }
    }
  });
</script>

运行与验证

在Docker中运行k6脚本:

docker run -i loadimpact/k6 run - <your-script.js>

运行完成后,当前目录会生成path-grouped-report.html,打开即可看到按路径分组的报告,逻辑与Locust分组视图一致。

内容的提问来源于stack exchange,提问作者lobafox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:44:49