Categories
Uncategorized

ASP.NET Core 3.0 – Logging in the Startup Class (with NLog)

With ASP.NET Core 3.0, the ability to inject an ILogger or ILoggerFactory into the Startup class has been removed, so we can no longer do this:

public class Startup
{
public Startup(IConfiguration configuration, ILoggerFactory logFactory)
{
Logger = logFactory.CreateLogger<Startup>();
}
private ILogger Logger { get; }
public void ConfigureServices(IServiceCollection services)
{
Logger.LogInformation("Registering Services");
// And the rest
}
}
view raw Startup.cs hosted with ❤ by GitHub

I understand why this has been done, because creating a temporary DI container just for the startup process adds a lot of complexity and potential for errors.

However, my ConfigureServices method (and the new ConfigureContainer method added in 3.0) does quite a bit of work, including loading extension assemblies; I want to be able to log during that time.

I also want to make sure I only pass around the ILogger from the Microsoft.Extensions.Logging namespace to other objects used at startup.

The Workaround

I use NLog for my logging (https://nlog-project.org/). In my Program’s Main method I configure it like so:

public static void Main(string[] args)
{
// NLog: setup the nlog config first; this will configure all subsequent nlog factories
// with our nlog config.
NLogBuilder.ConfigureNLog("nlog.config");
var host = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
// Use NLog to provide ILogger instances.
.UseNLog()
.Build();
host.Run();
}
view raw Program.cs hosted with ❤ by GitHub

You can grab details on how to create an nlog.config file from the NLog docs, I won’t go into it here.

Then, in my Startup class, I can create the NLogLoggerProvider class (this is sort of a factory for creating the Microsoft ILogger instances), and from that I can get my logger instance:

public class Startup
{
public Startup(IConfiguration configuration)
{
// Get the factory for ILogger instances.
var nlogLoggerProvider = new NLogLoggerProvider();
// Create an ILogger.
Logger = nlogLoggerProvider.CreateLogger(typeof(Startup).FullName);
}
public void ConfigureServices(IServiceCollection services)
{
Logger.LogInformation("Registering Services");
// And the rest
}
}
view raw Startup.cs hosted with ❤ by GitHub

Hey presto, logging in the Startup class. Note that we are obviously outside the entire DI system for this logging (which is sort of the point).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s