ghz Reports: JSON, HTML and Thresholds in CI
ghz writes its results in a chosen format with -O and -o, so CI can parse the JSON and fail when p99 latency or the error rate exceeds a threshold.
A load test is only a gate if something reads the numbers. ghz emits machine-readable JSON you can pipe into jq to assert latency and error budgets.
What it does
ghz formats its run summary in the format given by -O (summary, json, csv, html, pretty) and writes it to the path in -o (or stdout). The JSON includes average, fastest, slowest, latency percentiles under latencyDistribution, and a statusCodeDistribution map you can assert against.
Common usage
# write a JSON report
ghz --insecure --call acme.api.v1.UserService.GetUser \
-d '{"id":"42"}' -n 1000 -c 20 \
-O json -o report.json localhost:50051
# gate: fail if p99 latency exceeds 250ms (ns in the JSON)
jq -e '[.latencyDistribution[]|select(.percentage==99)][0].latency < 250000000' \
report.json
# fail if any non-OK status occurred
jq -e '(.statusCodeDistribution.OK // 0) == .count' report.jsonFlags and options
| Flag / field | What it does |
|---|---|
| -O <format> | Output format: summary, json, csv, html, pretty |
| -o <file> | Write the report to a file instead of stdout |
| latencyDistribution[] | Array of {percentage, latency(ns)} entries |
| statusCodeDistribution | Map of gRPC status to count (OK, Unavailable, ...) |
| count / errorDistribution | Total requests and per-error counts |
In CI
Use jq -e so a failed assertion sets a non-zero exit and fails the job. Latencies in the JSON are nanoseconds, so compare against 250000000 for 250ms, not 250. Archive report.html as a build artifact for humans while the JSON gates the pipeline.
Common errors in CI
"jq: error: Cannot index ... with number" usually means you parsed the summary text instead of -O json. A gate that never fails is often comparing nanoseconds against a millisecond number; fix the units. If statusCodeDistribution shows large Unavailable/DeadlineExceeded counts, the server (or runner) was overloaded, not necessarily a code regression.