Skip to main content

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 -- TestConfig for static load, LoadProfile enum for dynamic profiles (Constant, Ramp, Spike) with target concurrency interpolation.
  • worker -- Async worker loops accepting CancellationToken for 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, then calculate_summary computes 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

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/my-feature)
  3. Make your changes
  4. Run formatting, linting, and tests:
    cargo fmt
    cargo clippy --all-targets -- -D warnings
    cargo test
    uv run pytest -v
    
  5. Commit your changes following Conventional Commits
  6. 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


Download files

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

Source Distribution

strobengine-0.1.0.tar.gz (43.9 kB view details)

Uploaded Source

Built Distributions

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

strobengine-0.1.0-cp311-abi3-win_amd64.whl (2.7 MB view details)

Uploaded CPython 3.11+Windows x86-64

strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl (3.4 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.38+ x86-64

strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl (3.1 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

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

Hashes for strobengine-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0c25bcdff4ac4b4aabeb978030d6205d0084d7343af248912abe423baaa6da9f
MD5 0a2e68f9dc268858824e58166a094271
BLAKE2b-256 595f91292939dcbc49478408930889c0c3cac2c38d584c243b27676a7f58703d

See more details on using hashes here.

Provenance

The following attestation bundles were made for strobengine-0.1.0.tar.gz:

Publisher: publish.yml on strobe-ops/strobengine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for strobengine-0.1.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 25976cc03e3b45ba47420a93001e14717704ec9dc4403bb67145975be90a5102
MD5 bcdf527425a35e29e49ccf098d965750
BLAKE2b-256 df209017edbb8a7dc7c2e244fec7fbad65aa37506bb297750faa152cc569af70

See more details on using hashes here.

Provenance

The following attestation bundles were made for strobengine-0.1.0-cp311-abi3-win_amd64.whl:

Publisher: publish.yml on strobe-ops/strobengine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for strobengine-0.1.0-cp311-abi3-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 9c537bde9e320473e39e9261f4832a477ad0104ce00af169ad26030d8929c6a4
MD5 a5375ba60f4f35907f1af6e00ba37bf7
BLAKE2b-256 f95852ba31242c7b008bddf3006578d54159c985accb49586c1d882052fc472f

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for strobengine-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 72bce8bada2cf02bbdde4f49430f72f3362f97309260da5f377d7273aa3b24e4
MD5 2a2fc412017c15f3ff1ef43f700d2324
BLAKE2b-256 18b6a1b90afc0c6811d9a75f447aa62799a186cbb9963f8415ae14b16705e857

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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