diff --git a/README.md b/README.md index f9af907..f049321 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ sendit completion | `--log-level` | | *(from config)* | Override log level: `debug` \| `info` \| `warn` \| `error` | | `--dry-run` | | `false` | Print config summary (targets, pacing, limits) and exit without sending traffic | | `--capture` | | `""` | Write a synthetic PCAP file while running; file is finalised on clean shutdown | +| `--duration` | | *(unlimited)* | Auto-stop after this wall-clock time (e.g. `5m`, `30s`); **required** when `pacing.mode: burst` | ### `probe` flags @@ -569,18 +570,20 @@ Controls how requests are spaced in time. | Field | Default | Description | |-------|---------|-------------| -| `mode` | `human` | `human` \| `rate_limited` \| `scheduled` | +| `mode` | `human` | `human` \| `rate_limited` \| `scheduled` \| `burst` | | `requests_per_minute` | `20` | Target RPM — used by `rate_limited` and `scheduled` modes only | | `jitter_factor` | `0.4` | Unused in `human` mode; reserved for future modes | | `min_delay_ms` | `800` | Minimum inter-request delay in `human` mode | | `max_delay_ms` | `8000` | Maximum inter-request delay in `human` mode | | `schedule` | `[]` | List of cron windows — required when `mode: scheduled` | +| `ramp_up_s` | `0` | Seconds to linearly ramp up to full speed — `burst` mode only; `0` = immediate | **Pacing modes:** - **`human`** — random delay per request uniformly sampled from `[min_delay_ms, max_delay_ms]`. `requests_per_minute` and `jitter_factor` are ignored in this mode. - **`rate_limited`** — token-bucket limiter at `requests_per_minute` plus a small random jitter after each token. - **`scheduled`** — cron expressions open active windows; within each window behaves like `rate_limited` at the window's own RPM. Dispatch is paused between windows. +- **`burst`** — fires requests as fast as worker slots allow with no inter-request delay. Intended for internal infrastructure testing. **Requires `--duration`** on `sendit start` — the engine refuses to run an unbounded burst session. ```yaml pacing: @@ -591,6 +594,13 @@ pacing: requests_per_minute: 40 ``` +```yaml +# Burst example — always pair with --duration when starting +pacing: + mode: burst + ramp_up_s: 30 # optional: ramp from slow to full speed over 30 s +``` + ### `limits` Concurrency and resource thresholds. diff --git a/config/burst.yaml b/config/burst.yaml new file mode 100644 index 0000000..d72d805 --- /dev/null +++ b/config/burst.yaml @@ -0,0 +1,76 @@ +# burst.yaml — example configuration for burst / load-test mode +# +# Burst mode fires at full worker concurrency with no inter-request delay. +# It is designed for internal load testing and staging validation, not for +# traffic to third-party services. +# +# REQUIRED: --duration must be set on the command line when pacing.mode is burst. +# +# sendit start --config config/burst.yaml --duration 2m +# +# The optional ramp_up_s field linearly increases from a throttled start to +# full speed over the specified number of seconds. This prevents a thundering +# herd on startup. Delay per request = 50ms × remaining_ramp_up_seconds, +# capped at 5 s. + +pacing: + mode: burst + ramp_up_s: 30 # ramp from ~1500 ms/req to zero over 30 s + +limits: + max_workers: 20 + max_browser_workers: 2 + cpu_threshold_pct: 80.0 + memory_threshold_mb: 2048 + +# Rate limits and backoff are intentionally relaxed for burst mode. +# The engine still respects them — remove or adjust as needed. +rate_limits: + default_rps: 50.0 + +backoff: + initial_ms: 500 + max_ms: 10000 + multiplier: 2.0 + max_attempts: 2 + +targets: + - url: "http://localhost:8080/health" + weight: 5 + type: http + http: + method: GET + timeout_s: 5 + + - url: "http://localhost:8080/api/v1/status" + weight: 3 + type: http + http: + method: GET + headers: + Accept: "application/json" + timeout_s: 5 + + - url: "http://localhost:8080/api/v1/submit" + weight: 2 + type: http + http: + method: POST + headers: + Content-Type: "application/json" + body: '{"probe":true}' + timeout_s: 10 + +output: + enabled: true + file: "burst-results.jsonl" + format: jsonl + append: false + +metrics: + enabled: true + prometheus_port: 9090 + +daemon: + log_level: info + log_format: text diff --git a/config/example.yaml b/config/example.yaml index c22e4ef..28f291e 100644 --- a/config/example.yaml +++ b/config/example.yaml @@ -1,5 +1,5 @@ pacing: - mode: human # human | rate_limited | scheduled + mode: human # human | rate_limited | scheduled | burst requests_per_minute: 20 jitter_factor: 0.4 min_delay_ms: 800 @@ -9,6 +9,8 @@ pacing: - cron: "0 9 * * 1-5" # weekdays at 09:00 duration_minutes: 30 requests_per_minute: 40 + # ramp_up_s is only used when mode: burst + # ramp_up_s: 30 # linearly ramp up over 30 s; 0 = immediate full speed limits: max_workers: 4 diff --git a/docs/content/docs/configuration.md b/docs/content/docs/configuration.md index f9236ad..7852d56 100644 --- a/docs/content/docs/configuration.md +++ b/docs/content/docs/configuration.md @@ -15,12 +15,13 @@ Controls how requests are spaced in time. See [Pacing Modes](../pacing/) for det | Field | Type | Default | Description | |---|---|---|---| -| `mode` | string | `human` | `human` \| `rate_limited` \| `scheduled` | +| `mode` | string | `human` | `human` \| `rate_limited` \| `scheduled` \| `burst` | | `requests_per_minute` | float | `20` | Target RPM — used by `rate_limited` and `scheduled` only | | `jitter_factor` | float | `0.4` | Reserved for future modes; unused in current pacing logic | | `min_delay_ms` | int | `800` | Minimum inter-request delay for `human` mode (ms) | | `max_delay_ms` | int | `8000` | Maximum inter-request delay for `human` mode (ms) | | `schedule` | list | `[]` | Cron windows — required when `mode: scheduled` | +| `ramp_up_s` | int | `0` | Seconds to linearly ramp up to full speed — `burst` mode only; `0` = immediate full speed | ## `limits`