3

In a ASP.NET Core 6 project using a WebApplicationBuilder

<Project Sdk="Microsoft.NET.Sdk.Web">

I am able to get a logger right after it is defined. This is very useful so I can use the logger in the rest of the application configuration.

   _builder.Logging.ClearProviders()
      .AddLog4Net();

   var logger = _builder.Logging.Services.BuildServiceProvider()
       .GetService<ILoggerFactory>()
       .CreateLogger<MyType>();

But when I define a Worker Service using a IHostBuilder

<Project Sdk="Microsoft.NET.Sdk.Worker">

I am only able to configure logging, and cannot get a logger before after _builder.Build() which is to late.

_builder.ConfigureLogging(x =>
{
   x.ClearProviders();
   x.AddLog4Net();
};

var Logger = _builder.Build().Services.GetRequiredService<ILoggerFactory>()
    .CreateLogger<MyType>();

Why are these builders different and how do I get the logger right after defining it with ConfigureLogging?

Stig
  • 1,974
  • 2
  • 23
  • 50
  • 1
    You can always create [logger manually](https://stackoverflow.com/a/70635137/2501279). It will lead to some code duplication but should be much better approach then building multiple service providers. – Guru Stron Aug 27 '22 at 19:20

1 Answers1

2

I am able to get a logger right after it is defined. This is very useful so I can use the logger in the rest of the application configuration.

This isn't the right thing to do. The logging is already going to be available in all parts of the application because its configured up front. You should have very little reason to call BuildServiceProvider in your own code. There are special cases, but if you're doing it, it's often a sign that something isn't being done correctly. Why? Well it creates another copy of the service provider, which means a different copy of each singleton service and you're not disposing it.

Why are these builders different and how do I get the logger right after defining it with ConfigureLogging?

We've slowly moving away from the deferred hosting building model (callbacks) and moving to something more linear but we haven't done this change for the worker service as yet.

That said, there is an issue with not being able to log at startup because the logger is part of that initial wire up logic (chicken and egg problem). You can create another logging for startup purposes and then use the logger created by the DI container throughout the rest of your application.

davidfowl
  • 37,120
  • 7
  • 93
  • 103
  • Agree normally I wouldn't call BuildServiceProvider, but I need to if I want the logger just defined. If I create another logger (and ILoggerFactory) then I cannot use the convenient AddLog4Net, AddEventLog etc right? – Stig Aug 27 '22 at 17:46
  • Most code I read on various blogs doesn't address proper failure logging on start-up, due the chicken and egg problem. – Stig Aug 27 '22 at 17:47
  • That's right most code does not log startup errors that happen outside of the host code itself. If you understand the implications of creating another DI universe you can continue what you're doing. – davidfowl Aug 27 '22 at 18:07
  • So what to do with the deferred hosting builder? Can I somehow use AddLog4Net (and AddEventLog) or do I have to create the logger by hand (using log4net api etc) – Stig Aug 27 '22 at 18:12