Share a JMeter HTML dashboard

jmeter -g results.jtl -o dashboard/ produces a genuinely good report: APDEX scores, a statistics table, response-time percentiles, error breakdowns. It also produces a folder of ~40 files that only renders correctly when opened from disk, which is why it usually reaches the rest of the team as a zip attachment or a screenshot of the summary table.

The people who need the number — the release manager, the backend lead whose endpoint owns the p99 — are exactly the people who won't unzip a folder and open index.html from ~/Downloads.

The pattern

Run the plan, generate the dashboard, publish a summary:

jmeter -n -t plan.jmx -l results.jtl -e -o dashboard/

Store a scoped token (reports:write only) in CI, create the report once, and PATCH it on every run so the test plan keeps one URL:

curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html summary.html \
        --arg title "Load test — $(date -u +%Y-%m-%d) — $BUILD_TAG" \
        '{title: $title, html: $html}')"

Every run appends a revision. A regression is a diff between two revisions instead of two screenshots in a thread.

What renders, honestly

Comma stores report HTML verbatim and renders it inside an iframe with sandbox="allow-scripts" and no allow-same-origin. A report's own JavaScript runs — from an opaque origin, with no access to the app's DOM, cookies or storage. Two JMeter-specific caveats decide the shape of the publish:

  • The dashboard is a folder, not a file. index.html pulls sibling scripts and stylesheets and reads statistics.json at view time. Upload those files as assets alongside the HTML and relative src/href references are rewritten to the uploaded copies.
  • Data fetched at view time is the fragile half. A graph that loads its series over XHR from an opaque origin is the piece most likely to come up empty. The tables are rendered into the HTML and have no such problem.

Which is why, for JMeter specifically, a single self-contained summary is the publish that reliably works — and it's the part people read anyway:

  • Publish the statistics table as the body. Transaction name, sample count, error %, average, p90/p95/p99, throughput. Either lift the tables out of the generated index.html and statistics.json, or render your own from the .jtl with a short script. That table is the report.
  • Attach the rest. The full dashboard folder (zipped), the raw .jtl, and any exported chart PNGs go in as assets — 25 MB per file, 250 MB per report. Chart images can also be inlined in the body as <img> so the shape of the curve is visible without a download.
  • Add the run's context to the body. Duration, thread count, ramp-up, target environment, and the build under test. A load-test number with no configuration attached is unreviewable, and this is the one report type where people forget to write it down.

Where the discussion goes

The published summary renders with an anchored comment layer on top. The backend lead highlights the POST /checkout row and pins a thread: "the p99 moved after we turned on the new pricing cache — that's the cold path, not the hot one." The thread stays attached to the transaction as later runs append revisions, so next month's regression conversation starts with last month's conclusion instead of restarting it.

That is the part a zipped folder structurally cannot do: comments anchored to the report, and a revision history you can diff.

Wiring it into a pipeline

Load tests usually run on a schedule rather than per-commit, which fits the same machinery:

  • Nightly or weekly plan — publish from CI, or from a routine if you'd rather have the schedule live next to the report.
  • Announce it — a webhook on revision.created drops each new run into Slack, so people see the number without going looking.
  • Keep it team-visible — see the sharing model.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history. Publish tonight's run and send the link instead of the zip.

Create your first report →

Related