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.AddOpenTelemetryProviderBuilderServices();
|
||||||
|
|
||||||
services.RegisterOptionsFactory(configuration => new ExportActivityProcessorOptions(configuration));
|
services.RegisterOptionsFactory(configuration => new ExportActivityProcessorOptions(configuration));
|
||||||
|
services.TryAddSingleton<TracerProviderBuilderState>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,9 @@ namespace OpenTelemetry.Trace
|
||||||
this.State = state;
|
this.State = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This ctor is for AddOpenTelemetryTracing scenario where the builder
|
// This ctor is for ConfigureOpenTelemetryTracing +
|
||||||
// is bound to an external service collection.
|
// AddOpenTelemetryTracing scenarios where the builder is bound to an
|
||||||
|
// external service collection.
|
||||||
internal TracerProviderBuilderBase(IServiceCollection services)
|
internal TracerProviderBuilderBase(IServiceCollection services)
|
||||||
{
|
{
|
||||||
Guard.ThrowIfNull(services);
|
Guard.ThrowIfNull(services);
|
||||||
|
|
@ -65,6 +66,8 @@ namespace OpenTelemetry.Trace
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
|
|
||||||
services.AddOpenTelemetryTracerProviderBuilderServices();
|
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.services = services;
|
||||||
this.ownsServices = true;
|
this.ownsServices = true;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ namespace OpenTelemetry.Trace
|
||||||
internal Sampler? Sampler;
|
internal Sampler? Sampler;
|
||||||
internal bool SetErrorStatusOnException;
|
internal bool SetErrorStatusOnException;
|
||||||
|
|
||||||
|
private bool hasEnteredBuildPhase;
|
||||||
private TracerProviderBuilderSdk? builder;
|
private TracerProviderBuilderSdk? builder;
|
||||||
|
|
||||||
public TracerProviderBuilderState(IServiceProvider serviceProvider)
|
public TracerProviderBuilderState(IServiceProvider serviceProvider)
|
||||||
|
|
@ -49,6 +50,16 @@ namespace OpenTelemetry.Trace
|
||||||
|
|
||||||
public TracerProviderBuilderSdk Builder => this.builder ??= new TracerProviderBuilderSdk(this);
|
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(
|
public void AddInstrumentation(
|
||||||
string instrumentationName,
|
string instrumentationName,
|
||||||
string instrumentationVersion,
|
string instrumentationVersion,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using OpenTelemetry.Internal;
|
using OpenTelemetry.Internal;
|
||||||
using OpenTelemetry.Resources;
|
using OpenTelemetry.Resources;
|
||||||
|
|
||||||
|
|
@ -47,6 +48,9 @@ namespace OpenTelemetry.Trace
|
||||||
{
|
{
|
||||||
Debug.Assert(serviceProvider != null, "serviceProvider was null");
|
Debug.Assert(serviceProvider != null, "serviceProvider was null");
|
||||||
|
|
||||||
|
var state = serviceProvider!.GetRequiredService<TracerProviderBuilderState>();
|
||||||
|
state.CheckForCircularBuild();
|
||||||
|
|
||||||
this.ServiceProvider = serviceProvider!;
|
this.ServiceProvider = serviceProvider!;
|
||||||
|
|
||||||
if (ownsServiceProvider)
|
if (ownsServiceProvider)
|
||||||
|
|
@ -57,8 +61,6 @@ namespace OpenTelemetry.Trace
|
||||||
|
|
||||||
OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent("Building TracerProvider.");
|
OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent("Building TracerProvider.");
|
||||||
|
|
||||||
var state = new TracerProviderBuilderState(serviceProvider!);
|
|
||||||
|
|
||||||
TracerProviderBuilderServiceCollectionHelper.InvokeRegisteredConfigureStateCallbacks(
|
TracerProviderBuilderServiceCollectionHelper.InvokeRegisteredConfigureStateCallbacks(
|
||||||
serviceProvider!,
|
serviceProvider!,
|
||||||
state);
|
state);
|
||||||
|
|
|
||||||
|
|
@ -455,6 +455,56 @@ namespace OpenTelemetry.Trace.Tests
|
||||||
Assert.True(configureBuilderCalled);
|
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(
|
private static void RunBuilderServiceLifecycleTest(
|
||||||
TracerProviderBuilder builder,
|
TracerProviderBuilder builder,
|
||||||
Func<TracerProviderSdk> buildFunc,
|
Func<TracerProviderSdk> buildFunc,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue