Fix circular reference issue building up tracer provider. (#3803)
This commit is contained in:
parent
32650555d4
commit
9b8702e3dc
|
|
@ -41,6 +41,7 @@ internal static class ProviderBuilderServiceCollectionExtensions
|
|||
services.AddOpenTelemetryProviderBuilderServices();
|
||||
|
||||
services.RegisterOptionsFactory(configuration => new ExportActivityProcessorOptions(configuration));
|
||||
services.TryAddSingleton<TracerProviderBuilderState>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ namespace OpenTelemetry.Trace
|
|||
this.State = state;
|
||||
}
|
||||
|
||||
// This ctor is for AddOpenTelemetryTracing scenario where the builder
|
||||
// is bound to an external service collection.
|
||||
// This ctor is for ConfigureOpenTelemetryTracing +
|
||||
// AddOpenTelemetryTracing scenarios where the builder is bound to an
|
||||
// external service collection.
|
||||
internal TracerProviderBuilderBase(IServiceCollection services)
|
||||
{
|
||||
Guard.ThrowIfNull(services);
|
||||
|
|
@ -65,6 +66,8 @@ namespace OpenTelemetry.Trace
|
|||
var services = new ServiceCollection();
|
||||
|
||||
services.AddOpenTelemetryTracerProviderBuilderServices();
|
||||
services.AddSingleton<TracerProvider>(
|
||||
sp => throw new NotSupportedException("External TracerProvider created through Sdk.CreateTracerProviderBuilder cannot be accessed using service provider."));
|
||||
|
||||
this.services = services;
|
||||
this.ownsServices = true;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ namespace OpenTelemetry.Trace
|
|||
internal Sampler? Sampler;
|
||||
internal bool SetErrorStatusOnException;
|
||||
|
||||
private bool hasEnteredBuildPhase;
|
||||
private TracerProviderBuilderSdk? builder;
|
||||
|
||||
public TracerProviderBuilderState(IServiceProvider serviceProvider)
|
||||
|
|
@ -49,6 +50,16 @@ namespace OpenTelemetry.Trace
|
|||
|
||||
public TracerProviderBuilderSdk Builder => this.builder ??= new TracerProviderBuilderSdk(this);
|
||||
|
||||
public void CheckForCircularBuild()
|
||||
{
|
||||
if (this.hasEnteredBuildPhase)
|
||||
{
|
||||
throw new NotSupportedException("TracerProvider cannot be accessed while build is executing.");
|
||||
}
|
||||
|
||||
this.hasEnteredBuildPhase = true;
|
||||
}
|
||||
|
||||
public void AddInstrumentation(
|
||||
string instrumentationName,
|
||||
string instrumentationVersion,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OpenTelemetry.Internal;
|
||||
using OpenTelemetry.Resources;
|
||||
|
||||
|
|
@ -47,6 +48,9 @@ namespace OpenTelemetry.Trace
|
|||
{
|
||||
Debug.Assert(serviceProvider != null, "serviceProvider was null");
|
||||
|
||||
var state = serviceProvider!.GetRequiredService<TracerProviderBuilderState>();
|
||||
state.CheckForCircularBuild();
|
||||
|
||||
this.ServiceProvider = serviceProvider!;
|
||||
|
||||
if (ownsServiceProvider)
|
||||
|
|
@ -57,8 +61,6 @@ namespace OpenTelemetry.Trace
|
|||
|
||||
OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent("Building TracerProvider.");
|
||||
|
||||
var state = new TracerProviderBuilderState(serviceProvider!);
|
||||
|
||||
TracerProviderBuilderServiceCollectionHelper.InvokeRegisteredConfigureStateCallbacks(
|
||||
serviceProvider!,
|
||||
state);
|
||||
|
|
|
|||
|
|
@ -455,6 +455,56 @@ namespace OpenTelemetry.Trace.Tests
|
|||
Assert.True(configureBuilderCalled);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void TracerProviderNestedResolutionUsingBuilderTest(bool callNestedConfigure)
|
||||
{
|
||||
bool innerTestExecuted = false;
|
||||
|
||||
using var provider = Sdk.CreateTracerProviderBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
if (callNestedConfigure)
|
||||
{
|
||||
services.ConfigureOpenTelemetryTracing();
|
||||
}
|
||||
})
|
||||
.ConfigureBuilder((sp, builder) =>
|
||||
{
|
||||
innerTestExecuted = true;
|
||||
Assert.Throws<NotSupportedException>(() => sp.GetService<TracerProvider>());
|
||||
})
|
||||
.Build();
|
||||
|
||||
Assert.True(innerTestExecuted);
|
||||
|
||||
Assert.Throws<NotSupportedException>(() => provider.GetServiceProvider()?.GetService<TracerProvider>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TracerProviderNestedResolutionUsingConfigureTest()
|
||||
{
|
||||
bool innerTestExecuted = false;
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
serviceCollection.ConfigureOpenTelemetryTracing(builder =>
|
||||
{
|
||||
builder.ConfigureBuilder((sp, builder) =>
|
||||
{
|
||||
innerTestExecuted = true;
|
||||
Assert.Throws<NotSupportedException>(() => sp.GetService<TracerProvider>());
|
||||
});
|
||||
});
|
||||
|
||||
using var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var resolvedProvider = serviceProvider.GetRequiredService<TracerProvider>();
|
||||
|
||||
Assert.True(innerTestExecuted);
|
||||
}
|
||||
|
||||
private static void RunBuilderServiceLifecycleTest(
|
||||
TracerProviderBuilder builder,
|
||||
Func<TracerProviderSdk> buildFunc,
|
||||
|
|
|
|||
Loading…
Reference in New Issue