xUnitOTel 1.0.0.41

dotnet add package xUnitOTel --version 1.0.0.41
                    
NuGet\Install-Package xUnitOTel -Version 1.0.0.41
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="xUnitOTel" Version="1.0.0.41" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="xUnitOTel" Version="1.0.0.41" />
                    
Directory.Packages.props
<PackageReference Include="xUnitOTel" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add xUnitOTel --version 1.0.0.41
                    
#r "nuget: xUnitOTel, 1.0.0.41"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package xUnitOTel@1.0.0.41
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=xUnitOTel&version=1.0.0.41
                    
Install as a Cake Addin
#tool nuget:?package=xUnitOTel&version=1.0.0.41
                    
Install as a Cake Tool

xUnitOTel

<p align="center"> <img src="assets/images/icon.svg" alt="xUnitOTel Logo" width="128" height="128"> </p>

Build Status NuGet Version NuGet Downloads License: MIT

OpenTelemetry instrumentation for xUnit v3 tests. Automatically wraps tests in distributed tracing spans with HTTP, SQL, and gRPC instrumentation.

Table of Contents

Requirements

  • .NET Standard 2.0 compatible runtime (.NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+)
  • xUnit v3 (not compatible with xUnit v2)

Installation

dotnet add package xUnitOTel

Quick Start

1. Create TestSetup fixture

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using xUnitOTel.Diagnostics;

public class TestSetup : IAsyncLifetime
{
    private IHost _host = null!;
    public IHost Host => _host;

    public T GetRequiredService<T>() where T : notnull
        => _host.Services.GetRequiredService<T>();

    public async ValueTask InitializeAsync()
    {
        var builder = Microsoft.Extensions.Hosting.Host.CreateApplicationBuilder();

        builder.Services.AddOTelDiagnostics(
            configureMeterProviderBuilder: m => m.AddOtlpExporter(),
            configureTracerProviderBuilder: t => t.AddOtlpExporter(),
            configureLoggingBuilder: options => options.AddOpenTelemetry(o => o.AddOtlpExporter())
        );

        builder.Services.AddHttpClient();

        _host = builder.Build();
        await _host.StartAsync();
    }

    public async ValueTask DisposeAsync()
    {
        await _host.StopAsync();
        _host.Dispose();
    }
}

2. Enable tracing

Add to any test file to trace all tests in the assembly:

[assembly: Trace]
[assembly: AssemblyFixture(typeof(TestSetup))]

Or apply [Trace] to individual test methods.

3. Write tests

public class ApiTests(TestSetup fixture)
{
    [Fact]
    public async Task GetUsers_ReturnsSuccess()
    {
        var client = fixture.GetRequiredService<IHttpClientFactory>().CreateClient();
        var response = await client.GetAsync("https://api.example.com/users");
        Assert.True(response.IsSuccessStatusCode);
    }
}

All HTTP requests, timing, and trace IDs appear in test output automatically.

<p align="center"> <img src="assets/images/output.png" alt="Test Output Example" width="800"> </p>

How It Works

flowchart LR
    A[Test Method] --> B["[Trace] Attribute"]
    B --> C[Activity/Span]
    C --> D[OpenTelemetry]
    D --> E[OTLP Exporter]
    E --> F[Aspire Dashboard]
  1. TestSetup creates Host with AddOTelDiagnostics() configuring OpenTelemetry
  2. [Trace] attribute wraps tests in Activity spans
  3. Spans tagged with test.class.method, test.name, test.framework
  4. HTTP/SQL/gRPC calls auto-instrumented as child spans
  5. Logs attached as Activity events

Configuration

AddOTelDiagnostics Options

Parameter Type Description
serviceName string? Service name for telemetry (default: entry assembly name)
configureMeterProviderBuilder Action<MeterProviderBuilder>? Configure metrics exporters
configureTracerProviderBuilder Action<TracerProviderBuilder>? Configure trace exporters
configureLoggingBuilder Action<ILoggingBuilder>? Configure log exporters

Trace Attribute Properties

Property Type Default Description
CaptureError bool true Capture stderr to test output
CaptureOut bool true Capture stdout to test output

OpenTelemetry Tags

Tag Description
test.class.method Full test class and method name
test.name Test method name
test.framework Always "xunit"
testrun.id Unique ID for test run session

Failed Test Logging

Automatically exports failed test logs to JSON files for LLM analysis, CI/CD debugging, or archiving.

Enable

builder.Services.AddOTelDiagnostics(
    configureFailedTestLogging: opts => {
        opts.OutputDirectory = "test-failures";
    }
);

Options

Option Default Description
Enabled true Enable/disable feature
OutputDirectory "logs" Where to save JSON files

Output

File naming: {TestClass}.{TestName}_{yyyyMMdd_HHmmss}.json

{
  "traceId": "abc123...",
  "testClass": "ApiTests",
  "testName": "GetUsers_ReturnsSuccess",
  "timestamp": "2025-01-15T10:30:00Z",
  "failure": {
    "messages": ["Expected: true, Actual: false"],
    "stackTraces": ["at ApiTests.GetUsers_ReturnsSuccess()..."]
  },
  "logs": [
    {
      "timestamp": "2025-01-15T10:29:59Z",
      "level": "Information",
      "category": "System.Net.Http.HttpClient",
      "message": "Sending HTTP request GET https://api.example.com/users",
      "exception": null
    }
  ]
}

Notes

  • Only failed tests create files (passing tests are ignored)
  • Works with parallel test execution (AsyncLocal isolation)
  • HTTP/SQL/gRPC instrumentation logs included automatically

Viewing Telemetry

Start the dashboard:

docker run -d \
  -p 18888:18888 \
  -p 4317:18889 \
  -e DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true \
  --name aspire-dashboard \
  mcr.microsoft.com/dotnet/aspire-dashboard:9.0

Open http://localhost:18888 to view traces.

Console Exporter

For simple debugging without external tools:

builder.Services.AddOTelDiagnostics(
    configureTracerProviderBuilder: t => t.AddConsoleExporter()
);

API Reference

TraceAttribute

xUnit BeforeAfterTestAttribute that wraps tests in OpenTelemetry spans.

// Assembly-level (all tests)
[assembly: Trace]

// Method-level
[Fact]
[Trace]
public void MyTest() { }

OTelConfigurationExtensions

Entry point for configuring OpenTelemetry.

services.AddOTelDiagnostics(
    serviceName: "MyTests",
    configureTracerProviderBuilder: t => t.AddOtlpExporter()
);

ApplicationDiagnostics

Static ActivitySource for creating custom spans:

using var activity = ApplicationDiagnostics.ActivitySource.StartActivity("CustomOperation");
// ... operation code

Troubleshooting

[Trace] attribute has no effect

The attribute requires OpenTelemetry to be configured via AddOTelDiagnostics(). Ensure your TestSetup fixture is properly registered with [assembly: AssemblyFixture(typeof(TestSetup))].

No spans appearing in dashboard

  1. Verify OTLP endpoint is reachable (default: localhost:4317)
  2. Check that AddOtlpExporter() is configured
  3. Ensure Aspire Dashboard is running

xUnit v2 compatibility

This package only supports xUnit v3. For xUnit v2, consider upgrading or using a different instrumentation approach.

Missing HTTP/SQL instrumentation

AddOTelDiagnostics() automatically adds instrumentation for:

  • System.Net.Http (HttpClient)
  • System.Data.SqlClient / Microsoft.Data.SqlClient
  • gRPC clients

Ensure these libraries are used via dependency injection from the Host.

License

MIT License - see LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0.41 31 3/14/2026
1.0.0.40 42 3/9/2026
1.0.0.39 57 3/1/2026
1.0.0.38 79 2/6/2026
1.0.0.35 61 2/1/2026
1.0.0.33 97 2/1/2026
1.0.0.31 100 2/1/2026
1.0.0.30 96 2/1/2026
1.0.0.29 118 1/18/2026
1.0.0.28 308 12/15/2025
1.0.0.27 646 12/1/2025
1.0.0.26 253 11/14/2025
1.0.0.25 231 11/14/2025
1.0.0.24 397 8/8/2025