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

如何在k6 HTML测试报告中展示请求错误信息

问题分析与解决方案

问题根源

k6的虚拟用户(VU)运行在隔离的沙箱环境中,你定义的globalFailedRequests数组是每个VU独立拥有的副本,主进程中的handleSummary函数无法访问到各个VU沙箱里的数组数据。所以即便每个VU都往数组里push了错误记录,最终在handleSummary里拿到的还是初始化时的空数组。

最简可行修改方案

以下是修复后的完整脚本,通过自定义指标+标签的方式收集错误信息,确保handleSummary能获取到所有失败请求的详情并展示在HTML报告中:

import http from "k6/http";
import { sleep, check } from "k6";
import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
import { Counter } from "k6/metrics";

export const options = {
  stages: [
    { duration: "1s", target: 100 },
    { duration: "3s", target: 200 },
    { duration: "5s", target: 500 },
    { duration: "2s", target: 100 },
    { duration: "1s", target: 0 },
  ],
  thresholds: {
    http_req_duration: ["p(95)<200"],
    http_req_failed: ["rate<0.01"],
    failed_requests: ["rate<0.01"],
  },
};

// 自定义计数器,用于标记失败请求并携带关键信息标签
const failedRequests = new Counter("failed_requests");

export default () => {
  const url = "https://test-url/limit=50&langcode=en";
  const res = http.get(url);

  const success = check(res, {
    "status is 200": (r) => r.status === 200,
    "response time < 200ms": (r) => r.timings.duration < 200,
  });

  if (!success) {
    // 为失败请求添加标签,存储URL、状态码、响应时间、错误摘要等关键信息
    failedRequests.add(1, {
      url: url,
      status: res.status.toString(),
      response_time: res.timings.duration.toFixed(2),
      error: res.body ? res.body.substring(0, 100) : "No error message",
    });

    console.log(
      `Request success: ${success}, Status code: ${res.status}, timing: ${res.timings.duration}`
    );
  }

  sleep(6);
};

export function handleSummary(data) {
  let failedRequestsHtml = "<li>No failed requests</li>";

  // 从自定义指标的标签中提取失败请求详情
  if (data.metrics.failed_requests && Object.keys(data.metrics.failed_requests.tags).length > 0) {
    const failedEntries = Object.entries(data.metrics.failed_requests.tags);
    failedRequestsHtml = failedEntries.map(([tag, value]) => {
      // 解析k6序列化后的标签字符串,还原为键值对
      const tagObj = tag.split(",").reduce((acc, pair) => {
        const [key, val] = pair.split(":");
        acc[key] = val;
        return acc;
      }, {});
      return `<li><strong>URL:</strong> ${tagObj.url} | <strong>Status:</strong> ${tagObj.status} | <strong>Response Time:</strong> ${tagObj.response_time}ms | <strong>Error:</strong> ${tagObj.error}</li>`;
    }).join("");
  }

  // 构造错误详情的HTML模块
  const additionalHtml = `
    <h3>Failed Requests Details</h3>
    <ul>${failedRequestsHtml}</ul>
  `;

  // 生成最终的HTML报告
  const reportWithFailures = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Load Test Summary Report</title>
        <style>
          body { font-family: Arial, sans-serif; max-width: 1200px; margin: 20px auto; padding: 0 20px; }
          h1 { color: #2d3748; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; }
          h3 { color: #2b6cb0; margin-top: 30px; }
          ul { list-style: none; padding-left: 0; }
          li { padding: 10px; margin: 8px 0; background-color: #f7fafc; border-radius: 4px; }
          strong { color: #c53030; }
        </style>
    </head>
    <body>
        <h1>Load Test Summary Report</h1>
        ${htmlReport(data)}
        ${additionalHtml}
    </body>
    </html>
  `;

  return {
    "getLoad.html": reportWithFailures,
  };
}

关键修改说明

  1. 替换全局数组为自定义指标:用Counter类型的自定义指标failed_requests替代全局数组,每个失败请求都会携带包含关键信息的标签,确保主进程的handleSummary能获取到所有VU的错误数据。
  2. 解析标签生成错误列表:k6会将标签对象序列化为逗号分隔的字符串,在handleSummary中解析这些字符串,还原为错误详情后生成HTML列表。
  3. 优化报告样式:添加基础CSS样式,让错误详情模块更易读。

注意事项

  • 如果错误信息过长,建议截取部分内容(如示例中的substring(0, 100)),避免标签值过大影响性能。
  • 若需要完整的错误响应内容,可结合结构化日志输出:运行k6时执行k6 run script.js > failed_requests.log,再用外部脚本解析日志并插入到生成的HTML报告中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:44:58