dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.35k stars 9.99k forks source link

Logging startup errors through Microsoft.Extensions.Logging #18593

Closed ThomasArdal closed 4 years ago

ThomasArdal commented 4 years ago

I'm wondering why errors during initialization/startup aren't logged to Microsoft.Extensions.Logging in my set up. To test this scenario, I'm configuring logging in my Program.cs file (ASP.NET Core 3.1 app):

.ConfigureLogging((ctx, logging) =>
{
    logging.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
}

The MyLoggerProvider class looks like this:

internal class MyLoggerProvider : ILoggerProvider
{
    public ILogger CreateLogger(string categoryName)
    {
        return null;
    }

    public void Dispose()
    {
    }
}

Not exactly the best implementation of a provider, but I just want to set a breakpoint in the CreateLogger method to prove my point.

Inside the ConfigureServices method, I add a scoped service that I know will cause a startup error:

services.AddScoped<IMyInterface, IMyInterface>();

IMyInterface is just an empty interface.

On startup, the website throws the following error:

Cannot instantiate implementation type 'WebApplication1.IMyInterface' for service type 'WebApplication1.IMyInterface'.

The challenge here is that my log provider is never invoked. Shouldn't this be logged?

PS: I already tried setting this without effect:

webBuilder.CaptureStartupErrors(true);
analogrelay commented 4 years ago

The challenge here is that my log provider is never invoked. Shouldn't this be logged?

The problem is that logging is configured in DI, so if the DI container fails to build, there's no logger to log with. This used to work a little better in 2.x but it was because we had two parallel DI containers which caused a whole bunch of (worse) problems.

analogrelay commented 4 years ago

After some exploration, this isn't going to be feasible because of the construction order. Logging is build out of DI so we can't start logging until DI is ready and if ConfigureLogging and/or ConfigureServices (both of which run before DI is ready, in order to register the loggers in DI) fail there's no logger. We crash to the console, which also reports the issue to the Windows Event Log (on Windows).