-
Notifications
You must be signed in to change notification settings - Fork 1
HTTP Tracking Setup
HTTP tracking is the core mechanism that captures all HTTP traffic for diagram generation. There are two sides to track:
- Outgoing calls from the SUT — Calls your API makes to its downstream dependencies
- Incoming calls to the SUT — Calls your test makes to the API under test
Deprecation (v2.28.1):
CallingServiceNamehas been renamed toCallerNameacross all options classes. The old property still works but produces a compile warning. Update your code to useCallerName— the old name will be removed in a future major version.
This page covers the basic setup using
TrackDependenciesForDiagrams()and the options reference. If your project uses named clients, typed clients, existing DelegatingHandler chains, or other advancedHttpClientpatterns, see Tracking Dependencies for a step-by-step guide covering every common pattern.
Inside your WebApplicationFactory configuration, register tracking for outgoing calls from the SUT:
Simplified imports (v2.0.131+):
TrackDependenciesForDiagrams()andCreateTestTrackingClient()are now available directly from the coreKronikolnamespace. You can useusing Kronikol;instead of a framework-specific namespace — the core extensions accept the baseTestTrackingMessageHandlerOptionstype, so any framework-specific options class works.
builder.ConfigureServices(services =>
{
services.TrackDependenciesForDiagrams(
new XUnitTestTrackingMessageHandlerOptions
{
CallerName = "My API",
PortsToServiceNames =
{
{ 80, "My API" },
{ 5001, "Auth Service" },
{ 5002, "Payment Service" }
}
});
});This registers:
-
TestTrackingMessageHandlerOptionsas a singleton -
IHttpContextAccessorfor extracting tracking headers from incoming requests -
IHttpMessageHandlerBuilderFilterasTrackingHttpMessageHandlerBuilderFilter(automatically injects the trackingDelegatingHandlerinto everyHttpClientbuilt byIHttpClientFactory)
| Property | Type | Default | Description |
|---|---|---|---|
PortsToServiceNames |
Dictionary<int, string> |
{} |
Maps port numbers to human-readable service names for the diagram. When the SUT makes an HTTP call to localhost:5001, the diagram will show the target as the mapped name. Unmapped ports will appear as localhost_80, localhost_5001, etc. |
ClientNamesToServiceNames |
Dictionary<string, string> |
{} |
Maps IHttpClientFactory client names to human-readable service names. Useful when HTTP mocking makes port-based mapping unreliable. Pass the client name via the clientName constructor parameter: new TestTrackingMessageHandler(options, clientName: builder.Name). Resolution order: FixedNameForReceivingService > ClientNamesToServiceNames > PortsToServiceNames > localhost:port. |
FixedNameForReceivingService |
string? |
null |
If set, all requests handled by this handler are labelled with this fixed name (useful for the test-to-SUT client). |
CallerName |
string |
"Caller" |
The name shown in the diagram for the service making the call. |
HeadersToForward |
IEnumerable<string> |
[] |
Additional HTTP headers to forward from incoming requests to outgoing requests (propagated through the call chain). |
CurrentTestInfoFetcher |
Func<(string Name, string Id)>? |
null |
Delegate that returns the current test's name and unique ID. Each framework-specific options class sets this automatically. |
CurrentStepTypeFetcher |
Func<string?>? |
null |
Delegate that returns the current BDD step type (e.g. "GIVEN", "WHEN"). Used for automatic setup separation. Set automatically by BDDfy and ReqNRoll options classes. |
InternalFlowActivitySources |
string[]? |
null |
Additional ActivitySource names to capture for Internal Flow Tracking. The handler auto-starts a listener for well-known sources (ASP.NET Core, HttpClient, EF Core, etc.). Add your custom source names here to include them in internal flow diagrams. See Internal Flow Tracking#Span Granularity for the full list of well-known sources and granularity modes. |
TrackDuringSetup |
bool |
true |
When false, HTTP requests made during the Setup phase are not tracked. See Phase-Aware Tracking. |
TrackDuringAction |
bool |
true |
When false, HTTP requests made during the Action phase are not tracked. See Phase-Aware Tracking. |
ExcludedHosts |
IReadOnlyCollection<string> |
["override.com"] |
Host names to exclude from tracking. Requests to these hosts are forwarded without logging. Default includes override.com (ASP.NET Core TestServer's internal base address in WebApplicationFactory scenarios). Set to an empty collection to disable host-based filtering. |
HttpContextAccessor |
IHttpContextAccessor? |
null |
Optional — enables dual-resolution of test identity from HTTP headers. Auto-resolved by CreateTestTrackingClient() (v2.26.3+). See #Dual-Resolution Test Identity (v2.23.0+). |
ClientNamesToServiceNames uses a tiered resolution strategy (v3.0.23+):
- Exact match — The full client name is looked up as a dictionary key
-
EndsWith with boundary — If the client name (stripped of assembly qualification) ends with a key, and the preceding character is non-alphanumeric (e.g.
+,.,-), the match succeeds -
Contains (assembly-qualified names only) — For Refit v9 and other source generators that produce assembly-qualified client names (containing
,), a case-sensitiveContainscheck is used as a final fallback
The Contains fallback is restricted to assembly-qualified names to prevent false positives on simple names (e.g. key "Client" should not match "MyBetterClient").
For typed HttpClients registered via services.AddHttpClient<TClient>(), IHttpClientFactory uses the full type name as the client name. For example:
// Registration:
services.AddHttpClient<TenantHierarchyHttpClient>(o => o.BaseAddress = ...);
// In IHttpMessageHandlerBuilderFilter.Configure(), builder.Name = "TenantHierarchyHttpClient"
// So the dictionary key must be exactly "TenantHierarchyHttpClient":
ClientNamesToServiceNames =
{
{ "TenantHierarchyHttpClient", "Tenant Hierarchy Service" } // ✅ exact match
// { "TenantHierarchyService", "Tenant Hierarchy Service" } // ❌ won't match
}For named HttpClients registered via services.AddHttpClient("my-client"), the key is the string you passed.
Refit / source-generated clients (v3.0.21+): Refit and other source generators produce complex client names. For Refit v8-style names like Refit.Implementation.Generated+SomeModule+IIntelligenceAiApiClient, ends-with matching works (the + is a valid boundary). For Refit v9 assembly-qualified names like ...IntelligenceAiIIntelligenceAiApiClient, Data.Insights.Api, Version=1.0.0.0, ..., the contains fallback matches:
ClientNamesToServiceNames =
{
{ "IIntelligenceAiApiClient", "Intelligence AI" } // ✅ matches both Refit v8 (EndsWith) and v9 (Contains)
}Diagnostic tip (v2.28.12+): When
DiagnosticMode=true, the diagnostic report includes an Unmatched HTTP Client Names section that lists allclientNamevalues that didn't match anyClientNamesToServiceNameskey (neither exact nor ends-with), along with request counts. This makes misconfigured mappings immediately visible.
Framework-specific options classes (
XUnitTestTrackingMessageHandlerOptions,NUnitTestTrackingMessageHandlerOptions,BDDfyTestTrackingMessageHandlerOptions,LightBddTestTrackingMessageHandlerOptions,ReqNRollTestTrackingMessageHandlerOptions) extendTestTrackingMessageHandlerOptionsand auto-populateCurrentTestInfoFetcherfrom the framework's test context. Each framework package also provides aCurrentTestInfostatic class with aFetcherproperty — useCurrentTestInfo.Fetcherwhen you need to setCurrentTestInfoFetcheron extension options.
⚠️ Startup HTTP calls:XUnitTestTrackingMessageHandlerOptions(andXUnit2TestTrackingMessageHandlerOptions) setCurrentTestInfoFetcherto read from the test context. If your SUT makes HTTP calls during startup — e.g. hosted services fetching configuration, health checks, warm-up requests — the fetcher will execute when no test is active. As of v2.27.10,CurrentTestInfo.Fetcheris null-safe and returns("Unknown", "unknown")when the test context is unavailable. The tracking handler catches this and the startup call is either logged with "Unknown" identity or silently skipped — tests still pass and diagrams for actual tests are unaffected.If you want explicit control, use the base
TestTrackingMessageHandlerOptionswithCurrentTestInfo.Fetcher:services.TrackDependenciesForDiagrams(new TestTrackingMessageHandlerOptions { CallerName = "My API", PortsToServiceNames = { { 80, "My API" }, { 5001, "Auth Service" } }, CurrentTestInfoFetcher = CurrentTestInfo.Fetcher, });See also: Tracking Dependencies — Gotcha: HTTP Calls During HttpClient Construction for a related pitfall when HTTP calls are made during
HttpClientconstruction (not just app startup).
Not all dependencies use IHttpClientFactory. For dependencies with their own HTTP internals:
-
Azure Cosmos DB SDK — Uses its own
HttpClientinternally. UseKronikol.Extensions.CosmosDBwhich providesCosmosTrackingMessageHandler. See Integration CosmosDB Extension. -
EF Core / Relational databases — EF Core uses ADO.NET
DbCommandinternally, notHttpClient. UseKronikol.Extensions.EfCore.Relationalwhich providesSqlTrackingInterceptor— aDbCommandInterceptorthat classifies SQL operations and shows them asSelect: /ordersdb/Users,Insert: /ordersdb/Orders, etc. Works with SQL Server, PostgreSQL, MySQL, SQLite, Oracle, and Spanner. See Integration EF Core Relational Extension. -
gRPC services — gRPC clients use
GrpcChannel, notIHttpClientFactory. UseKronikol.Extensions.Grpcwhich providesGrpcTrackingInterceptorfor outgoing calls,GrpcTrackingChannel.Create()for incoming (test → SUT) calls, andAddTrackedGrpcClient<TClient>()for DI-based registration (v2.26.0+). Produces protobuf-aware labels likeSayHello: grpc:///greet.Greeter/SayHelloinstead of raw HTTP/2 binary traffic.AddTrackedGrpcClient<T>()andCreateTestTrackingGrpcClientauto-resolveIHttpContextAccessorfrom DI so test identity flows through for SUT → downstream calls. See Integration Grpc Extension for the full setup guide. -
Non-HTTP interactions (Kafka, Service Bus, etc.) — Use
MessageTracker. See Event & Message Tracking.
To track incoming calls from the test to the SUT, create the test's HttpClient via the CreateTestTrackingClient() extension method:
HttpClient client = factory.CreateTestTrackingClient(
new XUnitTestTrackingMessageHandlerOptions
{
FixedNameForReceivingService = "My API"
});This is a convenience method equivalent to:
var client = factory.CreateDefaultClient(new TestTrackingMessageHandler(options));It wraps the WebApplicationFactory's HttpClient in a TestTrackingMessageHandler so that all calls from the test to the SUT appear in the diagrams.
If your test suite already has custom DelegatingHandlers on the test-to-SUT client (e.g. a handler that waits for background processing to complete after each request), use the overload that accepts additional handlers:
HttpClient client = factory.CreateTestTrackingClient(
new XUnitTestTrackingMessageHandlerOptions
{
FixedNameForReceivingService = "My API"
},
new MyBackgroundWorkHandler(),
new MyRetryHandler());This is equivalent to manually calling CreateDefaultClient with the tracking handler first:
var trackingHandler = new TestTrackingMessageHandler(
new XUnit2TestTrackingMessageHandlerOptions
{
FixedNameForReceivingService = "My API"
});
HttpClient client = factory.CreateDefaultClient(trackingHandler, new MyBackgroundWorkHandler());Ordering: The tracking handler is always placed first (outermost) so it captures the full request/response including any modifications made by subsequent handlers.
For more complex handler chaining scenarios (named clients, typed clients, existing DelegatingHandler chains, IHttpMessageHandlerBuilderFilter, etc.), see Tracking Dependencies which covers 8 common patterns in detail.
When your SUT processes a request inside WebApplicationFactory, the code runs on the server's thread pool — not on the test thread. This means AsyncLocal<T>-based test context (used by xUnit, NUnit, LightBDD, ReqNRoll, etc.) is not available inside the SUT's request pipeline.
This affects all tracking extensions that run inside the pipeline. For example, if your API produces a Kafka message, writes to Cosmos DB, or logs to Redis as part of handling a request, the extension's CurrentTestInfoFetcher delegate will throw an exception (caught internally by TestInfoResolver, so tests still pass — but the operation is logged with no test identity and won't appear in diagrams).
The standard HTTP tracking (TestTrackingMessageHandler) never had this problem because it propagates test identity via HTTP headers (test-tracking-current-test-name, test-tracking-current-test-id) on the incoming request. But non-HTTP extensions (Kafka, Cosmos DB, Redis, EF Core, Service Bus, etc.) had no way to read those headers — until now.
Starting in v2.23.0, all 22 tracking extensions accept an optional IHttpContextAccessor? httpContextAccessor parameter in their constructors. When provided, the extension uses dual-resolution to determine the current test identity:
-
Try HTTP headers first — If an
HttpContextis available (meaning the code is running inside a request pipeline), readtest-tracking-current-test-nameandtest-tracking-current-test-idfrom the request headers -
Fall back to the delegate — If no
HttpContextis available (e.g. the code is running directly on the test thread), useCurrentTestInfoFetcheras before
This is fully backward-compatible. The httpContextAccessor parameter defaults to null, and all existing code continues to work unchanged.
v2.26.3+: All extension options classes now have an HttpContextAccessor property. Convenience methods, DI extensions, and CreateTestTrackingClient() auto-resolve IHttpContextAccessor from DI when available — no manual wiring needed for the standard setup paths:
builder.ConfigureTestServices(services =>
{
// TrackDependenciesForDiagrams() registers IHttpContextAccessor automatically
services.TrackDependenciesForDiagrams(new XUnitTestTrackingMessageHandlerOptions { ... });
// ServiceBus — AddServiceBusTestTracking auto-resolves IHttpContextAccessor from DI
services.AddServiceBusTestTracking(new ServiceBusTrackingOptions
{
ServiceName = "ServiceBus",
CallerName = "My API",
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
});
// gRPC — AddTrackedGrpcClient auto-resolves IHttpContextAccessor from DI
services.AddTrackedGrpcClient<MyGrpcClient>(handler, uri, opts => { ... });
});If you construct trackers manually (not via DI extensions), you can set HttpContextAccessor on the options:
builder.ConfigureTestServices(services =>
{
services.AddHttpContextAccessor();
services.AddSingleton(sp =>
{
var options = new KafkaTrackingOptions
{
ServiceName = "Kafka",
CallerName = "My API",
CurrentTestInfoFetcher = CurrentTestInfo.Fetcher,
HttpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>()
};
return new KafkaTracker(options);
});
});The constructor
httpContextAccessorparameter still works and takes precedence over the options property.
All DI extensions and convenience methods auto-resolve IHttpContextAccessor from the service provider when it's available in DI. This covers:
-
Core:
CreateTestTrackingClient()(both overloads) -
ServiceBus:
AddServiceBusTestTracking() -
gRPC:
AddTrackedGrpcClient<TClient>(),CreateTestTrackingGrpcClient() -
MediatR:
TrackMediatorForDiagrams()(auto-resolved since v2.23.0) -
All other extensions: Set
HttpContextAccessoron the options class — the tracker reads it via?? options.HttpContextAccessor
You need dual-resolution (via auto-resolve or manual HttpContextAccessor) if all of these are true:
- Your extension tracker runs inside the SUT's request pipeline (not on the test thread)
- The SUT is hosted via
WebApplicationFactory(in-process) - You're using
CreateTestTrackingClient()or manually addingTestTrackingMessageHandleron the test-to-SUT client (which propagates the headers)
If your extension only runs on the test thread (e.g. in [BeforeScenario] / [AfterScenario] hooks, or in step definitions that call the SDK directly without going through the SUT), the delegate alone is sufficient.
Note: If you register trackers manually via
services.AddSingleton(sp => new XxxTracker(options, sp.GetService<IHttpContextAccessor>())), the explicit constructor parameter takes precedence over the options property.
All extensions delegate to TestInfoResolver.Resolve(httpContextAccessor, currentTestInfoFetcher) which:
- Checks if
httpContextAccessor?.HttpContext?.Requesthastest-tracking-current-test-nameandtest-tracking-current-test-idheaders - If both headers are present and non-empty, returns them
- Otherwise, invokes the
CurrentTestInfoFetcherdelegate (with exception handling) - If the delegate also fails or is null, returns
null(operation is not logged)
All 22 tracking extensions support the optional IHttpContextAccessor parameter as of v2.23.0. v2.26.3+: All options classes now expose an HttpContextAccessor property, and convenience methods / DI extensions auto-resolve it from DI:
| Category | Extensions | Auto-resolved since |
|---|---|---|
| Core | CreateTestTrackingClient() |
v2.26.2 |
| Messaging | Kafka, ServiceBus, EventHubs, EventBridge, SQS, SNS, MassTransit, PubSub, StorageQueues | v2.26.2 (ServiceBus DI extension); others via options property |
| Databases | CosmosDB, MongoDB, DynamoDB, Redis, EF Core (Dapper), BigQuery, Elasticsearch | v2.26.2 via options property; MongoDB/BigQuery/Bigtable/Spanner/EF Core/PubSub/Kafka already auto-resolved |
| Storage | BlobStorage, S3, CloudStorage | v2.26.2 via options property |
| RPC | gRPC | v2.26.1 (AddTrackedGrpcClient / CreateTestTrackingGrpcClient) |
| Proxy-based | DispatchProxy, MediatR | MediatR auto-resolved since v2.23.0; DispatchProxy v2.26.2 via ReplaceWithTrackingProxy overload |
When using JustEat.HttpClientInterception for HTTP mocking, you need a custom IHttpMessageHandlerBuilderFilter to insert TestTrackingMessageHandler before the interception handler:
public class HttpClientInterceptionFilter(
HttpClientInterceptorOptions options,
IServiceProvider serviceProvider,
TestTrackingMessageHandlerOptions? trackingOptions = null) : IHttpMessageHandlerBuilderFilter
{
public Action<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuilder> next) =>
builder =>
{
next(builder);
string? serviceName = null;
if (trackingOptions is not null && !string.IsNullOrEmpty(builder.Name))
{
var match = trackingOptions.ClientNamesToServiceNames
.FirstOrDefault(kvp => builder.Name.Contains(kvp.Key, StringComparison.OrdinalIgnoreCase));
serviceName = match.Value;
}
if (serviceName is not null)
{
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
builder.PrimaryHandler = new TestTrackingMessageHandler(
new TestTrackingMessageHandlerOptions
{
CallerName = trackingOptions!.CallerName,
FixedNameForReceivingService = serviceName,
CurrentTestInfoFetcher = trackingOptions.CurrentTestInfoFetcher,
},
httpContextAccessor)
{
InnerHandler = new MockHttpMessageHandler(options)
{
InnerHandler = builder.PrimaryHandler
}
};
}
else
{
builder.AdditionalHandlers.Add(options.CreateHttpMessageHandler());
}
};
}The MockHttpMessageHandler wrapper handles GetResponseAsync properly as a DelegatingHandler:
public class MockHttpMessageHandler(HttpClientInterceptorOptions options) : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await options.GetResponseAsync(request, cancellationToken);
if (response is not null) return response;
if (options.ThrowOnMissingRegistration)
throw new HttpRequestNotInterceptedException(
$"No HTTP response configured for {request.Method} {request.RequestUri}.", request);
return await base.SendAsync(request, cancellationToken);
}
}Register in ConfigureTestServices:
services.AddSingleton<IHttpMessageHandlerBuilderFilter>(sp =>
new HttpClientInterceptionFilter(interceptorOptions, sp, trackingOptions));Common mistake —
_ =>vssp =>: Using_ =>discards the service provider, leavingIHttpContextAccessornull. Always usesp =>and resolveIHttpContextAccessorfrom it. See #Dual-Resolution Test Identity (v2.23.0+).
When combining TestTrackingMessageHandler with test faking (JustEat.HttpClientInterception, WireMock, or custom handlers), the handler chain ordering is critical:
┌─────────────────────────────────────┐
│ HttpClient │
├─────────────────────────────────────┤
│ TestTrackingMessageHandler │ ← Records request + response
│ InnerHandler ─┐ │
│ ▼ │
│ InterceptionHandler │ ← Returns fake response
│ InnerHandler ─┐ │
│ ▼ │
│ PrimaryHandler (HttpClientHandler) │ ← Never reached (intercepted)
└─────────────────────────────────────┘
The tracking handler must be outermost — it wraps the interception handler, not the reverse. This way:
- Request flows through
TestTrackingMessageHandler(recorded) - Then through the interception handler (fake response returned)
- Response flows back through
TestTrackingMessageHandler(recorded)
When implementing IHttpMessageHandlerBuilderFilter, replace PrimaryHandler with the tracking handler chained to the interceptor:
// ❌ Wrong: AdditionalHandlers runs after PrimaryHandler interception
builder.AdditionalHandlers.Add(trackingHandler);
// ✅ Correct: tracking wraps interception as the primary handler
var interceptionHandler = _interceptor.CreateHttpMessageHandler();
interceptionHandler.InnerHandler = builder.PrimaryHandler;
builder.PrimaryHandler = new TestTrackingMessageHandler(options, httpContextAccessor)
{
InnerHandler = interceptionHandler
};TestTrackingMessageHandler needs IHttpContextAccessor for dual-resolution of test identity. This must be resolved from DI at handler creation time, not at registration time:
// ❌ Wrong: HttpContextAccessor resolved at registration — HttpContext will be null
services.AddSingleton<IHttpMessageHandlerBuilderFilter>(_ =>
new MyFilter(new HttpContextAccessor()));
// ✅ Correct: resolved from service provider at filter creation time
services.AddSingleton<IHttpMessageHandlerBuilderFilter>(sp =>
new MyFilter(sp));CreateTestTrackingClient() is the primary entry point for tracking inbound HTTP requests (test → SUT). It:
- Creates an
HttpClienttargeting the in-memory test server - Inserts a
TestTrackingMessageHandleras the outermost handler - Auto-injects
test-tracking-current-test-name,test-tracking-current-test-id, andtest-tracking-trace-idheaders into every request - (v2.26.3+) Auto-resolves
IHttpContextAccessorfrom DI
These headers are how the SUT's internal tracking (CosmosDB, Redis, Service Bus, etc.) correlates operations back to the originating test.
FixedNameForReceivingService sets the target service name in diagrams. It should match the CallerName used in outbound tracking options:
// Inbound: "Caller" → "My Service"
var client = factory.CreateTestTrackingClient(new XUnitTestTrackingMessageHandlerOptions
{
FixedNameForReceivingService = "My Service"
});
// Outbound: "My Service" → "Downstream A"
services.TrackDependenciesForDiagrams(new XUnitTestTrackingMessageHandlerOptions
{
CallerName = "My Service", // Must match FixedNameForReceivingService above
ClientNamesToServiceNames = { { "DownstreamAClient", "Downstream A" } }
});One client per collection: Create one tracked client per test collection (not per test). The client is thread-safe and Kronikol headers are injected per-request based on the current test context.
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