xUnitOTel 1.0.0.41
dotnet add package xUnitOTel --version 1.0.0.41
NuGet\Install-Package xUnitOTel -Version 1.0.0.41
<PackageReference Include="xUnitOTel" Version="1.0.0.41" />
<PackageVersion Include="xUnitOTel" Version="1.0.0.41" />
<PackageReference Include="xUnitOTel" />
paket add xUnitOTel --version 1.0.0.41
#r "nuget: xUnitOTel, 1.0.0.41"
#:package xUnitOTel@1.0.0.41
#addin nuget:?package=xUnitOTel&version=1.0.0.41
#tool nuget:?package=xUnitOTel&version=1.0.0.41
xUnitOTel
<p align="center"> <img src="assets/images/icon.svg" alt="xUnitOTel Logo" width="128" height="128"> </p>
OpenTelemetry instrumentation for xUnit v3 tests. Automatically wraps tests in distributed tracing spans with HTTP, SQL, and gRPC instrumentation.
Table of Contents
- Requirements
- Installation
- Quick Start
- How It Works
- Configuration
- Failed Test Logging
- Viewing Telemetry
- API Reference
- Troubleshooting
- License
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]
TestSetupcreates Host withAddOTelDiagnostics()configuring OpenTelemetry[Trace]attribute wraps tests in Activity spans- Spans tagged with
test.class.method,test.name,test.framework - HTTP/SQL/gRPC calls auto-instrumented as child spans
- 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
Aspire Dashboard (Recommended)
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
- Verify OTLP endpoint is reachable (default:
localhost:4317) - Check that
AddOtlpExporter()is configured - 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 | Versions 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. |
-
.NETStandard 2.0
- Microsoft.Bcl.TimeProvider (>= 10.0.5)
- Microsoft.Extensions.Logging.Console (>= 10.0.5)
- Microsoft.Extensions.Logging.Debug (>= 10.0.5)
- OpenTelemetry (>= 1.15.0)
- OpenTelemetry.Api (>= 1.15.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.15.0)
- OpenTelemetry.Extensions.Hosting (>= 1.15.0)
- OpenTelemetry.Instrumentation.GrpcNetClient (>= 1.15.0-beta.1)
- OpenTelemetry.Instrumentation.Http (>= 1.15.0)
- OpenTelemetry.Instrumentation.Runtime (>= 1.15.0)
- OpenTelemetry.Instrumentation.SqlClient (>= 1.15.1)
- xunit.v3.extensibility.core (>= 3.2.2)
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 |