Reports
The terminal summary, the self-contained HTML report, and the JSON snapshot — what each is for and what is in it.
Every run produces a terminal summary. Two flags add artefacts that outlive the process.
loadwave run test.yaml --report results.html --out results.jsonThe terminal summary
Printed at the end of every run, --ui or not:
────────────────────────────────────────────────────────────────────────────── storefront — completed 30s to 100 VUs, then 5m0s to 100 VUs, then 30s to 0 VUs ran for 6m0s across 1 agent ────────────────────────────────────────────────────────────────────────────── METRIC VALUE requests 184,209 throughput 512/s duration p95 46.3ms failed requests 2,931 (1.59%) checks passed 181,278 of 184,209 REQUEST COUNT AVG P95 P99 MAX ERRORS view product 92,104 30.3ms 48.6ms 50.4ms 91.2ms 3.18% list products 92,105 15.1ms 24.7ms 25.5ms 62.1ms 0% THRESHOLD ACTUAL RESULT http_req_duration p95 < 500 46.34 pass http_req_failed rate < 0.01 0.0159 FAIL
The header line is worth reading rather than skipping: it restates the profile that actually ran and how many agents contributed. A run that says across 1 agent when you expected four has already told you why the numbers are low.
Warnings appear here too, and they matter:
warning: 1,284 samples were dropped by nodes that hit their series cap;
a high-cardinality tag is the usual cause
warning: 12 metric batches arrived too late to be counted; check clock skew between hostsEither one means the reported numbers understate reality. Fix the cause before trusting the run.
The HTML report
loadwave run test.yaml --report results.htmlOr the Download report button in the dashboard, or straight from the API:
curl -O http://localhost:8088/api/v1/runs/<id>/report.htmlOne self-contained file. Charts included, as inline SVG — no scripts, no external assets, no network dependency.
That constraint is the point. It renders the same in an email client, as a CI artefact, as a ticket attachment, or opened in two years to settle an argument about when a regression started. A report that needs a CDN to draw its charts is worthless the moment it leaves the machine that made it.
It contains everything the dashboard showed: the profile, the charts, the per-endpoint breakdown with exact percentiles, the threshold verdicts, agent details, the event log, and the failed-requests table with its response excerpts.
The JSON snapshot
loadwave run test.yaml --out results.jsonThe whole coordinator snapshot: build info, the run summary, per-series
aggregates, correctly merged totals, per-endpoint aggregates, failure kinds,
threshold results, time buckets and events.
This is the one to parse when a later pipeline step needs to make a decision or post a comment.
Read totals, not series. series has one entry per label combination;
totals has one correctly merged aggregate per metric. Folding series yourself
produces plausible-looking numbers that disagree with the thresholds, because
means need re-weighting by count and percentiles need the distributions rather
than their summaries.
A minimal extraction:
# Did anything breach?
jq '.run.thresholdsBreached' results.json
# Which ones, and by how much
jq -r '.run.thresholds[]
| select(.passed == false)
| "\(.metric) \(.stat) \(.op) \(.value) — actual \(.actual)"' results.json
# The whole-run p95
jq '.totals.http_req_duration.p95' results.jsonThe shapes are documented in the REST API reference, since the file is the same object the API serves.
Naming them per run
Nothing generates unique names for you, which is deliberate — a pipeline usually wants to decide that itself:
loadwave run test.yaml \
--name "storefront-$GIT_SHA" \
--tag release="$GIT_SHA" \
--tag env=staging \
--out "results-$GIT_SHA.json" \
--report "results-$GIT_SHA.html"Tagging the run means the artefact identifies what was measured, which matters as soon as you keep more than one of them. The tags are attached to every metric the run produces, so they survive into both files.
What is not kept
Runs are in-memory. There is no database, retention is a rolling window
(--window, default one hour of chart history), and everything is lost when the
coordinator exits. Persistence is a roadmap item, deliberately deferred rather
than half-built.
If you want a run to survive, write the files.