You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c4f2d23
Browse filesBrowse the repository at this point in the historyBrowse files
Generate audit and saga load against a ServiceControl.Audit instance (#5969)
* Add direct audit-queue writer and saga episode generation to the testing tool
Extends the testing tool to drive ServiceControl.Audit ingestion, not just
error ingestion. The new writer sends audit envelopes straight to the audit
queue, including whole saga episodes (New/Updated/Completed messages plus
their snapshots) linked via InvokedSagas/SagaStateChange headers so the
audit instance can resolve saga history and drill-through.
Also wires audit instances in the AppHost to the same SQL Server/PostgreSQL
backend as the primary via EF persistence, with ingestion tuning, OTel
export and custom-check reporting to the primary, and extends the Grafana
dashboard and docs to cover the new audit load paths.
* Bump Aspire to 13.6.1 and default audit instances to 1
Updates Aspire.Hosting.* packages and the AppHost SDK to 13.6.1, enables
the CLI bundle, and adds appsettings.json for logging configuration.
Also changes the default audit-instances option from 0 to 1 so audit
load is exercised out of the box.
* Fix audit instance creation & remove warning
* Default audit to 1 instance, change dashboard calc
* Pin pacakge with CVE
* retry folder delete to avoid locking problem on windows ci builds
* Add cancellation support
* Update test
---------
Co-authored-by: Rhys Bevilaqua <rhys.bevilaqua@particular.net>
Copy file name to clipboardExpand all lines: tools/testing-tool/README.md
+27-4Lines changed: 27 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ A stateless, horizontally-scalable .NET 10 service that generates error load and
4
4
scenarios against a test ServiceControl instance to validate its error-ingestion performance, with
5
5
OpenTelemetry observability and a simple web UI for manual scenario control.
6
6
7
-
The tool targets the error ingestion path only — audit testing is out of scope.
7
+
The tool drives both ingestion paths: failed messages into the primary ServiceControl instance, and audited messages and saga snapshots into a ServiceControl.Audit instance.
8
8
9
9
## What it does
10
10
@@ -73,6 +73,28 @@ failed message and groups it like the equivalent handler failure. Control via:
73
73
-`POST /api/bypass/stop`
74
74
-`GET /api/bypass/status`
75
75
76
+
### Direct audit-queue writer
77
+
78
+
The audit-queue counterpart of the bypass writer. It writes audit envelopes straight to the ServiceControl.Audit instance's audit queue, so audit ingestion can be loaded without any endpoint ever processing a message. Control via:
Most claims emit one processed-message envelope carrying the headers a real endpoint would have stamped: `NServiceBus.ProcessingEndpoint`, the host ids, and `TimeSent`, `ProcessingStarted` and `ProcessingEnded` spread so delivery, processing and critical times are not zero. They rotate across a pool of simulated endpoints, message types and conversations.
85
+
86
+
A share of claims instead emit a whole **saga episode**: the three messages that drove one saga through New, Updated and Completed, each followed by the snapshot it produced. The episode is written by a single worker so the phases reach the queue in order, and the pieces are linked the way a real deployment links them:
87
+
88
+
- each driving message carries `NServiceBus.InvokedSagas` (`SagaType:SagaId`) and `ServiceControl.SagaStateChange` (`SagaId:New|Updated|Completed`), which is the only thing that lets the audit instance attach saga information to an audited message
89
+
- each snapshot's `Initiator.InitiatingMessageId` is the id of the message directly before it, so drill-through from the saga view resolves to a real audited message
90
+
- the snapshot body is written in exact CLR casing, because ServiceControl deserializes it with a source-generated, case-sensitive context, and its `EnclosedMessageTypes` header is the bare unqualified type name, which is what the audit instance compares against to route a message to its saga branch
91
+
92
+
`sagaSnapshotRatio` is saga snapshots per processed message; the default `0.2` emits two saga snapshots for every ten processed messages. `0` disables saga episodes.
93
+
94
+
Audit ingestion needs a ServiceControl.Audit instance on SQL Server or PostgreSQL, so pair `--audit-instances` with `--persistence:PostgreSql` or `--persistence:SqlServer`. Under `--persistence:RavenDb` the audit instance runs on RavenDB and the EF path is not exercised.
95
+
96
+
The testing tool's own endpoint also audits its successfully handled load messages to the same queue, which is what makes its installers create the queue before the writer first sends into it.
97
+
76
98
### Release-test scenario presets
77
99
78
100
The tool ships with presets mapped from [docs/testing-scenarios.md](/docs/testing-scenarios.md) so
@@ -162,11 +184,11 @@ separator) or `--name:value` (colon separator):
162
184
163
185
| Flag | Default | Values | Description |
164
186
|---|---|---|---|
165
-
|`--persistence`|`RavenDb`|`RavenDb`, `SqlServer`, `PostgreSql`| Persistence backend for the ServiceControl error instance |
187
+
|`--persistence`|`RavenDb`|`RavenDb`, `SqlServer`, `PostgreSql`| Persistence backend for the ServiceControl error instance and for the audit instances |
166
188
|`--transport`|`RabbitMq`|`RabbitMq`, `SqlServer`| Transport shared by ServiceControl and the testing tool. `SqlServer` reuses the persistence SQL Server container with a separate `Transport` database |
167
189
|`--tag`|*(none — uses the current build's image)*| any image tag, e.g. `pr-1234` or `6.3.1`| Override the ServiceControl container image tag (useful for testing PR-based prereleases) |
168
190
|`--error-ingestion-scale-unit`|`0`| non-negative integer | Number of additional error-ingestion-only scale-out instances to spin up alongside the primary error instance (each runs with `--error-ingestion-only`) |
169
-
|`--audit-instances`|`0`| non-negative integer | Number of ServiceControl audit instances to add |
191
+
|`--audit-instances`|`1`| non-negative integer | Number of ServiceControl.Audit instances to add. They take the same `--persistence` backend, report custom checks to the primary and export OTel to the collector|
170
192
171
193
The Aspire dashboard provides allocated ports for each service. The testing tool automatically
172
194
connects to ServiceControl via the platform's transport and REST API URL, and sends its OTLP
@@ -242,7 +264,8 @@ All configuration is via environment variables (no files, no database). Settings
242
264
|`TestingTool__CustomCheckInterval`|`00:00:30`| Default interval for the custom-check-failures job |
243
265
|`TestingTool__CustomCheckHost`|`ServiceControl`|`Host` field on injected custom-check reports |
244
266
|`TestingTool__CustomCheckFailureProbability`|`0.4`| Probability (0–1) a given check is reported failed each cycle |
245
-
|`TestingTool__AuditQueueName`|`audit`| NServiceBus audit queue for processed messages |
267
+
|`TestingTool__AuditQueueName`|`audit`| NServiceBus audit queue the ServiceControl.Audit instance drains |
268
+
|`TestingTool__AuditSagaSnapshotRatio`|`0.2`| Default saga snapshots per processed message for the audit-queue writer |
246
269
|`TestingTool__MonitoringQueueName`|`Particular.Monitoring`| ServiceControl monitoring instance queue that endpoint metrics are sent to |
0 commit comments