Load / Performance Tests

Alongside unit tests and coverage, UniTrack ingests load/performance-test results — latency percentiles, throughput and error rate — keyed by project/branch/commit like a test run, so a team gets self-hosted, free, per-commit performance-regression tracking without a separate SaaS or a Grafana stack.

1. Uploading

Add a perf file to the ingest upload; the format is auto-detected:

  • JMeter JTL — the CSV results file (jmeter -l results.jtl). Per-sample, so the parser computes p50/p90/p95/p99 latency, throughput and error rate itself, overall and per request label.

  • k6 JSON summary — k6 run --summary-export=summary.json. Pre-aggregated; the parser reads http_req_duration percentiles, http_reqs count/rate and http_req_failed.

  • JMH JSON — a JMH microbenchmark result run with -rf json (track JVM library performance over time). Each benchmark becomes one tracked label (Class.method[params]); scores are normalised to ms, lower-is-better. Time-per-op modes (avgt/sample/ss) carry real percentiles — prefer avgt; thrpt (ops/sec) is inverted to a mean ms/op with flat percentiles. JMH has no error concept, so error rate is always 0.

scripts/unitrack-upload.sh --project myapp --commit "$GIT_SHA" --perf results.jtl
# or perf alongside tests + coverage in one upload:
scripts/unitrack-upload.sh --project myapp --commit "$GIT_SHA" \
  --junit 'target/surefire-reports/TEST-*.xml' --perf results.jtl

A perf upload may be sent on its own (no junit needed); the response carries a perfRunId.

The project Load tests page (/projects/{id}/perf) charts, over recent runs:

  • Latency — p50 / p90 / p99 lines (ms)

  • Throughput — requests/second

  • Error rate — percent

plus a table of recent perf runs. GET /api/v1/projects/{id}/perf-trend returns the same series as JSON.

3. Run detail

Each row in the recent-runs table links to a run-detail page (/perf-runs/{id}) showing the run’s summary metrics (p50/p90/p95/p99, throughput, error rate, samples, duration), the quality-gate verdict with its per-rule pass/fail breakdown, and a per-label table: samples, error rate and percentiles for every request label, each with its p95 delta versus the same label in the baseline run. GET /api/v1/perf-runs/{id} returns the same detail as JSON.

4. Regression gate

GET /api/v1/perf-runs/{id}/regression compares a run to its baseline (latest prior perf run on the base branch with the same flag) on three rules:

Rule Threshold (unitrack.performance.*) Fails when

latency-p95

latency-regression-pct (15%)

p95 latency rises more than the limit vs baseline.

throughput

throughput-drop-pct (10%)

throughput drops more than the limit vs baseline.

error-rate

max-error-pct (1%)

the run’s error rate exceeds the limit.

It returns 200 within thresholds and 422 on regression, so a CI step can fail the build on the HTTP status (the JSON body carries the per-rule detail either way). With no baseline yet, only the error-rate rule applies.

curl --fail "$UNITRACK_URL/api/v1/perf-runs/$PERF_RUN_ID/regression"   # exits non-zero on 422
Gatling support is planned — see the roadmap.