Custom logger using a service needs same instance

105 views Asked by At

I wrote a custom logger using the ILoggingBuilder and the ILoggerProvider pattern as describe in the .net documentation

My logger needs a service build in the app, I was able to pass the service using the ServiceProvider but unfortunetly the instance is duplicated (even if the service is declared as a singleton)

Here is a sample of the code :

return Host.CreateDefaultBuilder(args)                
                .ConfigureHostConfiguration(configurationBuilder =>
                {
                    if (args is not null)
                    {
                        _ = configurationBuilder.AddCommandLine(args);
                    }
                })
                .ConfigureAppConfiguration((context, builder) =>
                    builder.SetBasePath(AppContext.BaseDirectory)
                        .AddJsonFile("appsettings.json", optional: true))                

                .ConfigureServices((hostContext, services) =>
                {
                    
                    services.AddServices();
                    serviceProvider = services.BuildServiceProvider();
                }
                )
                .ConfigureLogging((hostContext, loggingFactory) =>
                {

                    loggingFactory
                            .AddConsole()
                            .AddEventLog()                            
                            .AddFile("Logs/worker-{Date}.txt")
                            .AddCustomFormatter(serviceProvider.GetService<IMycustomService>());
                });

I've tried many approches but I was not able to use the same instance in my servicesColletion and in my custom logger

Any hep would be greatly appreciated

1

There are 1 answers

0
Prolog On

I'm assuming that inside AddCustomFormatter() you are manually creating an instance of your logging provider and that's why you are passing the resolved instance of IMyCustomService. Instead of doing it, let DI handle it for you. Register your custom logger provider like this, to add it to the list of ILoggerProvider available implementations:

public static ILoggingBuilder AddCustomFormatter(this ILoggingBuilder builder)
{
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, CustomLoggerProvider>());

    return builder;
}

Then your custom logger provider can require IMyCustomService without the need for explicit supplying of its dependencies.

public class CustomLoggerProvider : ILoggerProvider
{
    private readonly IMyCustomService myCustomService;

    public CustomLoggerProvider(IMyCustomService myCustomService)
    {
        this.myCustomService = myCustomService;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return new CustomLogger(myCustomService);
    }

    public void Dispose()
    {
    }
}