Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ sendit completion <shell>
| `--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

Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand Down
76 changes: 76 additions & 0 deletions config/burst.yaml
Original file line number Diff line number Diff line change
@@ -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
4 changes: 3 additions & 1 deletion config/example.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion docs/content/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
Loading