Skip to content

Diagnostics and Debugging

Aryeh Citron edited this page Apr 16, 2026 · 13 revisions

Diagnostics and Debugging

TestTrackingDiagrams includes several diagnostic tools to help you understand what's being tracked, identify configuration issues, and debug missing or unexpected diagram content.


Diagnostic Mode

Enable DiagnosticMode on ReportConfigurationOptions to generate a comprehensive DiagnosticReport.html alongside your normal reports:

var options = new ReportConfigurationOptions
{
    DiagnosticMode = true // generates DiagnosticReport.html
};

The diagnostic report includes:

Section Contents
Configuration Dump All ReportConfigurationOptions values, including InternalFlow settings
Log Counts by Service Number of request/response logs per ServiceName
Log Counts by Test Number of logs per test, sorted descending — highlights tests with zero logs
Unpaired Requests Request logs without matching responses (same TraceId + RequestResponseId)
Orphaned Test IDs Test IDs in logs that don't match any Feature/Scenario
Scenarios with No Logs Scenarios that ran but produced zero logged interactions
Activity Source Discovery All detected ActivitySource names from captured OTel spans, with span counts and tracked/well-known status

Tip: Enable DiagnosticMode temporarily during development to identify why diagrams are missing content — unpaired logs, orphaned IDs, or missing activity sources are the most common root causes.


Report Diagnostics

ReportDiagnostics.Analyse() runs automatically at report generation time and produces warning strings that appear in the report footer. Common warnings include:

  • "No request/response logs recorded" — No interactions were tracked. Check that TestTrackingMessageHandler is wired up.
  • "N test(s) have no request/response logs" — Some scenarios didn't produce any HTTP interactions.
  • "InternalFlowSpanStore contains 0 spans" — No OTel spans were captured. Check that the activity listener is running.

When ActivitySourceDiscovery is enabled on ReportConfigurationOptions, the diagnostics additionally list all discovered activity sources with their span counts:

var options = new ReportConfigurationOptions
{
    ActivitySourceDiscovery = true // includes source discovery in diagnostics
};

Activity Source Discovery

ActivitySourceDiscovery.GetDiscoveredSources() returns a dictionary of all ActivitySource names that produced spans during the test run, with their span counts:

var sources = ActivitySourceDiscovery.GetDiscoveredSources();
// e.g. { "Microsoft.AspNetCore": 42, "System.Net.Http": 38, "MyApi.Services": 15 }

This is useful for:

  • Identifying which sources are producing spans — Helps you decide which to include/exclude via InternalFlowSpanGranularity and InternalFlowActivitySources.
  • Verifying custom sources are being captured — If your custom ActivitySource doesn't appear, check that InternalFlowActivitySources includes its name.
  • Understanding span volume — High span counts from a single source may indicate noisy instrumentation that could be filtered.

InternalFlowSpanStore.Complete()

When creating manual spans (e.g. inside a TrackingProxy or custom tracking code), use InternalFlowSpanStore.Complete(activity) as a one-liner to stop and store the span:

var activity = new ActivitySource("MySource").StartActivity("MyOperation");
try
{
    // ... do work ...
}
finally
{
    InternalFlowSpanStore.Complete(activity);
}

Complete() is null-safe — it does nothing if the activity is null. If the activity hasn't been stopped, it calls Stop() before adding it to the store.


Empty Diagram Diagnostics

When InternalFlowNoDataBehavior is set to ShowMessage (the default), segments with no captured spans show an enriched diagnostic message instead of a generic "No data" notice. The message includes:

  • The current InternalFlowSpanGranularity setting
  • The configured InternalFlowActivitySources (if Manual granularity)
  • A count of total spans in the InternalFlowSpanStore
  • Actionable suggestions (e.g. "Try switching to Full granularity", "Check that your activity sources are listed")

This makes it much easier to diagnose why a particular popup has no internal flow content.


RequestResponseLogger.LogPair()

LogPair() is a convenience method that logs a matched request/response pair in a single call, automatically generating TraceId and RequestResponseId values:

RequestResponseLogger.LogPair(
    testName: "My test",
    testId: "test-123",
    method: "Cache Get",                    // OneOf<HttpMethod, string>
    uri: new Uri("redis://cache/my-key"),
    serviceName: "Redis Cache",
    callerName: "My Service",
    requestContent: "GET my-key",
    responseContent: "{\"value\": 42}",
    statusCode: HttpStatusCode.OK
);

This is equivalent to calling RequestResponseLogger.Log() twice (once for Request, once for Response) with matching identifiers and timestamps. It's the recommended approach for custom dependency tracking when you already have both the request and response data available.

See Tracking Custom Dependencies for the full manual approach when you need more control (e.g. different timestamps for request vs response, custom headers, or TrackingIgnore support).


Flame Chart Zoom

Flame charts in internal flow popups and whole-test flow sections now support interactive zoom:

Action Effect
Click a bar Zooms into that span's time range (with 5% padding)
Double-click anywhere Resets to the full view

When zoomed, a hint banner appears: "🔍 Zoomed — double-click to reset"

Tooltips on each bar now include:

  • Activity source name (e.g. [Microsoft.AspNetCore])
  • Span display name
  • Duration in milliseconds
  • Percentage of total duration

Home


Demo


Getting Started

Common Tasks

Integration Guides

Extensions

Configuration

Features

Reference

Clone this wiki locally