Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ public void RegisterProvider(LoggerProviderSdk loggerProvider)
this.loggerProvider = loggerProvider;
}

public void UnregisterProvider(LoggerProviderSdk loggerProvider)
{
if (ReferenceEquals(this.loggerProvider, loggerProvider))
{
this.loggerProvider = null;
}
}

public override LoggerProviderBuilder AddInstrumentation<TInstrumentation>(Func<TInstrumentation> instrumentationFactory)
{
var instance = instrumentationFactory();
Expand Down
1 change: 1 addition & 0 deletions src/OpenTelemetry/Logs/LoggerProviderSdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public LoggerProviderSdk(
}
catch (Exception)
{
state.UnregisterProvider(this);
Comment thread
Copilot marked this conversation as resolved.
Outdated
Comment thread
martincostello marked this conversation as resolved.
Outdated
this.DisposeBuiltState(state);
throw;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,44 @@ public void CircularReferenceTest(bool requestLoggerProviderDirectly)
Assert.IsType<TestLogProcessorWithILoggerFactoryDependency>(loggerProvider.Processor);
}

[Fact]
public void LazyProviderRetriesAfterFailedBuildTest()
{
var configureInvocationCount = 0;
TestLogProcessor? configuredProcessor = null;
var services = new ServiceCollection();

services.AddLogging(logging => logging.AddOpenTelemetry());

services.ConfigureOpenTelemetryLoggerProvider((sp, builder) =>
{
if (Interlocked.Increment(ref configureInvocationCount) == 1)
{
throw new InvalidOperationException("The first logger provider build is expected to fail.");
}

configuredProcessor = new TestLogProcessor();
builder.AddProcessor(configuredProcessor);
});

using var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();

Assert.Throws<InvalidOperationException>(() => loggerFactory.CreateLogger("FirstLogger"));

var logger = loggerFactory.CreateLogger("SecondLogger");
logger.Log(
LogLevel.Information,
new EventId(1),
"This record should be processed.",
exception: null,
static (state, _) => state);

var processor = Assert.IsType<TestLogProcessor>(configuredProcessor);
Assert.Equal(2, configureInvocationCount);
Assert.Equal(1, processor.OnEndCount);
}

[Theory]
[InlineData(true, false)]
[InlineData(false, true)]
Expand Down Expand Up @@ -388,6 +426,15 @@ private sealed class TestLogProcessor : BaseProcessor<LogRecord>
{
public bool Disposed;

public int OnEndCount;

public override void OnEnd(LogRecord data)
{
this.OnEndCount++;

base.OnEnd(data);
}

protected override void Dispose(bool disposing)
{
this.Disposed = true;
Expand Down
Loading