ASP.NET Core Web API Logging from a Static Class

Solution is to have a static reference to the LoggerFactory in a utility static class initialized on startup:

/// <summary>
/// Shared logger
/// </summary>
internal static class ApplicationLogging
{
    internal static ILoggerFactory LoggerFactory { get; set; }// = new LoggerFactory();
    internal static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();        
    internal static ILogger CreateLogger(string categoryName) => LoggerFactory.CreateLogger(categoryName);
}

Which you initialize on Startup.cs:

public Startup(ILogger<Startup> logger, ILoggerFactory logFactory, IHostingEnvironment hostingEnvironment)
{
    _log = logger;
    _hostingEnvironment = hostingEnvironment;
    Util.ApplicationLogging.LoggerFactory = logFactory;//<===HERE
}

Then you can build a logger to use from your static class like so:

internal static class CoreJobSweeper
{
    private static ILogger log = Util.ApplicationLogging.CreateLogger("CoreJobSweeper");
}

You can use the static LoggerFactory instance with the following extension method which accepts a regular parameter of type Type, rather than a generic type parameter: CreateLogger(ILoggerFactory, Type)

i.e. loggerFactory.CreateLogger(typeof(T)) rather than loggerFactory.CreateLogger<T>()


I've added a static member of ILoggerFactory in Startup class so it can be used in other classes.

public class Startup
{
    internal static ILoggerFactory LogFactory { get; set; }
    …

    public void Configure(…, ILoggerFactory logFactory)
    {
        …
        LogFactory = logFactory;
    }
}

Then use it in the static class.

static class YourClass
{
    private static ILogger<YourClass> Logger = Startup.LogFactory.CreateLogger<YourClass>();
…

However, this code will result in a TypeInitializationException when the CreateLogger throws an exception, so you should try to do better. [1]


I found this question with answers useful, but I remembered I already have installed Serilog. Instead of implementing a custom static instance, I could use the default implementation from Serilog.

It comes with multiple nice logging features with multiple overloaded version.
Here are two examples:

using Serilog;
...
    Log.Error(myException, "my message");
    Log.Warning("My message", myValue);

Serilog.Log is a static instance that is ready when configured in Program.cs or Startup.cs.