A load testing framework with a Python UI and a bare-metal Rust engine core.
Project description
strobengine
A high-performance HTTP load testing engine with a Python API and a bare-metal Rust core.
Dependencies
- Python >= 3.11
- Rust (stable, with
cargo) - uv (Python package manager)
Rust crates
| Crate | Version | Purpose |
|---|---|---|
| pyo3 | 0.29 | Python FFI bindings (stable ABI, abi3-py311) |
| reqwest | 0.13 | HTTP client with connection pooling |
| tokio | 1.53 | Multi-threaded async runtime |
| tokio-util | 0.7 | CancellationToken for graceful worker shutdown |
| tracing | 0.1 | Structured logging instrumentation |
| tracing-subscriber | 0.3 | Log formatting and output (stderr/file) |
Installation & Compilation
# Clone the repository
git clone https://github.com/riccione/strobengine.git
cd strobengine
# Build the native extension and install the package
uv sync
uv sync invokes maturin under the hood, which compiles the Rust code into a native Python extension module and installs it into your virtual environment.
Quick Start Usage
from strobengine import StrobEngine
from strobengine.reporter import print_summary
# Constant load test
engine = StrobEngine(url="http://localhost:8080/api/health", concurrency=50, duration=30)
summary = engine.run()
print_summary(summary, url=engine._url, duration_secs=30)
# Ramp/stress test (10 -> 200 workers over 60s, hold 30s)
engine = StrobEngine.stress_test(
"http://localhost:8080/api/health",
start_concurrency=10, max_concurrency=200,
ramp_duration=60, hold_duration=30,
)
summary = engine.run()
print_summary(summary, url=engine._url, duration_secs=30)
# Spike test (baseline 5 -> peak 500 -> back to 5)
engine = StrobEngine.spike_test(
"http://localhost:8080/api/health",
baseline=5, peak_concurrency=500,
pre_spike_duration=5, spike_duration=10, post_spike_duration=5,
)
summary = engine.run()
print_summary(summary, url=engine._url, duration_secs=30)
For async contexts (FastAPI, Typer, etc.):
summary = await engine.run_async()
CLI Usage
# Constant load test (default subcommand)
strobengine http://localhost:8080/api/health -c 50 -d 30
# Ramp/stress test
strobengine stress http://localhost:8080/api/health --from 10 --to 500 --ramp 60 --hold 30
# Spike test
strobengine spike http://localhost:8080/api/health --baseline 5 --peak 1000 --pre-spike 5 --spike-duration 10 --post-spike 5
# JSON output for CI/CD
strobengine load http://localhost:8080/api/health --json
By default, this spawns 10 concurrent workers for 10 seconds with a 10-second request timeout. Results are displayed as a formatted table with total requests, errors, requests/sec, and latency percentiles (avg, p95, p99).
Subcommands
| Subcommand | Description |
|---|---|
load |
Constant load test (default if no subcommand given) |
stress |
Ramp from starting to target concurrency, then hold |
spike |
Baseline -> peak -> baseline |
Load Subcommand Options
| Flag | Default | Description |
|---|---|---|
-c, --concurrency |
10 |
Number of concurrent workers |
-d, --duration |
10 |
Duration in seconds |
-t, --timeout |
10 |
Per-request timeout in seconds |
--json |
off | Output raw JSON instead of formatted table |
Stress Subcommand Options
| Flag | Default | Description |
|---|---|---|
--from |
10 |
Starting concurrency |
--to |
200 |
Target concurrency |
--ramp |
60 |
Ramp duration in seconds |
--hold |
30 |
Hold duration at target concurrency |
-t, --timeout |
10 |
Per-request timeout in seconds |
--json |
off | Output raw JSON |
Spike Subcommand Options
| Flag | Default | Description |
|---|---|---|
--baseline |
5 |
Baseline concurrency |
--peak |
500 |
Peak concurrency |
--pre-spike |
5 |
Pre-spike duration in seconds |
--spike-duration |
10 |
Spike duration in seconds |
--post-spike |
5 |
Post-spike duration in seconds |
-t, --timeout |
10 |
Per-request timeout in seconds |
--json |
off | Output raw JSON |
Global Options
| Flag | Default | Description |
|---|---|---|
-v, -vv, -vvv |
warn | Increase verbosity (INFO, DEBUG, TRACE) |
-q, --quiet |
off | Suppress all output |
--log-file <path> |
none | Write logs to file |
-V, --version |
off | Show version and exit |
Logs stream to stderr by default, keeping stdout clean for JSON output piping:
strobengine load http://localhost:8080/api/health -vv --json > results.json
Architecture
strobengine separates configuration, execution, and metrics into clean Rust modules, exposed to Python via PyO3:
config--TestConfigfor static load,LoadProfileenum for dynamic profiles (Constant, Ramp, Spike) with target concurrency interpolation.worker-- Async worker loops acceptingCancellationTokenfor graceful shutdown. Workers finish in-flight requests before exiting.metrics-- Lock-free atomic counters (AtomicUsize) track total requests and errors without contention. An aggregator task collects raw latencies, thencalculate_summarycomputes average, p95, and p99 percentiles in Rust at bare-metal speed.- Orchestrator -- Supervisor task ticks every 200ms, calculates target concurrency from the active profile curve, spawns/aborts workers dynamically.
The Python GIL is released entirely via py.detach() during test execution, allowing the full Tokio thread pool to run concurrently without throttling Python.
Testing
Run the full test suite with:
# Rust unit tests
cargo test
# Python unit tests
uv run pytest -v
How to Contribute
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-feature) - Make your changes
- Run formatting, linting, and tests:
cargo fmt cargo clippy --all-targets -- -D warnings cargo test uv run pytest -v
- Commit your changes following Conventional Commits
- Push to your branch and open a Pull Request
License
This project is licensed under the Apache License, Version 2.0. See LICENSE for the full text.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file strobengine-0.1.0.tar.gz.
File metadata
- Download URL: strobengine-0.1.0.tar.gz
- Upload date:
- Size: 43.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c25bcdff4ac4b4aabeb978030d6205d0084d7343af248912abe423baaa6da9f
|
|
| MD5 |
0a2e68f9dc268858824e58166a094271
|
|
| BLAKE2b-256 |
595f91292939dcbc49478408930889c0c3cac2c38d584c243b27676a7f58703d
|
Provenance
The following attestation bundles were made for strobengine-0.1.0.tar.gz:
Publisher:
publish.yml on strobe-ops/strobengine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strobengine-0.1.0.tar.gz -
Subject digest:
0c25bcdff4ac4b4aabeb978030d6205d0084d7343af248912abe423baaa6da9f - Sigstore transparency entry: 2228316786
- Sigstore integration time:
-
Permalink:
strobe-ops/strobengine@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/strobe-ops
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Trigger Event:
push
-
Statement type:
File details
Details for the file strobengine-0.1.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: strobengine-0.1.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 2.7 MB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25976cc03e3b45ba47420a93001e14717704ec9dc4403bb67145975be90a5102
|
|
| MD5 |
bcdf527425a35e29e49ccf098d965750
|
|
| BLAKE2b-256 |
df209017edbb8a7dc7c2e244fec7fbad65aa37506bb297750faa152cc569af70
|
Provenance
The following attestation bundles were made for strobengine-0.1.0-cp311-abi3-win_amd64.whl:
Publisher:
publish.yml on strobe-ops/strobengine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strobengine-0.1.0-cp311-abi3-win_amd64.whl -
Subject digest:
25976cc03e3b45ba47420a93001e14717704ec9dc4403bb67145975be90a5102 - Sigstore transparency entry: 2228318036
- Sigstore integration time:
-
Permalink:
strobe-ops/strobengine@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/strobe-ops
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Trigger Event:
push
-
Statement type:
File details
Details for the file strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.11+, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c537bde9e320473e39e9261f4832a477ad0104ce00af169ad26030d8929c6a4
|
|
| MD5 |
a5375ba60f4f35907f1af6e00ba37bf7
|
|
| BLAKE2b-256 |
f95852ba31242c7b008bddf3006578d54159c985accb49586c1d882052fc472f
|
Provenance
The following attestation bundles were made for strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl:
Publisher:
publish.yml on strobe-ops/strobengine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl -
Subject digest:
9c537bde9e320473e39e9261f4832a477ad0104ce00af169ad26030d8929c6a4 - Sigstore transparency entry: 2228318423
- Sigstore integration time:
-
Permalink:
strobe-ops/strobengine@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/strobe-ops
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Trigger Event:
push
-
Statement type:
File details
Details for the file strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.1 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72bce8bada2cf02bbdde4f49430f72f3362f97309260da5f377d7273aa3b24e4
|
|
| MD5 |
2a2fc412017c15f3ff1ef43f700d2324
|
|
| BLAKE2b-256 |
18b6a1b90afc0c6811d9a75f447aa62799a186cbb9963f8415ae14b16705e857
|
Provenance
The following attestation bundles were made for strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl:
Publisher:
publish.yml on strobe-ops/strobengine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl -
Subject digest:
72bce8bada2cf02bbdde4f49430f72f3362f97309260da5f377d7273aa3b24e4 - Sigstore transparency entry: 2228317503
- Sigstore integration time:
-
Permalink:
strobe-ops/strobengine@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/strobe-ops
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db2548834959ce2f01cef8e5c8a217c79284ae53 -
Trigger Event:
push
-
Statement type: