strobengine 0.5.2__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {strobengine-0.5.2 → strobengine-0.6.0}/CHANGELOG.md +48 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/Cargo.lock +1 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/Cargo.toml +1 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/PKG-INFO +1 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/http3.md +10 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/reports.md +18 -2
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/roadmap.md +12 -12
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/sse.md +8 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/pyproject.toml +2 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/src/chaos.rs +33 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/config.rs +97 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/lib.rs +172 -143
- {strobengine-0.5.2 → strobengine-0.6.0}/src/metrics.rs +322 -33
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/grpc.rs +1 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/http.rs +3 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/http3.rs +2 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/sse.rs +6 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/websocket.rs +5 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/report/schema.rs +38 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/report/writer.rs +4 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/_strobengine.pyi +30 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/cli.py +135 -179
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/engine.py +8 -5
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporter.py +81 -1
- strobengine-0.5.2/src/strobengine/reporting/html_report.py → strobengine-0.6.0/src/strobengine/reporting/assets/report_template.html +0 -72
- strobengine-0.6.0/src/strobengine/reporting/html_report.py +71 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_grpc_e2e.py +4 -0
- strobengine-0.6.0/tests/e2e/test_latency_stats_e2e.py +52 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_sse_e2e.py +27 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_websocket_e2e.py +8 -4
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/test_reporter.py +7 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/test_reporting.py +28 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/uv.lock +1 -1
- {strobengine-0.5.2 → strobengine-0.6.0}/.dockerignore +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.github/workflows/ci.yml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.github/workflows/docker-release.yml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.github/workflows/publish-test.yml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.github/workflows/publish.yml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.gitignore +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.pre-commit-config.yaml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/.python-version +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/Dockerfile +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/LICENSE +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/Makefile +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/README.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/cliff.toml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/benchmarks.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/cli.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/dependencies.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/docker.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/grpc.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/http_methods.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/infrastructure.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/install.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/quickstart.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/release.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/table_of_contents.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/testing.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/docs/websockets.md +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/grpc.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/http3.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/http_methods.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/load_test.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/spike_test.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/sse.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/stress_test.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/examples/websocket.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/rust-toolchain.toml +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/scripts/release.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/logging.rs +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/progress.rs +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/grpc_parser.rs +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/grpc_reflection.rs +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/protocols/mod.rs +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/report/mod.rs +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/__init__.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/constants.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/py.typed +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporting/__init__.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporting/assets/chart.min.js +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporting/baseline.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporting/csv_report.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporting/junit_report.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/src/strobengine/reporting/markdown_report.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/__init__.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/conftest.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/__init__.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/conftest.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/mock_server.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_cli_interface.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_http3_e2e.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_http_scenarios.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_performance_sanity.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/e2e/test_persistence_e2e.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/fixtures/service.proto +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/test_cli.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/test_engine.py +0 -0
- {strobengine-0.5.2 → strobengine-0.6.0}/tests/test_logging.py +0 -0
|
@@ -4,6 +4,50 @@ All notable changes to `strobengine` will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.6.0] - 2026-09-09
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- *(pyi)* Add QuicMetrics, SseMetrics stubs and missing TestSummary properties
|
|
12
|
+
- *(metrics)* Use serde_json for to_json and add protocol fields to schema
|
|
13
|
+
- *(reporter)* Include protocol sections in JSON report artifact
|
|
14
|
+
- *(reporter)* Use correct chaos_faults structure in JSON artifact
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
- *(cli)* Document known CLI option duplication across subcommands
|
|
19
|
+
- Update documentation for QuicMetrics and SseMetrics
|
|
20
|
+
- Update roadmap and report schema for chaos fault tracking
|
|
21
|
+
- Update roadmap and report schema for extended latency statistics
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
- *(metrics)* Add QuicMetrics, SseMetrics, and connection latency to TestSummary
|
|
26
|
+
- *(aggregator)* Aggregate connection latency, QUIC, and SSE metrics in execute_test
|
|
27
|
+
- *(chaos)* Add ChaosMetrics struct and ChaosFault name helper
|
|
28
|
+
- *(metrics)* Add chaos fields to RequestMetric and TestSummary
|
|
29
|
+
- *(protocols)* Set chaos_fault on RequestMetric in all engines
|
|
30
|
+
- *(aggregator)* Collect chaos metrics in existing Tokio loop
|
|
31
|
+
- *(reports)* Include chaos metrics in JSON report artifact
|
|
32
|
+
- *(metrics)* Add latency jitter, p99.99, and histogram bucketing
|
|
33
|
+
- *(reporter)* Expose extended latency stats in terminal and artifact output
|
|
34
|
+
|
|
35
|
+
### Refactoring
|
|
36
|
+
|
|
37
|
+
- *(lib)* Extract spawn_worker helper from execute_test
|
|
38
|
+
- *(config)* Add protocol sub-structs and for_protocol_detection
|
|
39
|
+
- *(lib)* Use for_protocol_detection in run_load_profiles
|
|
40
|
+
- *(cli)* Extract ExportOptions dataclass and deduplicate _output_results
|
|
41
|
+
- *(cli)* Replace 27-param _build_request_options with **kwargs
|
|
42
|
+
- *(reporting)* Extract inline HTML template to separate file
|
|
43
|
+
- *(engine)* Replace nested ternary with dictionary WsMode mapping
|
|
44
|
+
|
|
45
|
+
### Testing
|
|
46
|
+
|
|
47
|
+
- *(report)* Update TestSummary test fixture for new metric fields
|
|
48
|
+
- *(e2e)* Add test for SSE metrics JSON export
|
|
49
|
+
- *(e2e)* Add chaos fault tracking verification tests
|
|
50
|
+
- *(e2e)* Add latency stats JSON and terminal output E2E tests
|
|
7
51
|
## [0.5.2] - 2026-09-02
|
|
8
52
|
|
|
9
53
|
### Bug Fixes
|
|
@@ -13,6 +57,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
13
57
|
- *(reporter)* Replace hardcoded version string with dynamic resolution
|
|
14
58
|
- *(reporting)* Validate baseline artifact structure in compute_comparison
|
|
15
59
|
|
|
60
|
+
### Miscellaneous Tasks
|
|
61
|
+
|
|
62
|
+
- *(release)* Bump version to 0.5.2
|
|
63
|
+
|
|
16
64
|
### Refactoring
|
|
17
65
|
|
|
18
66
|
- *(lib)* Remove unnecessary clones on config.body, config.form, config.headers
|
|
@@ -123,7 +123,15 @@ The `--http3` flag enables HTTP/3 mode explicitly.
|
|
|
123
123
|
## Metrics
|
|
124
124
|
|
|
125
125
|
HTTP/3 load tests produce the same `TestSummary` metrics as HTTP, plus
|
|
126
|
-
QUIC
|
|
126
|
+
aggregated QUIC metrics in `TestSummary.quic`:
|
|
127
|
+
|
|
128
|
+
| Field | Description |
|
|
129
|
+
|-------|-------------|
|
|
130
|
+
| `zero_rtt_accepted_count` | Number of successful 0-RTT connections |
|
|
131
|
+
| `retransmissions` | Total QUIC packet retransmissions |
|
|
132
|
+
| `avg_handshake_ms` | Average QUIC handshake duration in milliseconds |
|
|
133
|
+
|
|
134
|
+
Per-iteration fields available in `RequestMetric`:
|
|
127
135
|
|
|
128
136
|
| Metric | Description |
|
|
129
137
|
|--------|-------------|
|
|
@@ -138,6 +146,7 @@ QUIC-specific fields:
|
|
|
138
146
|
| `max_latency_ms` | Maximum latency |
|
|
139
147
|
| `total_bytes_received` | Total bytes received |
|
|
140
148
|
| `status_codes` | Status code distribution (200=success, 0=network error) |
|
|
149
|
+
| `avg_connection_latency_us` | Average connection establishment latency in microseconds |
|
|
141
150
|
| `quic_handshake_us` | QUIC handshake duration (persistent sessions) |
|
|
142
151
|
| `quic_0rtt_used` | Whether 0-RTT was accepted (persistent sessions) |
|
|
143
152
|
| `quic_retransmits` | Packet retransmission count since last iteration |
|
|
@@ -40,8 +40,13 @@ These flags appear on all three subcommands (`load`, `stress`, `spike`):
|
|
|
40
40
|
| `cli_options` | `method`, `concurrency`, `timeout_secs`, `chaos`, `chaos_rate`, `body`, `headers` |
|
|
41
41
|
| `system_info` | `hostname`, `platform`, `version` |
|
|
42
42
|
| `summary` | `total_requests`, `successful_requests`, `failed_requests`, `rps`, `bytes_transferred` |
|
|
43
|
-
| `latency_percentiles` | `p50_us`, `p90_us`, `p95_us`, `p99_us`, `min_us`, `max_us`, `mean_us` |
|
|
43
|
+
| `latency_percentiles` | `p50_us`, `p90_us`, `p95_us`, `p99_us`, `p99_99_us`, `min_us`, `max_us`, `mean_us`, `std_dev_us` |
|
|
44
|
+
| `latency_histogram` | Bucket distribution (e.g., `"<1ms": 1240`, `"1-5ms": 750`, ...) |
|
|
44
45
|
| `error_breakdown` | Status code string → count (e.g., `"200": 950, "500": 50`) |
|
|
46
|
+
| `avg_connection_latency_us` | Average connection establishment latency in microseconds |
|
|
47
|
+
| `quic` | `zero_rtt_accepted_count`, `retransmissions`, `avg_handshake_ms` *(HTTP/3 only)* |
|
|
48
|
+
| `sse` | `total_events_received`, `avg_ttfb_ms` *(SSE only)* |
|
|
49
|
+
| `chaos_faults` | `injected_total`, `by_type` *(chaos-enabled runs only)* |
|
|
45
50
|
|
|
46
51
|
All latency values are stored in **microseconds**.
|
|
47
52
|
|
|
@@ -58,7 +63,18 @@ All latency values are stored in **microseconds**.
|
|
|
58
63
|
},
|
|
59
64
|
"summary": { "total_requests": 1500, "successful_requests": 1485, "failed_requests": 15, "rps": 50.0, "bytes_transferred": 524288 },
|
|
60
65
|
"latency_percentiles": { "p50_us": 1200.0, "p90_us": 3500.0, "p95_us": 5200.0, "p99_us": 9800.0, "min_us": 200.0, "max_us": 15000.0, "mean_us": 2800.0 },
|
|
61
|
-
"error_breakdown": { "200": 1485, "500": 15 }
|
|
66
|
+
"error_breakdown": { "200": 1485, "500": 15 },
|
|
67
|
+
"avg_connection_latency_us": 850.0,
|
|
68
|
+
"quic": null,
|
|
69
|
+
"sse": null,
|
|
70
|
+
"chaos_faults": {
|
|
71
|
+
"injected_total": 12,
|
|
72
|
+
"by_type": {
|
|
73
|
+
"ConnectionDrop": 5,
|
|
74
|
+
"LatencySpike": 4,
|
|
75
|
+
"CorruptedPayload": 3
|
|
76
|
+
}
|
|
77
|
+
}
|
|
62
78
|
}
|
|
63
79
|
```
|
|
64
80
|
|
|
@@ -87,18 +87,18 @@ This document outlines the planned trajectory and upcoming feature epics for **s
|
|
|
87
87
|
### Epic: Advanced Metrics & Observability
|
|
88
88
|
*Target Focus: Deep Performance Insights & System Monitoring*
|
|
89
89
|
|
|
90
|
-
- [
|
|
91
|
-
- [
|
|
92
|
-
- [
|
|
93
|
-
|
|
94
|
-
- [
|
|
95
|
-
- [
|
|
96
|
-
- [
|
|
97
|
-
|
|
98
|
-
- [
|
|
99
|
-
- [
|
|
100
|
-
- [
|
|
101
|
-
- [
|
|
90
|
+
- [x] **Aggregate Existing Protocol Metrics** `[v0.6.0]`
|
|
91
|
+
- [x] Forward `connection_latency_us`, `quic_*`, `sse_*` fields through aggregator to `TestSummary`
|
|
92
|
+
- [x] Add protocol-specific sections to JSON report artifact
|
|
93
|
+
|
|
94
|
+
- [x] **Chaos Fault Tracking** `[v0.6.0]`
|
|
95
|
+
- [x] Count injected faults by type (ConnectionDrop, LatencySpike, etc.)
|
|
96
|
+
- [x] Include fault breakdown in JSON report artifact
|
|
97
|
+
|
|
98
|
+
- [x] **Extended Latency Statistics** `[v0.6.0]`
|
|
99
|
+
- [x] Compute latency jitter (standard deviation)
|
|
100
|
+
- [x] Add p99.99 percentile
|
|
101
|
+
- [x] Add latency histogram buckets for distribution visualization
|
|
102
102
|
|
|
103
103
|
- [ ] **Client System Resource Monitoring** `[v0.7.0]`
|
|
104
104
|
- [ ] Track engine CPU %, memory (RSS), thread count during test
|
|
@@ -141,7 +141,14 @@ connection.
|
|
|
141
141
|
## Metrics
|
|
142
142
|
|
|
143
143
|
SSE load tests produce the same `TestSummary` metrics as HTTP, plus
|
|
144
|
-
SSE
|
|
144
|
+
aggregated SSE metrics in `TestSummary.sse`:
|
|
145
|
+
|
|
146
|
+
| Field | Description |
|
|
147
|
+
|-------|-------------|
|
|
148
|
+
| `total_events_received` | Total SSE events received across all iterations |
|
|
149
|
+
| `avg_ttfb_ms` | Average time to first event in milliseconds |
|
|
150
|
+
|
|
151
|
+
Per-iteration fields available in `RequestMetric`:
|
|
145
152
|
|
|
146
153
|
| Metric | Description |
|
|
147
154
|
|--------|-------------|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "strobengine"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
description = "A load testing framework with a Python UI and a bare-metal Rust engine core."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -31,6 +31,7 @@ features = ["pyo3/extension-module"]
|
|
|
31
31
|
module-name = "strobengine._strobengine"
|
|
32
32
|
python-packages = ["strobengine"]
|
|
33
33
|
python-source = "src"
|
|
34
|
+
include = ["src/strobengine/reporting/assets/*"]
|
|
34
35
|
|
|
35
36
|
[tool.uv]
|
|
36
37
|
cache-keys = [{ file = "pyproject.toml" }, { file = "src/**/*.rs" }, { file = "Cargo.toml" }, { file = "Cargo.lock" }]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
1
3
|
pub const DEFAULT_CHAOS_RATE: f32 = 0.1;
|
|
2
4
|
|
|
3
5
|
#[derive(Debug, Clone, Copy)]
|
|
@@ -8,6 +10,37 @@ pub enum ChaosFault {
|
|
|
8
10
|
ConnectionDrop,
|
|
9
11
|
}
|
|
10
12
|
|
|
13
|
+
impl ChaosFault {
|
|
14
|
+
pub fn name(&self) -> &'static str {
|
|
15
|
+
match self {
|
|
16
|
+
ChaosFault::LatencySpike { .. } => "LatencySpike",
|
|
17
|
+
ChaosFault::CorruptedPayload => "CorruptedPayload",
|
|
18
|
+
ChaosFault::MetadataCorruption => "MetadataCorruption",
|
|
19
|
+
ChaosFault::ConnectionDrop => "ConnectionDrop",
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
|
|
25
|
+
pub struct ChaosMetrics {
|
|
26
|
+
pub total_injected: u64,
|
|
27
|
+
pub faults_by_type: HashMap<String, u64>,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
impl ChaosMetrics {
|
|
31
|
+
pub fn new() -> Self {
|
|
32
|
+
Self::default()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub fn record_fault(&mut self, fault: &ChaosFault) {
|
|
36
|
+
self.total_injected += 1;
|
|
37
|
+
*self
|
|
38
|
+
.faults_by_type
|
|
39
|
+
.entry(fault.name().to_string())
|
|
40
|
+
.or_insert(0) += 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
11
44
|
#[derive(Debug, Clone, Copy, Default)]
|
|
12
45
|
pub struct ChaosEngine {
|
|
13
46
|
pub enabled: bool,
|
|
@@ -3,6 +3,57 @@ use std::time::Duration;
|
|
|
3
3
|
use crate::chaos::DEFAULT_CHAOS_RATE;
|
|
4
4
|
use pyo3::prelude::*;
|
|
5
5
|
|
|
6
|
+
/// WebSocket protocol options (internal, not exposed to Python).
|
|
7
|
+
#[derive(Debug, Clone, Default)]
|
|
8
|
+
#[allow(dead_code)]
|
|
9
|
+
pub(crate) struct WsOptions {
|
|
10
|
+
pub mode: WsMode,
|
|
11
|
+
pub payload: Option<String>,
|
|
12
|
+
pub persistent: bool,
|
|
13
|
+
pub keepalive_secs: Option<u64>,
|
|
14
|
+
pub max_messages: Option<u64>,
|
|
15
|
+
pub role: Option<String>,
|
|
16
|
+
pub publish_interval_ms: Option<u64>,
|
|
17
|
+
pub subscribers: Option<usize>,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// gRPC protocol options (internal, not exposed to Python).
|
|
21
|
+
#[derive(Debug, Clone, Default)]
|
|
22
|
+
#[allow(dead_code)]
|
|
23
|
+
pub(crate) struct GrpcOptions {
|
|
24
|
+
pub service: Option<String>,
|
|
25
|
+
pub method: Option<String>,
|
|
26
|
+
pub payload: Option<String>,
|
|
27
|
+
pub deadline_ms: Option<u64>,
|
|
28
|
+
pub proto_path: Option<String>,
|
|
29
|
+
pub use_reflection: bool,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// HTTP/3 + QUIC options (internal, not exposed to Python).
|
|
33
|
+
#[derive(Debug, Clone, Default)]
|
|
34
|
+
#[allow(dead_code)]
|
|
35
|
+
pub(crate) struct Http3Options {
|
|
36
|
+
pub enabled: bool,
|
|
37
|
+
pub zero_rtt: bool,
|
|
38
|
+
pub max_idle_timeout_ms: Option<u64>,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// SSE streaming options (internal, not exposed to Python).
|
|
42
|
+
#[derive(Debug, Clone, Default)]
|
|
43
|
+
#[allow(dead_code)]
|
|
44
|
+
pub(crate) struct SseOptions {
|
|
45
|
+
pub enabled: bool,
|
|
46
|
+
pub max_events: Option<u64>,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// Report output options (internal, not exposed to Python).
|
|
50
|
+
#[derive(Debug, Clone, Default)]
|
|
51
|
+
#[allow(dead_code)]
|
|
52
|
+
pub(crate) struct OutputOptions {
|
|
53
|
+
pub output_dir: Option<String>,
|
|
54
|
+
pub no_save: bool,
|
|
55
|
+
}
|
|
56
|
+
|
|
6
57
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
|
7
58
|
#[pyclass(from_py_object)]
|
|
8
59
|
pub enum WsMode {
|
|
@@ -208,6 +259,52 @@ impl TestConfig {
|
|
|
208
259
|
}
|
|
209
260
|
}
|
|
210
261
|
|
|
262
|
+
impl TestConfig {
|
|
263
|
+
/// Minimal config for protocol detection (used by `run_load_profiles`).
|
|
264
|
+
/// Replaces the 32-line positional call with a concise factory.
|
|
265
|
+
pub fn for_protocol_detection(
|
|
266
|
+
url: String,
|
|
267
|
+
concurrency: usize,
|
|
268
|
+
duration_secs: u64,
|
|
269
|
+
timeout_secs: u64,
|
|
270
|
+
) -> Self {
|
|
271
|
+
Self::new(
|
|
272
|
+
url,
|
|
273
|
+
concurrency,
|
|
274
|
+
duration_secs,
|
|
275
|
+
timeout_secs,
|
|
276
|
+
false,
|
|
277
|
+
DEFAULT_CHAOS_RATE,
|
|
278
|
+
false,
|
|
279
|
+
"GET",
|
|
280
|
+
None,
|
|
281
|
+
None,
|
|
282
|
+
None,
|
|
283
|
+
WsMode::Handshake,
|
|
284
|
+
None,
|
|
285
|
+
None,
|
|
286
|
+
None,
|
|
287
|
+
None,
|
|
288
|
+
None,
|
|
289
|
+
None,
|
|
290
|
+
false,
|
|
291
|
+
false,
|
|
292
|
+
None,
|
|
293
|
+
None,
|
|
294
|
+
None,
|
|
295
|
+
None,
|
|
296
|
+
None,
|
|
297
|
+
false,
|
|
298
|
+
false,
|
|
299
|
+
None,
|
|
300
|
+
false,
|
|
301
|
+
None,
|
|
302
|
+
None,
|
|
303
|
+
false,
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
211
308
|
#[derive(Debug, Clone)]
|
|
212
309
|
#[pyclass(from_py_object)]
|
|
213
310
|
pub enum LoadProfile {
|