Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core Web API Logging from a Static Class

I'm logging just fine using dependency injection on my controllers, now I need to log something from a static class.

How can I log from a static class?

I can't use dependency injection because it's static and I can't just pass in an existing logger object to the static class because it would have the wrong name of class in the log file.

In other words how can I get a logger from the loggerfactory inside my static class?

I came across a similar question and they pointed to an article on a loggerfactory in a static class but that doesn't actually work as I can't get a new logger from it because it won't accept a static class as the parameter:

"Static types cannot be used as type arguments"

like image 538
JohnC Avatar asked Feb 08 '18 01:02

JohnC


People also ask

How do I log into NET Core API?

Set the environment key Logging:LogLevel:Microsoft to a value of Information on Windows. Test the settings when using an app created with the ASP.NET Core web application templates. The dotnet run command must be run in the project directory after using set .

Does dependency injection work with static classes?

You can use dependency injection in a static class using method or property injection. However, you cannot use constructor injection in a static class because the constructor of a static class cannot accept any parameters.

Which .NET function would you use to get a logger?

log4net is one of the most common external logging services available to . NET developers. The developers for log4net promise you can have logging integrated with your application within minutes, and it's true—setup is easy. log4net is available in NuGet, so it's just as easy to install as it is to code.

What is the use of ILogger in .NET Core?

The ILoggerFactory is the factory interface for creating an appropriate ILogger type instance and also for adding the ILoggerProvider instance. The Logging API includes the built-in LoggerFactory class that implements the ILoggerFactory interface.


3 Answers

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");
}
like image 79
JohnC Avatar answered Oct 18 '22 22:10

JohnC


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.

like image 40
pekaaw Avatar answered Oct 18 '22 20:10

pekaaw


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>()

like image 6
Adrian Avatar answered Oct 18 '22 21:10

Adrian