Skip to content

NLog GetCurrentClassLogger and Microsoft ILogger

Rolf Kristensen edited this page Oct 3, 2021 · 29 revisions

Microsoft ILogger Injection

Where NLog recommends having logger as static class variable, then Microsoft ILogger should be injected as input-parameter for the class-constructor:

public class MyClass
{
     private readonly ILogger Logger;

     public MyClass(ILogger<MyClass> logger)
     {
         Logger = logger;
     }
}

This introduces some extra noise for all class contructors. But it also makes it possible to have multiple Host-applications within the same process. And also gives better isolation when running unit-tests in parallel.

NLog GetCurrentClassLogger finds its Logger-Name using reflection tricks, but the generic Microsoft ILogger<MyClass> extracts the Logger-Name from the generic-type. The Microsoft Dependency Injection has a small memory allocation overhead, as it will always allocate a new class-object for every ILogger<MyClass>-parameter.

How to get ILogger with dynamic Logger name ?

If the class wants to generate output to multiple logger-objects, then NLog provides LogManager.GetLogger("ExtraLog"). But for Microsoft ILogger then one must request ILoggerFactory as input:

public class MyClass
{
     private readonly ILogger Logger;
     private readonly ILogger ExtraLogger;

     public MyClass(ILogger<MyClass> logger, ILoggerFactory loggerFactory)
     {
         Logger = logger;
         ExtraLogger = loggerFactory.CreateLogger("ExtraLog");
     }
}

How to create class instance without ILogger ?

.NET Core 2 introduced NullLogger and NullLoggerFactory so one can do this:

public class MyClass
{
     private readonly ILogger Logger;

     public MyClass(ILogger<MyClass> logger = null)
     {
         Logger = logger ?? NullLogger.Instance;
     }
}

This can be useful in unit-testing scenarios, or for utility-classes where logging output is not always necessary.

How to create local ILogger without dependency injection ?

.NET Core 3 introduced LoggerFactory.Create that can be useful for application startup logging, before the dependency injection system is fully initialized

var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger("StartupLogger");
logger.LogInformation("Starting...");

This can also be used for unit-testing scenarios, as each test-scenario can have their own local LoggerFactory.