Skip to content

Phase Aware Tracking

Aryeh Citron edited this page Apr 27, 2026 · 6 revisions

Phase-aware tracking lets you configure tracking behavior differently for the Setup phase (BDD Given/Arrange) vs the Action phase (BDD When-Then/Act-Assert). This is useful for reducing diagram noise — e.g. suppressing verbose database seeding calls during setup while keeping full detail for the action under test.


How It Works

Every tracking extension reads the current test phase from an ambient AsyncLocal context (TestPhaseContext.Current). Based on the phase, each tracker decides:

  1. Whether to track at allTrackDuringSetup / TrackDuringAction (default: both true)
  2. What verbosity to useSetupVerbosity / ActionVerbosity override the default Verbosity during that phase

If no phase is set (the default for non-BDD frameworks that don't call StartSetup()), the phase is Unknown and all phase-specific overrides are ignored — tracking behaves exactly as before.

Phase Detection

Source How phase is set
BDDfy Automatically from ExecutionOrderSetupState/ConsecutiveSetupState/Assertion → Setup; others → Action
LightBDD Automatically from GetTopLevelStepType() — Given/And/But → Setup; When/Then → Action
ReqNRoll Automatically in BeforeStep hook — Given/And/But → Setup; When/Then → Action
Non-BDD Manually via TrackingDiagramOverride.StartSetup() and TrackingDiagramOverride.StartAction()

Quick Start

Suppress all tracking during setup

new SqlTrackingInterceptorOptions
{
    ServiceName = "OrdersDb",
    Verbosity = SqlTrackingVerbosity.Detailed,
    TrackDuringSetup = false  // ← no SQL tracking during Given/Arrange
}

Use summarised verbosity during setup, detailed during action

new SqlTrackingInterceptorOptions
{
    ServiceName = "OrdersDb",
    Verbosity = SqlTrackingVerbosity.Detailed,       // default for Unknown phase
    SetupVerbosity = SqlTrackingVerbosity.Summarised, // less detail during setup
    ActionVerbosity = SqlTrackingVerbosity.Raw         // maximum detail during action
}

Suppress HTTP tracking during setup

services.TrackDependenciesForDiagrams(
    new XUnitTestTrackingMessageHandlerOptions
    {
        CallingServiceName = "My API",
        PortsToServiceNames = { { 80, "My API" } },
        TrackDuringSetup = false  // ← no HTTP tracking during setup
    });

Non-BDD: Explicit phase boundaries

[Fact]
public async Task Create_order_stores_in_database()
{
    TrackingDiagramOverride.StartSetup();

    // Setup phase — seeding, config, etc.
    await client.PostAsync("/api/seed-data", seedContent);

    TrackingDiagramOverride.StartAction();

    // Action phase — the actual behavior under test
    var response = await client.PostAsync("/api/orders", orderContent);
    response.StatusCode.Should().Be(HttpStatusCode.Created);
}

BDD frameworks: You don't need to call StartSetup() or StartAction() — phase detection is automatic based on the step keyword.


Options Reference

All Extension Options

Every extension options class (except OpenTelemetry) supports these four phase-aware properties:

Property Type Default Description
TrackDuringSetup bool true When false, tracking is completely suppressed during the Setup phase
TrackDuringAction bool true When false, tracking is completely suppressed during the Action phase
SetupVerbosity {ExtVerbosity}? null Verbosity override for the Setup phase. null = use default Verbosity
ActionVerbosity {ExtVerbosity}? null Verbosity override for the Action phase. null = use default Verbosity

Where {ExtVerbosity} is the extension-specific verbosity enum (e.g. SqlTrackingVerbosity, RedisTrackingVerbosity, CosmosTrackingVerbosity, etc.).

TestTrackingMessageHandlerOptions (HTTP)

The core HTTP tracking handler supports TrackDuringSetup and TrackDuringAction but does not have verbosity overrides (HTTP tracking doesn't use an enum-based verbosity system):

Property Type Default Description
TrackDuringSetup bool true When false, HTTP requests during Setup are not tracked
TrackDuringAction bool true When false, HTTP requests during Action are not tracked

MediatR Extension

The MediatR extension uses TrackingProxy internally and supports TrackDuringSetup / TrackDuringAction only (no verbosity overrides):

Property Type Default Description
TrackDuringSetup bool true When false, MediatR send/publish tracking is suppressed during Setup
TrackDuringAction bool true When false, MediatR send/publish tracking is suppressed during Action

DispatchProxy Extension

The DispatchProxy extension takes a TrackingProxyOptions directly, which has TrackDuringSetup and TrackDuringAction:

Property Type Default Description
TrackDuringSetup bool true When false, proxy interaction logging is suppressed during Setup
TrackDuringAction bool true When false, proxy interaction logging is suppressed during Action

Extensions Supporting Phase-Aware Verbosity

The following extensions support both the enable/disable toggle (TrackDuringSetup/TrackDuringAction) and per-phase verbosity overrides (SetupVerbosity/ActionVerbosity):

Extension Options Class Verbosity Enum
EF Core (Relational) SqlTrackingInterceptorOptions SqlTrackingVerbosity
Redis RedisTrackingDatabaseOptions RedisTrackingVerbosity
Kafka KafkaTrackingOptions KafkaTrackingVerbosity
gRPC GrpcTrackingOptions GrpcTrackingVerbosity

gRPC note: If your gRPC calls run inside the SUT's request pipeline (SUT → downstream), phase-aware tracking will only work if test identity can be resolved. v2.26.0+: AddTrackedGrpcClient<TClient>() auto-resolves IHttpContextAccessor from DI. For older versions, set HttpContextAccessor on GrpcTrackingOptions manually. See Integration Grpc Extension#Dual-Resolution Test Identity (HttpContextAccessor).

| MassTransit | MassTransitTrackingOptions | MassTransitTrackingVerbosity | | MongoDB | MongoDbTrackingOptions | MongoDbTrackingVerbosity | | CosmosDB | CosmosTrackingMessageHandlerOptions | CosmosTrackingVerbosity | | Elasticsearch | ElasticsearchTrackingOptions | ElasticsearchTrackingVerbosity | | Dapper | DapperTrackingOptions | DapperTrackingVerbosity | | BigQuery | BigQueryTrackingMessageHandlerOptions | BigQueryTrackingVerbosity | | BlobStorage | BlobTrackingMessageHandlerOptions | BlobTrackingVerbosity | | CloudStorage | CloudStorageTrackingMessageHandlerOptions | CloudStorageTrackingVerbosity | | DynamoDB | DynamoDbTrackingMessageHandlerOptions | DynamoDbTrackingVerbosity | | EventBridge | EventBridgeTrackingMessageHandlerOptions | EventBridgeTrackingVerbosity | | S3 | S3TrackingMessageHandlerOptions | S3TrackingVerbosity | | SNS | SnsTrackingMessageHandlerOptions | SnsTrackingVerbosity | | SQS | SqsTrackingMessageHandlerOptions | SqsTrackingVerbosity | | StorageQueues | StorageQueueTrackingMessageHandlerOptions | StorageQueueTrackingVerbosity | | EventHubs | EventHubsTrackingOptions | EventHubsTrackingVerbosity | | PubSub | PubSubTrackingOptions | PubSubTrackingVerbosity | | ServiceBus | ServiceBusTrackingOptions | ServiceBusTrackingVerbosity |


Combining with Setup Separation

Phase-aware tracking works independently from Diagram Customisation#Setup Separation (SeparateSetup = true). They complement each other:

Feature Purpose
Setup Separation Visual — wraps setup calls in a coloured partition in the diagram
Phase-Aware Tracking Functional — controls whether calls are tracked and at what verbosity

You can use both together: suppress noisy setup database calls (TrackDuringSetup = false on the DB extension) while still showing setup HTTP calls in a partition (SeparateSetup = true).


RequestResponseLog Phase Property

Each RequestResponseLog entry now includes a Phase property (TestPhase enum) indicating which phase produced it. This is available in:

  • Custom report generators that consume RequestResponseLog directly
  • The JSON/YAML/XML export formats

How Phase Detection Works Internally

Test Step Executes
    │
    ├── BDD adapter (BDDfy/LightBDD/ReqNRoll)
    │   └── Calls PhaseConfiguration.ResolvePhaseFromStepType("Given")
    │       └── Sets TestPhaseContext.Current = Setup
    │
    ├── OR: Non-BDD test
    │   └── Calls TrackingDiagramOverride.StartSetup() / StartAction()
    │       └── Sets TestPhaseContext.Current = Setup / Action
    │
    ▼
Tracker intercepts operation (SQL, Redis, HTTP, etc.)
    │
    ├── PhaseConfiguration.ShouldTrack(trackDuringSetup, trackDuringAction)
    │   └── Reads TestPhaseContext.Current
    │   └── Returns false → skip tracking entirely
    │
    ├── PhaseConfiguration.GetEffectiveVerbosity(default, setupOverride, actionOverride)
    │   └── Reads TestPhaseContext.Current
    │   └── Returns phase-appropriate verbosity
    │
    └── Logs with Phase = TestPhaseContext.Current on RequestResponseLog

Step Type to Phase Mapping

Step Keyword Phase
Given, And, But Setup
When, Then Action
null / unrecognised Unknown

Note: And and But always map to Setup because in BDD conventions they typically continue the Given context. If your And/But steps follow a When or Then, you can override by calling TrackingDiagramOverride.StartAction() explicitly.


Not Supported

  • OpenTelemetry Extension: The OpenTelemetry extension is a pass-through that captures spans from the OpenTelemetry SDK. It does not have its own tracking loop, so phase-aware configuration does not apply.

Home


Demo


Getting Started

Common Tasks

Integration Guides

Extensions

Configuration

Features

Reference

Clone this wiki locally