-
Notifications
You must be signed in to change notification settings - Fork 1
Integration BlobStorage Extension
The Kronikol.Extensions.BlobStorage package adds Azure Blob Storage operation tracking to your test diagrams. Instead of showing raw HTTP requests like PUT /mycontainer/myblob.txt?comp=blocklist, your sequence diagrams show classified operations like Upload: /mycontainer/myblob.txt or ListBlobs: /mycontainer.
Using a shared library or abstraction layer? If your code doesn't use the Blob Storage SDK directly — e.g. it goes through a shared storage library, wrapper, or custom abstraction — this extension won't be able to intercept the underlying calls. See Tracking Custom Dependencies for alternative approaches including
RequestResponseLogger.LogPair(),TrackingProxy<T>, andMessageTracker.
The Azure Blob Storage SDK translates all operations into HTTP requests to the Azure Storage REST API. BlobTrackingMessageHandler is a DelegatingHandler that intercepts these HTTP requests, classifies each one into a Blob operation (Upload, Download, Delete, ListBlobs, etc.) using the HTTP method, URL path, and query parameters, then logs it to RequestResponseLogger with a human-readable label.
Because it logs to the same RequestResponseLogger as the standard TestTrackingMessageHandler, Blob Storage operations appear alongside your HTTP API calls in the same sequence diagram — showing the complete flow from test → API → Blob Storage.
dotnet add package Kronikol.Extensions.BlobStorageThe extension supports three verbosity levels that control how much detail appears in the diagrams:
| Level | Method shown | URI shown | Headers | Request body | Response body |
|---|---|---|---|---|---|
| Raw | HTTP method (PUT, GET, etc.) |
Full URI with query parameters | All except excluded set | Full content | Full content |
| Detailed | Classified operation (Upload) |
Clean path without query params (/mycontainer/myblob.txt) |
Filtered (noisy Storage headers excluded) | Full content | Full content |
| Summarised | Classified operation (Upload) |
Clean path (/mycontainer/myblob.txt) |
None | None | None |
The default is Detailed.
| Operation | Raw | Detailed | Summarised |
|---|---|---|---|
| Upload blob | PUT: /mycontainer/myblob.txt |
Upload: /mycontainer/myblob.txt |
Upload: /mycontainer/myblob.txt |
| Download blob | GET: /mycontainer/myblob.txt |
Download: /mycontainer/myblob.txt |
Download: /mycontainer/myblob.txt |
| Delete blob | DELETE: /mycontainer/myblob.txt |
Delete: /mycontainer/myblob.txt |
Delete: /mycontainer/myblob.txt |
| Get blob properties | HEAD: /mycontainer/myblob.txt |
GetProperties: /mycontainer/myblob.txt |
GetProperties: /mycontainer/myblob.txt |
| List blobs | GET: /mycontainer?restype=container&comp=list |
ListBlobs: /mycontainer |
ListBlobs: /mycontainer |
| Create container | PUT: /mycontainer?restype=container |
CreateContainer: /mycontainer |
CreateContainer: /mycontainer |
| Set metadata | PUT: /mycontainer/myblob.txt?comp=metadata |
SetMetadata: /mycontainer/myblob.txt |
SetMetadata: /mycontainer/myblob.txt |
| Put block list | PUT: /mycontainer/myblob.txt?comp=blocklist |
PutBlockList: /mycontainer/myblob.txt |
PutBlockList: /mycontainer/myblob.txt |
| SDK metadata | GET: /mycontainer?restype=container |
Other: /mycontainer |
(skipped) |
The classifier recognises these Blob Storage operations from the SDK's HTTP traffic:
| Operation | HTTP Pattern |
|---|---|
Upload |
PUT /{container}/{blob} (no comp parameter) |
Download |
GET /{container}/{blob} (no comp parameter) |
Delete |
DELETE /{container}/{blob} |
GetProperties |
HEAD /{container}/{blob} |
SetMetadata |
PUT /{container}/{blob}?comp=metadata |
GetMetadata |
GET /{container}/{blob}?comp=metadata |
Copy |
PUT /{container}/{blob}?comp=copy |
PutBlock |
PUT /{container}/{blob}?comp=block |
PutBlockList |
PUT /{container}/{blob}?comp=blocklist |
Lease |
PUT /{container}/{blob}?comp=lease |
CreateContainer |
PUT /{container}?restype=container |
DeleteContainer |
DELETE /{container}?restype=container |
ListBlobs |
GET /{container}?restype=container&comp=list |
Other |
Unrecognised or SDK metadata requests |
In Summarised mode, Other operations are silently skipped.
var trackingOptions = new BlobTrackingMessageHandlerOptions
{
ServiceName = "BlobStorage",
CallerName = "My API",
Verbosity = BlobTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
};
var clientOptions = new BlobClientOptions();
clientOptions.WithTestTracking(trackingOptions);
var client = new BlobServiceClient(connectionString, clientOptions);WithTestTracking sets the Transport property on BlobClientOptions to route all HTTP requests through the tracking handler.
If you need more control over the HTTP pipeline:
var trackingOptions = new BlobTrackingMessageHandlerOptions
{
ServiceName = "BlobStorage",
CallerName = "My API",
Verbosity = BlobTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
};
var trackingHandler = new BlobTrackingMessageHandler(trackingOptions);
var httpClient = new HttpClient(trackingHandler);
var transport = new Azure.Core.Pipeline.HttpClientTransport(httpClient);
var clientOptions = new BlobClientOptions
{
Transport = transport
};
var client = new BlobServiceClient(connectionString, clientOptions);builder.ConfigureTestServices(services =>
{
// Replace BlobServiceClient with one that uses the tracking transport
services.AddSingleton(sp =>
{
var trackingOptions = new BlobTrackingMessageHandlerOptions
{
ServiceName = "BlobStorage",
CallerName = "My API",
Verbosity = BlobTrackingVerbosity.Detailed,
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
};
var clientOptions = new BlobClientOptions();
clientOptions.WithTestTracking(trackingOptions);
return new BlobServiceClient("UseDevelopmentStorage=true", clientOptions);
});
});| Property | Type | Default | Description |
|---|---|---|---|
ServiceName |
string |
"BlobStorage" |
The participant name shown in the diagram for the Blob Storage service |
CallerName |
string |
"Caller" |
The participant name shown for the service making Blob Storage calls |
Verbosity |
BlobTrackingVerbosity |
Detailed |
Controls how much detail appears in the diagram (Raw, Detailed, Summarised) |
CurrentTestInfoFetcher |
Func<(string Name, string Id)>? |
null |
Returns the current test's name and ID. Required — if null, requests are forwarded but not logged |
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+) |
ExcludedHeaders |
HashSet<string> |
See below | Headers to exclude from diagrams in Raw/Detailed mode |
SetupVerbosity |
BlobTrackingVerbosity? |
null |
Verbosity override for the Setup phase. See Phase-Aware Tracking |
ActionVerbosity |
BlobTrackingVerbosity? |
null |
Verbosity override for the Action phase. See Phase-Aware Tracking |
TrackDuringSetup |
bool |
true |
When false, tracking is suppressed during Setup. See Phase-Aware Tracking
|
TrackDuringAction |
bool |
true |
When false, tracking is suppressed during Action. See Phase-Aware Tracking
|
v2.23.0+ Dual-Resolution:
BlobTrackingMessageHandleraccepts an optionalIHttpContextAccessor? httpContextAccessorconstructor parameter for resolving test identity from HTTP request headers when running inside the SUT's request pipeline. v2.26.3+: SetHttpContextAccessoronBlobTrackingMessageHandlerOptionsinstead — the tracker reads it automatically. See HTTP Tracking Setup#Dual-Resolution Test Identity (v2.23.0+) for details.
The following Azure Storage headers are excluded by default (they add noise without diagnostic value):
Authorizationx-ms-datex-ms-versionx-ms-client-request-idx-ms-return-client-request-idUser-AgentCache-Control
Override ExcludedHeaders to customise:
new BlobTrackingMessageHandlerOptions
{
ExcludedHeaders = ["Authorization", "x-ms-date"] // Only exclude these two
}Every framework package provides a CurrentTestInfo static class with a Fetcher property. The syntax is identical regardless of framework - just ensure you have the correct using directive:
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher| Framework |
using directive |
|---|---|
| xUnit v3 | using Kronikol.xUnit3; |
| xUnit v2 | using Kronikol.xUnit2; |
| NUnit 4 | using Kronikol.NUnit4; |
| MSTest | using Kronikol.MSTest; |
| TUnit | using Kronikol.TUnit; |
| LightBDD | using Kronikol.LightBDD; |
| ReqNRoll | using Kronikol.ReqNRoll; |
| BDDfy | using Kronikol.BDDfy.xUnit3; |
public static BlobClientOptions WithTestTracking(
this BlobClientOptions options,
BlobTrackingMessageHandlerOptions trackingOptions,
HttpMessageHandler? innerHandler = null)Configures BlobClientOptions to use BlobTrackingMessageHandler. Sets options.Transport to an HttpClientTransport backed by an HttpClient wrapping the tracking handler. The optional innerHandler parameter sets the inner handler (defaults to HttpClientHandler).
BlobTrackingMessageHandler implements ITrackingComponent and auto-registers with TrackingComponentRegistry on construction. At report generation time, unused components are automatically detected and surfaced as console warnings and in the diagnostic report (when DiagnosticMode=true). This never throws or fails tests.
See Diagnostics and Debugging for full details on the TrackingComponentRegistry API.
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 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
Reference