serilog-extensions-logging icon indicating copy to clipboard operation
serilog-extensions-logging copied to clipboard

Collision with Microsoft.Extensions.Telemetry

Open bdovaz opened this issue 1 year ago • 2 comments
trafficstars

https://www.nuget.org/packages/Microsoft.Extensions.Telemetry/

This library provides advanced logging and telemetry enrichment capabilities for .NET applications. It allows for detailed and configurable enrichment of log entries, along with enhanced latency monitoring and logging features. It is built for applications needing sophisticated telemetry and logging insights.

This package replaces the ILoggerFactory implementation and causes it to collide with the ILoggerFactory implementation of this repository:

https://github.com/dotnet/extensions/blob/5752f1d4ac15686432a228099386c709c7dacf74/src/Libraries/Microsoft.Extensions.Telemetry/Logging/LoggingEnrichmentExtensions.cs#L37

I would like to be able to use the Telemetry package at the same time as this Serilog package.

The use of Serilog in my case is because of the need to use certain Sinks (example: OpenSearch), that is why I would like to use all the possible functionalities of Microsoft.Extensions.Logging and Microsoft.Extensions.Telemetry without coupling to Serilog more than necessary.

bdovaz avatar May 19 '24 20:05 bdovaz

Hi @bdovaz,

If you just want to use Serilog as a sink, then adding it via your ILoggingBuilder rather than at the host level will do what you need:

builder.Logging.AddSerilog(..)

The downside is that you will now have two logging frameworks in play, with their own filters, minimum levels, etc., but you should be able to work around that reasonably easily.

Hope this helps, Nick

nblumhardt avatar May 19 '24 23:05 nblumhardt

Hi @bdovaz

Not sure if this is still relevant to you but we were able to at least make some progress using ILoggerFactory from Microsoft.Extensions.Telemetry package but using Serilog sinks.

The workaround which has not been thoroughly tested yet but seems to yield promising results but which requires a bit of boilerplate.

Create a custom logger provider:

/// <summary>
/// Custom <see cref="ILoggerProvider"/> which lazily configures <see cref="SerilogLoggerProvider"/> using the provided <paramref name="configureLogger"/>
/// </summary>
/// <param name="serviceProvider">The built service provider</param>
/// <param name="configureLogger">Configuration action to configure the <see cref="LoggerConfiguration"/></param>
/// <param name="setupAsGlobalSerilogLogger">Whether or not to set the created <see cref="Serilog.ILogger"/> as value for global <see cref="Log.Logger"/></param>
public sealed class CustomSerilogLoggerProvider(
    IServiceProvider serviceProvider,
    Action<IServiceProvider, LoggerConfiguration> configureLogger,
    bool setupAsGlobalSerilogLogger
    ) : ILoggerProvider
{
    private SerilogLoggerProvider? _provider;
    private SerilogLoggerProvider Provider => _provider ??= CreateProvider();

    private Serilog.Core.Logger? _logger;
    internal Serilog.Core.Logger SerilogLogger => _logger ??= CreateLogger();

    public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) =>
        Provider.CreateLogger(categoryName);

    private SerilogLoggerProvider CreateProvider() => new(
        SerilogLogger,
        dispose: !setupAsGlobalSerilogLogger
    );

    private Serilog.Core.Logger CreateLogger()
    {
        var logger = CreateConfiguration().CreateLogger();

        if (setupAsGlobalSerilogLogger)
        {
            Log.Logger = logger;
        }

        return logger;
    }

    private LoggerConfiguration CreateConfiguration()
    {
        var configuration = new LoggerConfiguration();
        configureLogger(serviceProvider, configuration);
        return configuration;
    }

    public void Dispose()
    {
        _provider?.Dispose();
    }
}

Create custom extension for ILoggingBuilder to setup the custom provider:

public static class CustomLoggingBuilderExtensions
{
    public static ILoggingBuilder AddCustomSerilog(
        this ILoggingBuilder builder,
        Action<IServiceProvider, LoggerConfiguration> configureLogger,
        bool setupAsGlobalSerilogLogger = false)
    {
        builder.Services.AddSingleton(container => new CustomSerilogLoggerProvider(
            container,
            configureLogger,
            setupAsGlobalSerilogLogger
        ));

        builder.Services.AddSingleton<ILoggerProvider>(container => container.GetRequiredService<CustomSerilogLoggerProvider>());

        builder.Services.AddSingleton<Serilog.ILogger>(container =>
            container.GetRequiredService<CustomSerilogLoggerProvider>().SerilogLogger
        );

        builder.AddFilter<CustomSerilogLoggerProvider>(null, LogLevel.Trace);

        // If using SerilogRequestLogging
        // Based on
        // https://github.com/serilog/serilog-extensions-hosting/blob/87e316f7d31ae431747d1106976dfceffdecc32c/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs#L218
        builder.Services.AddSingleton(provider => new DiagnosticContext(provider.GetService<Serilog.ILogger>()));
        builder.Services.AddSingleton<IDiagnosticContext>(provider => provider.GetRequiredService<DiagnosticContext>());

        return builder;
    }
}

And then utilize that


builder.Services.AddLogging(logging =>
{
   // ... other logging setup ...
   logging.AddCustomSerilog((provider, config) => 
   {
       // configure LoggerConfiguration    
   });
});

Using this at least allowed us to utilize Microsoft.Extensions.Compliance.Redaction with some [LoggerMessage] generated log messages successfully, without these adjustments, redacted data would be completely missing from the logs because the "ExtendedLogger" seems to be the only one able to handle these. (https://github.com/dotnet/extensions/blob/c08790cf79d2d8feaa53751f039f38638741a154/src/Libraries/Microsoft.Extensions.Telemetry/Logging/ExtendedLogger.cs)

vipentti avatar Dec 19 '24 14:12 vipentti

I am trying to utilize Microsoft.Extensions.Telemetry library as well to make use of Microsoft.Extensions.Compliance.Redaction capabilities.

b1tzer0 avatar Aug 20 '25 14:08 b1tzer0