-
Notifications
You must be signed in to change notification settings - Fork 1
Integration ServiceBus Extension
The Kronikol.Extensions.ServiceBus package adds Azure Service Bus messaging operation tracking to your test diagrams. Instead of opaque AMQP traffic, your sequence diagrams show classified operations like Send → orders-queue or Receive ← notifications-topic.
Using a shared library or abstraction layer? If your code doesn't use the
ServiceBusClientSDK directly — e.g. it goes through MassTransit, NServiceBus, a shared messaging library, or a custom abstraction — see the MassTransit Extension or Tracking Custom Dependencies for alternative approaches includingMessageTrackerandTrackingProxy<T>.
The Azure Service Bus SDK (Azure.Messaging.ServiceBus) uses AMQP by default, which does not go through an HttpMessageHandler pipeline. This extension uses a wrapper/decorator pattern instead — TrackingServiceBusClient wraps the real ServiceBusClient and returns tracked senders (TrackingServiceBusSender) and receivers (TrackingServiceBusReceiver) that intercept every operation and log it to RequestResponseLogger.
Because it logs to the same RequestResponseLogger as the standard TestTrackingMessageHandler, Service Bus operations appear alongside your HTTP API calls in the same sequence diagram — showing the complete flow from test → API → Service Bus.
Messaging operations (Send, Receive, Schedule, Peek) are tagged with MetaType.Event for blue async-messaging rendering in PlantUML diagrams.
dotnet add package Kronikol.Extensions.ServiceBusThe extension supports three verbosity levels that control how much detail appears in the diagrams:
| Level | Label shown | URI shown | Message body |
|---|---|---|---|
| Raw | Enum name (Send, SendBatch) |
servicebus://{queue} |
Included |
| Detailed | Operation with arrows (Send → orders-queue, Receive ← orders-queue) |
servicebus://{queue} or servicebus://{topic}/{subscription}
|
Included |
| Summarised | Simple name (Send, Receive, Complete) |
servicebus://{queue}/ |
None |
The default is Detailed.
| Operation | Raw | Detailed | Summarised |
|---|---|---|---|
| Send a message | Send |
Send → orders-queue |
Send |
| Send a batch (5 messages) | SendBatch |
Send (×5) → orders-queue |
Send |
| Schedule a message | Schedule |
Schedule → orders-queue |
Schedule |
| Receive a message | Receive |
Receive ← orders-queue |
Receive |
| Receive a batch (10 messages) | ReceiveBatch |
Receive (×10) ← orders-queue |
Receive |
| Peek | Peek |
Peek ← orders-queue |
Peek |
| Complete | Complete |
Complete |
Complete |
| Abandon | Abandon |
Abandon |
Abandon |
| Dead-letter | DeadLetter |
DeadLetter |
DeadLetter |
| Defer | Defer |
Defer |
Defer |
| Renew lock | RenewMessageLock |
RenewLock |
RenewLock |
The classifier recognises these Service Bus operations:
| Operation | Method Name |
|---|---|
Send |
SendMessageAsync |
SendBatch |
SendMessagesAsync |
Schedule |
ScheduleMessageAsync, ScheduleMessagesAsync
|
CancelSchedule |
CancelScheduledMessageAsync, CancelScheduledMessagesAsync
|
Receive |
ReceiveMessageAsync |
ReceiveBatch |
ReceiveMessagesAsync |
Peek |
PeekMessageAsync, PeekMessagesAsync
|
Complete |
CompleteMessageAsync |
Abandon |
AbandonMessageAsync |
DeadLetter |
DeadLetterMessageAsync |
Defer |
DeferMessageAsync |
RenewMessageLock |
RenewMessageLockAsync |
RenewSessionLock |
RenewSessionLockAsync |
GetSessionState |
GetSessionStateAsync |
SetSessionState |
SetSessionStateAsync |
StartProcessing |
StartProcessingAsync |
StopProcessing |
StopProcessingAsync |
v2.27.14+ Use the built-in DI extension method. It automatically resolves
IHttpContextAccessorfrom DI and handles the dual-resolution test identity pattern.
// In your test's ConfigureTestServices:
services.AddServiceBusTestTracking(options =>
{
options.ServiceName = "ServiceBus";
options.CallerName = "OrdersApi";
options.Verbosity = ServiceBusTrackingVerbosity.Detailed;
options.CurrentTestInfoFetcher = CurrentTestInfo.Fetcher;
});This uses DecorateAll<ServiceBusClient> internally — it finds all existing ServiceBusClient registrations, replaces each with a TrackingServiceBusClient (which inherits from ServiceBusClient), and preserves the original service lifetime. No-op if no ServiceBusClient registrations exist. No changes to production code required.
v2.27.14 Breaking Change:
TrackingServiceBusClientnow inherits fromServiceBusClient(previously a composition wrapper). TheInnerproperty and existing API remain available, but the service is now registered asServiceBusClient(not asTrackingServiceBusClient). Code that resolvesServiceBusClientfrom DI will receive the tracking subclass transparently.
Create a TrackingServiceBusClient that wraps your existing ServiceBusClient:
var trackingOptions = new ServiceBusTrackingOptions
{
ServiceName = "ServiceBus",
CallerName = "My API",
Verbosity = ServiceBusTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
};
var realClient = new ServiceBusClient("your-connection-string");
var trackedClient = new TrackingServiceBusClient(realClient, trackingOptions);
// Use trackedClient instead of realClient
var sender = trackedClient.CreateSender("orders-queue");
await sender.SendMessageAsync(new ServiceBusMessage("hello"));
var receiver = trackedClient.CreateReceiver("orders-queue");
var message = await receiver.ReceiveMessageAsync();Use AddServiceBusTestTracking() with a pre-constructed options object:
// In your test WebApplicationFactory or DI setup:
services.AddServiceBusTestTracking(new ServiceBusTrackingOptions
{
ServiceName = "ServiceBus",
CallerName = "OrdersApi",
Verbosity = ServiceBusTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
});This overload is preserved for backward compatibility and uses the same DecorateAll<ServiceBusClient> pattern internally.
| Property | Type | Default | Description |
|---|---|---|---|
ServiceName |
string |
"ServiceBus" |
Display name in diagrams for the Service Bus |
CallerName |
string |
"Caller" |
Calling service name in diagrams |
Verbosity |
ServiceBusTrackingVerbosity |
Detailed |
Verbosity level (Raw, Detailed, Summarised) |
CurrentTestInfoFetcher |
Func<(string Name, string Id)>? |
null |
Required: provides test context for log correlation |
CurrentStepTypeFetcher |
Func<string?>? |
null |
Optional — returns the current BDD step type (Given/When/Then) |
HttpContextAccessor |
IHttpContextAccessor? |
null |
Optional — enables dual-resolution of test identity from HTTP headers. Auto-resolved by DI extensions (v2.26.3+). See HTTP Tracking Setup#Dual-Resolution Test Identity (v2.23.0+) |
v2.23.0+ Dual-Resolution:
ServiceBusTrackeraccepts an optionalIHttpContextAccessor? httpContextAccessorconstructor parameter for resolving test identity from HTTP request headers when running inside the SUT's request pipeline. v2.26.3+: SetHttpContextAccessoronServiceBusTrackingOptionsinstead — the tracker reads it automatically. DI extensions likeAddServiceBusTestTracking()auto-resolve it from the service provider. See HTTP Tracking Setup#Dual-Resolution Test Identity (v2.23.0+) for details. |SetupVerbosity|ServiceBusTrackingVerbosity?|null| Verbosity override for the Setup phase. See Phase-Aware Tracking | |ActionVerbosity|ServiceBusTrackingVerbosity?|null| Verbosity override for the Action phase. See Phase-Aware Tracking | |TrackDuringSetup|bool|true| Whenfalse, tracking is suppressed during Setup. See Phase-Aware Tracking | |TrackDuringAction|bool|true| Whenfalse, tracking is suppressed during Action. See Phase-Aware Tracking | |PropagateTestIdentity|bool|true| Whentrue, senders injectkronikol-test-name/kronikol-test-idintoApplicationPropertiesand receivers extract them to establishTestIdentityScope. See Background Thread Correlation#Solution 1b: Automatic Message Header Propagation (v2.34.0+) | |AutoCorrelateOnConsume|bool|true| Whentrue, received messages auto-populateTestCorrelationStorefor parallel-safe background thread correlation |
Because ServiceBusSender and ServiceBusReceiver are sealed classes in the Azure SDK, this extension uses wrapper classes rather than DelegatingHandler or DispatchProxy:
ServiceBusClient (real)
└── TrackingServiceBusClient (wrapper)
├── CreateSender() → TrackingServiceBusSender (wraps ServiceBusSender)
└── CreateReceiver() → TrackingServiceBusReceiver (wraps ServiceBusReceiver)
Each wrapper delegates all calls to the real instance and adds tracking before/after each operation. The Inner property on each wrapper provides escape-hatch access to the original SDK object.
TrackingServiceBusSender tracks:
-
SendMessageAsync— logs message body (at Raw/Detailed) -
SendMessagesAsync— logs count -
ScheduleMessageAsync— logs message body, response includes sequence number -
CancelScheduledMessageAsync— logs sequence number
Untracked (pass-through): CreateMessageBatchAsync, CloseAsync
TrackingServiceBusReceiver tracks:
-
ReceiveMessageAsync— logs received message body in response -
ReceiveMessagesAsync— logs count in response -
PeekMessageAsync— logs peeked message body in response CompleteMessageAsyncAbandonMessageAsync-
DeadLetterMessageAsync— logs dead-letter reason (at Raw/Detailed) DeferMessageAsyncRenewMessageLockAsync
Untracked (pass-through): CloseAsync
ServiceBusTracker implements ITrackingComponent and auto-registers with TrackingComponentRegistry on construction. If the tracker is registered but never processes any operations, a passive warning appears in the console output and (when DiagnosticMode=true) in the HTML diagnostic report. This never throws or fails tests — see Diagnostics and Debugging for details.
When your application processes Service Bus messages on background threads (e.g. inside a ServiceBusProcessor or hosted service), the test framework's TestContext is unavailable. The extension solves this automatically via ApplicationProperties propagation.
-
Sender side:
TrackingServiceBusSenderinjectskronikol-test-nameandkronikol-test-idinto each message'sApplicationPropertiesbefore sending. -
Receiver side:
TrackingServiceBusReceiverreads these properties from each received message and callsTestIdentityScope.SetFromMessage(). - All subsequent tracking within the message handler resolves to the originating test.
var options = new ServiceBusTrackingOptions
{
PropagateTestIdentity = false,
// ...
};See Background Thread Correlation#Solution 1b: Automatic Message Header Propagation (v2.34.0+) for the full architecture overview.
Getting Started
Common Tasks
Integration Guides
- Integration xUnit3
- Integration xUnit2
- Integration NUnit
- Integration MSTest
- Integration TUnit
- Integration BDDfy xUnit3
- Integration LightBDD xUnit2
- Integration LightBDD xUnit3
- Integration LightBDD TUnit
- Integration ReqNRoll xUnit2
- Integration ReqNRoll xUnit3
- Integration ReqNRoll TUnit
Extensions
- Integration AtlasDataApi Extension
- Integration BigQuery Extension
- Integration Bigtable Extension
- Integration BlobStorage Extension
- Integration ClickHouse Extension
- Integration CloudStorage Extension
- Integration CosmosDB Extension
- Integration Dapper Extension
- Integration DynamoDB Extension
- Integration EF Core Relational Extension
- Integration Elasticsearch Extension
- Integration EventBridge Extension
- Integration EventHubs Extension
- Integration Grpc Extension
- Integration Kafka Extension
- Integration MassTransit Extension
- Integration MongoDB Extension
- Integration MySqlConnector Extension
- Integration Npgsql Extension
- Integration Oracle Extension
- Integration PubSub Extension
- Integration Redis Extension
- Integration S3 Extension
- Integration ServiceBus Extension
- Integration SNS Extension
- Integration Spanner Extension
- Integration SqlClient Extension
- Integration Sqlite Extension
- Integration SQS Extension
- Integration StorageQueues Extension
- Integration OpenTelemetry Extension
- Integration DispatchProxy Extension
- Integration MediatR Extension
- Integration PlantUML IKVM
Configuration
- Tracking Dependencies
- Tracking Custom Dependencies
- HTTP Tracking Setup
- Report Configuration
- Diagram Customisation
- Phase-Aware Tracking
- Content Formatting
- PlantUML Server Configuration
Features
- Generated Reports
- Search Syntax
- Component Diagrams
- PlantUML Browser Rendering
- Inline SVG Rendering
- Internal Flow Tracking
- Tags and Attributes
- Excluding Requests
- Excluded Headers
- Multi-Host Test Architectures
- Event-Driven Architecture Testing
- Service Bus Tracking Patterns
- Background Thread Correlation
- Parallel-Safe Background Correlation
- Event & Message Tracking
- Assertion Tracking
- Step Tracking
- Tabular Attributes
- Large Response and Diagram Handling
- Diagnostics and Debugging
- CI Summary Integration
- CI Artifact Upload
- Merging Parallel Reports
Reference