Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Extensions.Enrichment/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
* Updated OpenTelemetry core component version(s) to `1.15.2`.
([#4080](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4080))

* Fixed trace enrichment callbacks so exceptions thrown by user-provided
enrichers or enrichment actions no longer interrupt trace processing.
([#4165](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4165))

## 1.15.0-beta.1

Released 2026-Jan-21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ public override void Enrich(in TraceEnrichmentBag bag)
{
for (var i = 0; i < this.actions.Length; i++)
{
this.actions[i].Invoke(bag);
try
{
this.actions[i].Invoke(bag);
}
catch (Exception)
Comment thread
martincostello marked this conversation as resolved.
Outdated
{
}
Comment thread
ysolomchenko marked this conversation as resolved.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ public override void OnStart(Activity activity)

foreach (var enricher in this.traceEnrichers)
{
enricher.EnrichOnActivityStart(bag);
try
{
enricher.EnrichOnActivityStart(bag);
}
catch (Exception)
{
}
}
}

Expand All @@ -32,7 +38,13 @@ public override void OnEnd(Activity activity)

foreach (var enricher in this.traceEnrichers)
{
enricher.Enrich(bag);
try
{
enricher.Enrich(bag);
}
catch (Exception)
{
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,155 @@ public async Task FactoryMethod_RegistersEnricher()

await host.StopAsync();
}

[Fact]
public async Task DelegateMethod_SwallowsExceptionsFromEnrichmentActions()
{
var exportedItems = new List<Activity>();

const string testKey = "safe-key";
const string testValue = "safe-value";

using var host = Host.CreateDefaultBuilder()
.ConfigureServices(services => services
.AddOpenTelemetry()
.WithTracing(builder => builder
.AddSource(SourceName)
.AddInMemoryExporter(exportedItems))
.Services
.AddTraceEnricher((Action<TraceEnrichmentBag>)(_ => throw new InvalidOperationException("boom")))
.AddTraceEnricher((Action<TraceEnrichmentBag>)(bag => bag.Add(testKey, testValue))))
.Build();

await host.StartAsync();

using var source = new ActivitySource(SourceName);

var exception = Record.Exception(() =>
{
using var activity = source.StartActivity(SourceName);
Assert.NotNull(activity);
activity.Stop();
});

Assert.Null(exception);
Assert.Single(exportedItems);
Assert.Equal(testValue, exportedItems[0].TagObjects.Single(tag => tag.Key == testKey).Value);

await host.StopAsync();
}

[Fact]
public async Task InstanceMethod_SwallowsExceptionsFromEnrich()
{
var exportedItems = new List<Activity>();
var trackingEnricher = new TrackingTraceEnricher();

using var host = Host.CreateDefaultBuilder()
.ConfigureServices(services => services
.AddOpenTelemetry()
.WithTracing(builder => builder
.AddSource(SourceName)
.AddInMemoryExporter(exportedItems))
.Services
.TryAddTraceEnricher(new ThrowingOnEndTraceEnricher())
.TryAddTraceEnricher(trackingEnricher))
.Build();

await host.StartAsync();

using var source = new ActivitySource(SourceName);

var exception = Record.Exception(() =>
{
using var activity = source.StartActivity(SourceName);
Assert.NotNull(activity);
activity.Stop();
});

Assert.Null(exception);
Assert.Equal(1, trackingEnricher.StartCalls);
Assert.Equal(1, trackingEnricher.EndCalls);
Assert.Single(exportedItems);
Assert.Equal(TrackingTraceEnricher.EndValue, exportedItems[0].TagObjects.Single(tag => tag.Key == TrackingTraceEnricher.EndKey).Value);

await host.StopAsync();
}

[Fact]
public async Task InstanceMethod_SwallowsExceptionsFromEnrichOnActivityStart()
{
var exportedItems = new List<Activity>();
var trackingEnricher = new TrackingTraceEnricher();

using var host = Host.CreateDefaultBuilder()
.ConfigureServices(services => services
.AddOpenTelemetry()
.WithTracing(builder => builder
.AddSource(SourceName)
.AddInMemoryExporter(exportedItems))
.Services
.TryAddTraceEnricher(new ThrowingOnStartTraceEnricher())
.TryAddTraceEnricher(trackingEnricher))
.Build();

await host.StartAsync();

using var source = new ActivitySource(SourceName);

var exception = Record.Exception(() =>
{
using var activity = source.StartActivity(SourceName);
Assert.NotNull(activity);
activity.Stop();
});

Assert.Null(exception);
Assert.Equal(1, trackingEnricher.StartCalls);
Assert.Equal(1, trackingEnricher.EndCalls);
Assert.Single(exportedItems);
Assert.Equal(TrackingTraceEnricher.StartValue, exportedItems[0].TagObjects.Single(tag => tag.Key == TrackingTraceEnricher.StartKey).Value);

await host.StopAsync();
}

private sealed class ThrowingOnStartTraceEnricher : TraceEnricher
{
public override void Enrich(in TraceEnrichmentBag bag)
{
}

public override void EnrichOnActivityStart(in TraceEnrichmentBag bag)
=> throw new InvalidOperationException("boom");
}

private sealed class ThrowingOnEndTraceEnricher : TraceEnricher
{
public override void Enrich(in TraceEnrichmentBag bag)
=> throw new InvalidOperationException("boom");
}

private sealed class TrackingTraceEnricher : TraceEnricher
{
public const string StartKey = "tracking-start";
public const string StartValue = "start";
public const string EndKey = "tracking-end";
public const string EndValue = "end";

public int StartCalls { get; private set; }

public int EndCalls { get; private set; }

public override void Enrich(in TraceEnrichmentBag bag)
{
this.EndCalls++;
bag.Add(EndKey, EndValue);
}

public override void EnrichOnActivityStart(in TraceEnrichmentBag bag)
{
this.StartCalls++;
bag.Add(StartKey, StartValue);
}
}
}
Loading