[logging] UseOpenTelemetry extension & WithLogging default behavior (#5072)
This commit is contained in:
parent
39c77d40f8
commit
a47b222101
|
|
@ -1,2 +1,3 @@
|
|||
OpenTelemetry.OpenTelemetryBuilder.WithLogging() -> OpenTelemetry.OpenTelemetryBuilder!
|
||||
OpenTelemetry.OpenTelemetryBuilder.WithLogging(System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
|
||||
OpenTelemetry.OpenTelemetryBuilder.WithLogging(System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>? configureBuilder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configureOptions) -> OpenTelemetry.OpenTelemetryBuilder!
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@
|
|||
APIs.
|
||||
([#4958](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4958))
|
||||
|
||||
* The `OpenTelemetryBuilder.WithLogging` experimental API method will now
|
||||
register an `ILoggerProvider` named 'OpenTelemetry' into the
|
||||
`IServiceCollection` to enable `ILoggerFactory` integration.
|
||||
([#5072](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5072))
|
||||
|
||||
## 1.7.0-alpha.1
|
||||
|
||||
Released 2023-Oct-16
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.Metrics;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenTelemetry.Internal;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Metrics;
|
||||
|
|
@ -146,10 +147,17 @@ public sealed class OpenTelemetryBuilder
|
|||
/// Adds logging services into the builder.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>WARNING</b>: This is an experimental API which might change or be removed in the future. Use at your own risk.</para>
|
||||
/// Note: This is safe to be called multiple times and by library authors.
|
||||
/// <para><b>WARNING</b>: This is an experimental API which might change or
|
||||
/// be removed in the future. Use at your own risk.</para>
|
||||
/// Notes:
|
||||
/// <list type="bullet">
|
||||
/// <item>This is safe to be called multiple times and by library authors.
|
||||
/// Only a single <see cref="LoggerProvider"/> will be created for a given
|
||||
/// <see cref="IServiceCollection"/>.
|
||||
/// <see cref="IServiceCollection"/>.</item>
|
||||
/// <item>This method automatically registers an <see
|
||||
/// cref="ILoggerProvider"/> named 'OpenTelemetry' into the <see
|
||||
/// cref="IServiceCollection"/>.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
|
||||
/// calls.</returns>
|
||||
|
|
@ -159,16 +167,22 @@ public sealed class OpenTelemetryBuilder
|
|||
/// Adds logging services into the builder.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: This is safe to be called multiple times and by library authors.
|
||||
/// Notes:
|
||||
/// <list type="bullet">
|
||||
/// <item>This is safe to be called multiple times and by library authors.
|
||||
/// Only a single <see cref="LoggerProvider"/> will be created for a given
|
||||
/// <see cref="IServiceCollection"/>.
|
||||
/// <see cref="IServiceCollection"/>.</item>
|
||||
/// <item>This method automatically registers an <see
|
||||
/// cref="ILoggerProvider"/> named 'OpenTelemetry' into the <see
|
||||
/// cref="IServiceCollection"/>.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
|
||||
/// calls.</returns>
|
||||
internal
|
||||
#endif
|
||||
OpenTelemetryBuilder WithLogging()
|
||||
=> this.WithLogging(b => { });
|
||||
=> this.WithLogging(configureBuilder: null, configureOptions: null);
|
||||
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
|
|
@ -195,9 +209,40 @@ public sealed class OpenTelemetryBuilder
|
|||
{
|
||||
Guard.ThrowIfNull(configure);
|
||||
|
||||
var builder = new LoggerProviderBuilderBase(this.Services);
|
||||
return this.WithLogging(configureBuilder: configure, configureOptions: null);
|
||||
}
|
||||
|
||||
configure(builder);
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
/// Adds logging services into the builder.
|
||||
/// </summary>
|
||||
/// <remarks><inheritdoc cref="WithLogging()" path="/remarks"/></remarks>
|
||||
/// <param name="configureBuilder">Optional <see
|
||||
/// cref="LoggerProviderBuilder"/> configuration callback.</param>
|
||||
/// <param name="configureOptions">Optional <see
|
||||
/// cref="OpenTelemetryLoggerOptions"/> configuration callback.</param>
|
||||
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
|
||||
/// calls.</returns>
|
||||
public
|
||||
#else
|
||||
/// <summary>
|
||||
/// Adds logging services into the builder.
|
||||
/// </summary>
|
||||
/// <remarks><inheritdoc cref="WithLogging()" path="/remarks"/></remarks>
|
||||
/// <param name="configureBuilder">Optional <see
|
||||
/// cref="LoggerProviderBuilder"/> configuration callback.</param>
|
||||
/// <param name="configureOptions">Optional <see
|
||||
/// cref="OpenTelemetryLoggerOptions"/> configuration callback.</param>
|
||||
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
|
||||
/// calls.</returns>
|
||||
internal
|
||||
#endif
|
||||
OpenTelemetryBuilder WithLogging(
|
||||
Action<LoggerProviderBuilder>? configureBuilder,
|
||||
Action<OpenTelemetryLoggerOptions>? configureOptions)
|
||||
{
|
||||
this.Services.AddLogging(
|
||||
logging => logging.UseOpenTelemetry(configureBuilder, configureOptions));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,3 +40,6 @@ override OpenTelemetry.Metrics.AlwaysOnExemplarFilter.ShouldSample(double value,
|
|||
override OpenTelemetry.Metrics.AlwaysOnExemplarFilter.ShouldSample(long value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
|
||||
override OpenTelemetry.Metrics.TraceBasedExemplarFilter.ShouldSample(double value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
|
||||
override OpenTelemetry.Metrics.TraceBasedExemplarFilter.ShouldSample(long value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
|
||||
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.UseOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
|
||||
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.UseOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
|
||||
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.UseOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>? configureBuilder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configureOptions) -> Microsoft.Extensions.Logging.ILoggingBuilder!
|
||||
|
|
|
|||
|
|
@ -64,6 +64,18 @@
|
|||
[#4563](https://github.com/open-telemetry/opentelemetry-dotnet/issues/4563).
|
||||
([#5089](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5089))
|
||||
|
||||
* Added the `ILoggingBuilder.UseOpenTelemetry` experimental API extension for
|
||||
registering OpenTelemetry `ILogger` integration using `LoggerProviderBuilder`
|
||||
which supports the full DI (`IServiceCollection` \ `IServiceProvider`) API
|
||||
surface (mirrors tracing & metrics).
|
||||
([#5072](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5072))
|
||||
|
||||
* Changed the `ILoggingBuilder` registration extensions (`AddOpenTelemetry` &
|
||||
`UseOpenTelemetry`) to fire the optional `OpenTelemetryLoggerOptions`
|
||||
configuration delegate AFTER the "Logging:OpenTelemetry" `IConfiguration`
|
||||
section has been applied.
|
||||
([#5072](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5072))
|
||||
|
||||
## 1.7.0-alpha.1
|
||||
|
||||
Released 2023-Oct-16
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
#if NET6_0_OR_GREATER
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
#endif
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
using System.ComponentModel;
|
||||
#endif
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -48,6 +51,11 @@ public static class OpenTelemetryLoggingExtensions
|
|||
/// </remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
// todo: [Obsolete("Call UseOpenTelemetry instead this method will be removed in a future version.")]
|
||||
// Note: We hide AddOpenTelemetry from IDEs using EditorBrowsable when UseOpenTelemetry is present to reduce confusion.
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
#endif
|
||||
public static ILoggingBuilder AddOpenTelemetry(
|
||||
this ILoggingBuilder builder)
|
||||
=> AddOpenTelemetryInternal(builder, configureBuilder: null, configureOptions: null);
|
||||
|
|
@ -59,11 +67,101 @@ public static class OpenTelemetryLoggingExtensions
|
|||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <param name="configure">Optional configuration action.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
// todo: [Obsolete("Call UseOpenTelemetry instead this method will be removed in a future version.")]
|
||||
// Note: We hide AddOpenTelemetry from IDEs using EditorBrowsable when UseOpenTelemetry is present to reduce confusion.
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
#endif
|
||||
public static ILoggingBuilder AddOpenTelemetry(
|
||||
this ILoggingBuilder builder,
|
||||
Action<OpenTelemetryLoggerOptions>? configure)
|
||||
=> AddOpenTelemetryInternal(builder, configureBuilder: null, configureOptions: configure);
|
||||
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>WARNING</b>: This is an experimental API which might change or be removed in the future. Use at your own risk.</para>
|
||||
/// Note: This is safe to be called multiple times and by library authors.
|
||||
/// Only a single <see cref="OpenTelemetryLoggerProvider"/> will be created
|
||||
/// for a given <see cref="IServiceCollection"/>.
|
||||
/// </remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
public
|
||||
#else
|
||||
/// <summary>
|
||||
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: This is safe to be called multiple times and by library authors.
|
||||
/// Only a single <see cref="OpenTelemetryLoggerProvider"/> will be created
|
||||
/// for a given <see cref="IServiceCollection"/>.
|
||||
/// </remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
internal
|
||||
#endif
|
||||
static ILoggingBuilder UseOpenTelemetry(
|
||||
this ILoggingBuilder builder)
|
||||
=> AddOpenTelemetryInternal(builder, configureBuilder: null, configureOptions: null);
|
||||
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <remarks><inheritdoc cref="UseOpenTelemetry(ILoggingBuilder)" path="/remarks"/></remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <param name="configure">Optional <see cref="LoggerProviderBuilder"/> configuration action.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
public
|
||||
#else
|
||||
/// <summary>
|
||||
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <remarks><inheritdoc cref="UseOpenTelemetry(ILoggingBuilder)" path="/remarks"/></remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <param name="configure"><see cref="LoggerProviderBuilder"/> configuration action.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
internal
|
||||
#endif
|
||||
static ILoggingBuilder UseOpenTelemetry(
|
||||
this ILoggingBuilder builder,
|
||||
Action<LoggerProviderBuilder> configure)
|
||||
{
|
||||
Guard.ThrowIfNull(configure);
|
||||
|
||||
return AddOpenTelemetryInternal(builder, configureBuilder: configure, configureOptions: null);
|
||||
}
|
||||
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <remarks><inheritdoc cref="UseOpenTelemetry(ILoggingBuilder)" path="/remarks"/></remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <param name="configureBuilder">Optional <see cref="LoggerProviderBuilder"/> configuration action.</param>
|
||||
/// <param name="configureOptions">Optional <see cref="OpenTelemetryLoggerOptions"/> configuration action.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
public
|
||||
#else
|
||||
/// <summary>
|
||||
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <remarks><inheritdoc cref="UseOpenTelemetry(ILoggingBuilder)" path="/remarks"/></remarks>
|
||||
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
|
||||
/// <param name="configureBuilder">Optional <see cref="LoggerProviderBuilder"/> configuration action.</param>
|
||||
/// <param name="configureOptions">Optional <see cref="OpenTelemetryLoggerOptions"/> configuration action.</param>
|
||||
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
|
||||
internal
|
||||
#endif
|
||||
static ILoggingBuilder UseOpenTelemetry(
|
||||
this ILoggingBuilder builder,
|
||||
Action<LoggerProviderBuilder>? configureBuilder,
|
||||
Action<OpenTelemetryLoggerOptions>? configureOptions)
|
||||
=> AddOpenTelemetryInternal(builder, configureBuilder, configureOptions);
|
||||
|
||||
private static ILoggingBuilder AddOpenTelemetryInternal(
|
||||
ILoggingBuilder builder,
|
||||
Action<LoggerProviderBuilder>? configureBuilder,
|
||||
|
|
@ -75,19 +173,19 @@ public static class OpenTelemetryLoggingExtensions
|
|||
|
||||
var services = builder.Services;
|
||||
|
||||
if (configureOptions != null)
|
||||
{
|
||||
// TODO: Move this below the RegisterLoggerProviderOptions call so
|
||||
// that user-supplied delegate fires AFTER the options are bound to
|
||||
// Logging:OpenTelemetry configuration.
|
||||
services.Configure(configureOptions);
|
||||
}
|
||||
|
||||
// Note: This will bind logger options element (eg "Logging:OpenTelemetry") to OpenTelemetryLoggerOptions
|
||||
RegisterLoggerProviderOptions(services);
|
||||
|
||||
services.AddOpenTelemetrySharedProviderBuilderServices();
|
||||
|
||||
if (configureOptions != null)
|
||||
{
|
||||
// Note: Order is important here so that user-supplied delegate
|
||||
// fires AFTER the options are bound to Logging:OpenTelemetry
|
||||
// configuration.
|
||||
services.Configure(configureOptions);
|
||||
}
|
||||
|
||||
var loggingBuilder = new LoggerProviderBuilderBase(services).ConfigureBuilder(
|
||||
(sp, logging) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ public class OpenTelemetryServicesExtensionsTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddOpenTelemetry_WithLogging_HostConfigurationHonoredTest()
|
||||
public void AddOpenTelemetry_WithLogging_HostConfigurationHonoredTest()
|
||||
{
|
||||
bool configureBuilderCalled = false;
|
||||
|
||||
|
|
@ -416,14 +416,8 @@ public class OpenTelemetryServicesExtensionsTests
|
|||
|
||||
var host = builder.Build();
|
||||
|
||||
Assert.False(configureBuilderCalled);
|
||||
|
||||
await host.StartAsync();
|
||||
|
||||
Assert.True(configureBuilderCalled);
|
||||
|
||||
await host.StopAsync();
|
||||
|
||||
host.Dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#nullable enable
|
||||
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit;
|
||||
|
|
@ -25,16 +26,25 @@ namespace OpenTelemetry.Logs.Tests;
|
|||
|
||||
public sealed class OpenTelemetryLoggingExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void ServiceCollectionAddOpenTelemetryNoParametersTest()
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void ServiceCollectionAddOpenTelemetryNoParametersTest(bool callUseExtension)
|
||||
{
|
||||
bool optionsCallbackInvoked = false;
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
serviceCollection.AddLogging(configure =>
|
||||
serviceCollection.AddLogging(logging =>
|
||||
{
|
||||
configure.AddOpenTelemetry();
|
||||
if (callUseExtension)
|
||||
{
|
||||
logging.UseOpenTelemetry();
|
||||
}
|
||||
else
|
||||
{
|
||||
logging.AddOpenTelemetry();
|
||||
}
|
||||
});
|
||||
|
||||
serviceCollection.Configure<OpenTelemetryLoggerOptions>(options =>
|
||||
|
|
@ -52,10 +62,16 @@ public sealed class OpenTelemetryLoggingExtensionsTests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, 0)]
|
||||
[InlineData(1, 1)]
|
||||
[InlineData(5, 5)]
|
||||
public void ServiceCollectionAddOpenTelemetryConfigureActionTests(int numberOfBuilderRegistrations, int numberOfOptionsRegistrations)
|
||||
[InlineData(false, 1, 0)]
|
||||
[InlineData(false, 1, 1)]
|
||||
[InlineData(false, 5, 5)]
|
||||
[InlineData(true, 1, 0)]
|
||||
[InlineData(true, 1, 1)]
|
||||
[InlineData(true, 5, 5)]
|
||||
public void ServiceCollectionAddOpenTelemetryConfigureActionTests(
|
||||
bool callUseExtension,
|
||||
int numberOfBuilderRegistrations,
|
||||
int numberOfOptionsRegistrations)
|
||||
{
|
||||
int configureCallbackInvocations = 0;
|
||||
int optionsCallbackInvocations = 0;
|
||||
|
|
@ -63,11 +79,18 @@ public sealed class OpenTelemetryLoggingExtensionsTests
|
|||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
serviceCollection.AddLogging(configure =>
|
||||
serviceCollection.AddLogging(logging =>
|
||||
{
|
||||
for (int i = 0; i < numberOfBuilderRegistrations; i++)
|
||||
{
|
||||
configure.AddOpenTelemetry(ConfigureCallback);
|
||||
if (callUseExtension)
|
||||
{
|
||||
logging.UseOpenTelemetry(configureBuilder: null, configureOptions: ConfigureCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
logging.AddOpenTelemetry(ConfigureCallback);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -116,6 +139,92 @@ public sealed class OpenTelemetryLoggingExtensionsTests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UseOpenTelemetryDependencyInjectionTest()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
serviceCollection.AddLogging(logging =>
|
||||
{
|
||||
logging.UseOpenTelemetry(builder =>
|
||||
{
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<TestLogProcessor>();
|
||||
});
|
||||
|
||||
builder.ConfigureBuilder((sp, builder) =>
|
||||
{
|
||||
builder.AddProcessor(
|
||||
sp.GetRequiredService<TestLogProcessor>());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
using var sp = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var loggerProvider = sp.GetRequiredService<LoggerProvider>() as LoggerProviderSdk;
|
||||
|
||||
Assert.NotNull(loggerProvider);
|
||||
|
||||
Assert.NotNull(loggerProvider.Processor);
|
||||
|
||||
Assert.True(loggerProvider.Processor is TestLogProcessor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UseOpenTelemetryOptionsOrderingTest()
|
||||
{
|
||||
int currentIndex = -1;
|
||||
int beforeDelegateIndex = -1;
|
||||
int extensionDelegateIndex = -1;
|
||||
int afterDelegateIndex = -1;
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?> { ["Logging:OpenTelemetry:IncludeFormattedMessage"] = "true" })
|
||||
.Build();
|
||||
|
||||
serviceCollection.Configure<OpenTelemetryLoggerOptions>(o =>
|
||||
{
|
||||
// Verify this fires BEFORE options are bound
|
||||
Assert.False(o.IncludeFormattedMessage);
|
||||
|
||||
beforeDelegateIndex = ++currentIndex;
|
||||
});
|
||||
|
||||
serviceCollection.AddLogging(logging =>
|
||||
{
|
||||
// Note: Typically the host binds logging configuration to the
|
||||
// "Logging" section but since we aren't using a host we do this
|
||||
// manually.
|
||||
logging.AddConfiguration(config.GetSection("Logging"));
|
||||
|
||||
logging.UseOpenTelemetry(
|
||||
configureBuilder: null,
|
||||
configureOptions: o =>
|
||||
{
|
||||
// Verify this fires AFTER options are bound
|
||||
Assert.True(o.IncludeFormattedMessage);
|
||||
|
||||
extensionDelegateIndex = ++currentIndex;
|
||||
});
|
||||
});
|
||||
|
||||
serviceCollection.Configure<OpenTelemetryLoggerOptions>(o => afterDelegateIndex = ++currentIndex);
|
||||
|
||||
using var sp = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var loggerProvider = sp.GetRequiredService<LoggerProvider>() as LoggerProviderSdk;
|
||||
|
||||
Assert.NotNull(loggerProvider);
|
||||
|
||||
Assert.Equal(0, beforeDelegateIndex);
|
||||
Assert.Equal(1, extensionDelegateIndex);
|
||||
Assert.Equal(2, afterDelegateIndex);
|
||||
}
|
||||
|
||||
// This test validates that the OpenTelemetryLoggerOptions contains only primitive type properties.
|
||||
// This is necessary to ensure trim correctness since that class is effectively deserialized from
|
||||
// configuration. The top level properties are ensured via annotation on the RegisterProviderOptions API
|
||||
|
|
@ -136,11 +245,11 @@ public sealed class OpenTelemetryLoggingExtensionsTests
|
|||
// arrange
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddSingleton<MyProcessor>();
|
||||
services.AddSingleton<TestLogProcessor>();
|
||||
|
||||
services.AddLogging(logging =>
|
||||
logging.AddOpenTelemetry(
|
||||
o => o.AddProcessor(sp => sp.GetRequiredService<MyProcessor>())));
|
||||
o => o.AddProcessor(sp => sp.GetRequiredService<TestLogProcessor>())));
|
||||
|
||||
// act
|
||||
using var sp = services.BuildServiceProvider();
|
||||
|
|
@ -150,7 +259,7 @@ public sealed class OpenTelemetryLoggingExtensionsTests
|
|||
// assert
|
||||
Assert.NotNull(loggerProvider);
|
||||
Assert.NotNull(loggerProvider.Processor);
|
||||
Assert.True(loggerProvider.Processor is MyProcessor);
|
||||
Assert.True(loggerProvider.Processor is TestLogProcessor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -170,7 +279,7 @@ public sealed class OpenTelemetryLoggingExtensionsTests
|
|||
Assert.Throws<ArgumentNullException>(() => sp.GetRequiredService<LoggerProvider>() as LoggerProviderSdk);
|
||||
}
|
||||
|
||||
private class MyProcessor : BaseProcessor<LogRecord>
|
||||
private class TestLogProcessor : BaseProcessor<LogRecord>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue