Skip to main content

HAR-based load testing library for jac-scale applications

Project description

jac-loadtest-cli

HAR-based load testing CLI built on Jac. Capture real browser traffic via Chrome DevTools, export it as a .har file, and replay it under load — no scripting required.

The tool registers itself as a jac subcommand, so after installation you run jac loadtest alongside jac start, jac deploy, and the rest of the jac ecosystem.

Compatibility: Works with any HTTP server — jac-scale, Django, FastAPI, Node.js, etc. The only jac-scale-specific feature is auth: if your app uses jac-scale's /user/login JWT flow, credentials are automatically handled. For other auth schemes the raw request from the HAR is replayed as-is.

Testing Modes

Monolith mode (default) — all requests go through a single --url. Use this for production-realistic load testing: it measures what users actually experience end-to-end through the gateway.

Microservice mode — route requests directly to individual service processes by URL path prefix. Use this locally or inside your cluster to isolate per-service latency and identify which service is the bottleneck — without gateway overhead masking the signal.

# Monolith: all traffic through the gateway
jac loadtest recording.har --url http://localhost:8000 --vus 10 --iterations 20

# Microservice: bypass gateway, route by path prefix to individual services
jac loadtest recording.har --mode microservice \
  --url http://localhost:8000 \
  --services-map '{"order_service":"http://localhost:18001","inventory_service":"http://localhost:18002"}' \
  --vus 10 --iterations 20

Note: Microservice mode requires direct network access to service ports. This means it's only usable locally (jac serve) or from inside a Kubernetes cluster — not from outside production. For remote or production load testing, use monolith mode.

Quick Start

# Minimal: 1 VU, 1 HAR replay
jac loadtest recording.har --url http://localhost:8000

# 50 VUs, each replaying the HAR 100 times, with 10s ramp-up
jac loadtest recording.har --url http://localhost:8000 \
  --vus 50 --iterations 100 --ramp-up 10s

# Realistic pacing: replay at recorded think times, halved
jac loadtest recording.har --url http://localhost:8000 \
  --vus 10 --iterations 30 --think-time scaled --think-time-scale 0.5

# Rate-limited stress test: cap global throughput to 50 req/s
jac loadtest recording.har --url http://localhost:8000 \
  --vus 10 --iterations 50 --rps 50

# CI gate: fail if p95 > 500ms or error rate > 1%, stop early on first breach
jac loadtest recording.har --url http://staging:8000 \
  --vus 20 --iterations 100 \
  --fail-on-p95 500 --fail-on-error-rate 1 \
  --threshold-start-delay 10s --abort-on-fail

# Per-request debug output
jac loadtest recording.har --url http://localhost:8000 --vus 2 --iterations 5 --debug

Exit Codes

Code Meaning
0 Test completed; all thresholds passed (or none configured)
1 At least one threshold failed (--fail-on-error-rate, --fail-on-p95, --fail-on-p99)
2 Config or tool error (missing flag, bad HAR file, auth failure)

Failed thresholds are printed to stderr before exit:

THRESHOLD FAILED: error_rate 3.2% > limit 1.0%
THRESHOLD FAILED: p95 612.4ms > limit 500.0ms

Key Flags

Flag Default Description
--vus 1 Concurrent virtual users (asyncio coroutines per worker)
--iterations 1 Stop each VU after N full HAR replays
--ramp-up 0s Stagger VU startup — prevents thundering herd at test start
--workers CPU count Worker processes; each runs its own event loop (capped at --vus and CPU count)
--rps 0 (unlimited) Global requests-per-second cap across all VUs
--timeout 30s Per-request timeout; exceeded requests are recorded as TIMEOUT errors
--think-time none none / real / scaled — inter-request delay from HAR timings
--think-time-scale 1.0 Multiplier on think times (0.5 = half speed, 2.0 = double)
--fail-on-error-rate Fail (exit 1) if global error rate exceeds N%
--fail-on-p95 Fail (exit 1) if global p95 latency exceeds N ms
--fail-on-p99 Fail (exit 1) if global p99 latency exceeds N ms
--threshold-start-delay 0s Ignore threshold checks for this long after the test starts
--abort-on-fail false Stop the test immediately when a threshold is first breached
--debug false Print one line per request to stderr: VU ID, endpoint, status, latency
--report-format console console / json / html
--report-out Write report to file (required for --report-format html)

See docs/COMMANDS.md for the full flag reference including microservice mode, auth, and jac.toml configuration.

Authentication

The tool auto-detects the login request in the HAR by matching --login-path (default /user/login). At test start each VU logs in once and injects the returned JWT into all subsequent requests.

# All VUs log in with the same account used during HAR recording
jac loadtest recording.har --url http://localhost:8000 \
  --username admin@example.com --password secret

Developer Setup

# 1. Navigate to the CLI directory
cd jac_loadtest_cli

# 2. Install the package in editable mode (also installs runtime deps)
jac install -e .

# 3. Verify the command is registered
jac loadtest --help

Running tests

cd jac_loadtest_cli
jac test tests/          # all 148 tests
jac test tests/unit/     # unit tests only
jac test tests/integration/  # integration tests (needs aiohttp servers)

Mock service for local testing

The scripts/mock_service.jac script spins up lightweight HTTP servers to test against without a real backend:

# Start two fake services on ports 8001 and 8002
jac run scripts/mock_service.jac -- order_service:8001 inventory_service:8002

Project Layout

jac_loadtest_cli/          ← Python package (importable as jac_loadtest_cli)
├── plugin.jac             ← registers `jac loadtest` via jaclang entry-points
├── cli.jac                ← argument wiring, run orchestration, exit codes
├── config.jac             ← LoadTestConfig + three-layer config resolution
├── core/
│   ├── har_parser.jac     ← parse HAR 1.2, filter, URL rewrite
│   ├── engine.jac         ← asyncio VU coroutines, RPS cap, threshold watcher
│   ├── metrics.jac        ← RequestResult, MetricsCollector, p50/p95/p99
│   └── process_runner.jac ← multi-process worker orchestration
├── bridge/
│   ├── auth.jac           ← login detection, JWT injection, credential rotation
│   └── topology.jac       ← TopologyRouter, longest-prefix matching
├── output/
│   └── reporter.jac       ← Rich console, JSON, HTML reporters
└── scripts/
    └── mock_service.jac   ← lightweight fake HTTP servers for local testing

HAR Compatibility

Tested with HAR 1.1 and 1.2 (the format exported by Chrome DevTools, Firefox, Postman, and Insomnia). Files from other versions are parsed with a warning — open an issue if something breaks.

Documentation

  • Architecture — module map, data flow, design decisions
  • Commands — full CLI flag reference
  • Roadmap — delivery phases for CLI and web UI
  • Testing — test strategy and coverage guide

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jac_loadtest-0.3.3.tar.gz (96.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jac_loadtest-0.3.3-py3-none-any.whl (317.9 kB view details)

Uploaded Python 3

File details

Details for the file jac_loadtest-0.3.3.tar.gz.

File metadata

  • Download URL: jac_loadtest-0.3.3.tar.gz
  • Upload date:
  • Size: 96.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for jac_loadtest-0.3.3.tar.gz
Algorithm Hash digest
SHA256 5e54ba25138047e13d24524c8af31f3d6a6b7befe4f32b5996a7080da0297009
MD5 e980307638cac7889d5dd8ca578db20e
BLAKE2b-256 87dfb4d6bc0d4297eb725b979e685042e5882642b81cced6ac06a27c1f649749

See more details on using hashes here.

File details

Details for the file jac_loadtest-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: jac_loadtest-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 317.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for jac_loadtest-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 a0a4feccc461bd329c678d48597c6e6cc1e1c9015f932c1b26e1b2f12939de1f
MD5 a3d727fce3860eed552f96cfa9e7cc1c
BLAKE2b-256 d470d658035118be148d2d2196c42ae8d8e456a1a921a9cd8e5d0de86516aa52

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page