Fundamentals of Logging in .NET Core
.NET Core SDK is a light weight SDK which includes a bare minimum set of features required to build an application. We can install NuGet packages for other features we require for our application. For this, Microsoft provides .NET APIs as .NET Extensions.
.NET Extensions is an open-source, cross-platform set of APIs for commonly used programming patterns and utilities, such as dependency injection, logging, and app configuration. Most APIs in this project are meant to work on many .NET platforms, such as .NET Core, .NET Framework, Xamarin, and other. While commonly used in ASP.NET Core applications, these APIs are not coupled to the ASP.NET Core application model. They can be used in console apps, WinForms and WPF, etc. You can find the documentation and the source code of extensions at https://github.com/aspnet/Extensions.
All the extensions are included under the Microsoft.Extensions
namespace. You can find all built-in and third party extensions at nuget.org/packages.
The Logging API is included in the Microsoft.Extensions.Logging
package. The Logging API does not work as standalone. It works with one or more logging providers that store or display logs to a particular medium such as Console, Debug, TraceListeners etc.
So, there are two important building blocks for implementing logging in a .NET Core based application:
- Logging API
- Logging Providers
The following figure illustrates logging in .NET Core:
As you can see in the above figure, the logging API in Microsoft.Extensions.Logging
works on the .NET Core based applications whether it is ASP.NET Core or EF Core. You just need to use the logging API with one or more logging providers to implement logging in any .NET Core based application.
Logging API
As mentioned before, Microsoft provides logging API as an extension in the wrapper Microsoft.Extensions.Logging which comes as a NuGet package.
Microsoft.Extensions.Logging
includes the necessary classes and interfaces for logging. The most important are the ILogger, ILoggerFactory, ILoggerProvider interfaces and the LoggerFactory class.
The following figure shows the relationship between logging classes.
Let's have an overview of each of the above class.
ILoggerFactory
The ILoggerFactory
is the factory interface for creating an appropriate ILogger
type instance and also for adding the ILoggerProvider
instance.
public interface ILoggerFactory : IDisposable
{
ILogger CreateLogger(string categoryName);
void AddProvider(ILoggerProvider provider);
}
The Logging API includes the built-in LoggerFactory
class that implements the ILoggerFactory
interface. We can use it to add an instance of type ILoggerProvider
and to retrieve the ILogger
instance for the specified category.
Visit ILoggerFactory and LoggerFactory for more information.
ILoggerProvider
The ILoggerProvider
manages and creates an appropriate logger, specified by the logging category.
public interface ILoggerProvider : IDisposable
{
ILogger CreateLogger(string categoryName);
}
We can create our own logging provider by implementing the ILoggerProvider
interface.
Visit ILoggerProvider for more information.
ILogger
The ILogger
interface includes methods for logging to the underlying storage. There are many extension methods which make logging easy.
Visit ILogger for more information.
public interface ILogger
{
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
bool IsEnabled(LogLevel logLevel);
IDisposable BeginScope<TState>(TState state);
}
Logging Providers
A logging provider displays or stores logs to a particular medium such as a console, a debugging event, an event log, a trace listener, and others. Microsoft provides various logging providers as NuGet packages.
The following table lists important logging providers.
Logging Provider's NuGet Package | Output Target |
---|---|
Microsoft.Extensions.Logging.Console | Console |
Microsoft.Extensions.Logging.AzureAppServices | Azure App Services 'Diagnostics logs' and 'Log stream' features |
Microsoft.Extensions.Logging.Debug | Debugger Monitor |
Microsoft.Extensions.Logging.EventLog | Windows Event Log |
Microsoft.Extensions.Logging.EventSource | EventSource/EventListener |
Microsoft.Extensions.Logging.TraceSource | Trace Listener |
Microsoft has also collaborated with various logging framework teams (including third parties like NLog, Serilog, Loggr, Log4Net, and others) to extend the list of providers compatible with Microsoft.Extensions.Logging
.
The following are some thrid-party logging providers:
Logging Provider | Description |
---|---|
elmah.io | Provider for the Elmah.Io service |
Loggr | Provider for the Logger service |
NLog | Provider for the NLog library |
Serilog | Provider for the Serilog library |
Let's take an example using the Microsoft.Extensions.Logging.Console
package which displays logs on the Console.
Console Logging Provider
Let's see how to display logs on the console using the NuGet package for a console provider.
The Microsoft.Extensions.Logging.Console
package includes logging classes which send log output to the console.
The following figure illustrates how the logging API works with the console logging provider.
As you can see in the above figure, the ConsoleLogger
implements ILogger
, while the ConsoleLoggingProvider
implements ILoggingProvider
. The ConsoleLoggerExtensions
class includes extension method AddConsole()
, which adds a console logger to the LoggerFactory
.
Now, let's see how to display logs on the Console in the .NET Core console application.
First of all, create a new console application using the Console App (.NET Core) template in Visual Studio 2017 (or later).
Now, you need to install a NuGet package of Microsoft.Extensions.Logging
. You can install it either using the NuGet Package Manager or executing the following command in the Package Manager Console.
Now, you need to install a logging provider of your choice. Here, we will send logs on the Console, so, install the Microsoft.Extensions.Logging.Console
package either using NPM or execute the following command in the Package Manager Console in Visual Studio.
After successfully installing the above two packages, you can now implement logging in your .NET Core console application, as shown below.
namespace DotnetCoreConsoleApp
{
class Program
{
static void Main(string[] args)
{
ILoggerFactory loggerFactory = new LoggerFactory(
new[] { new ConsoleLoggerProvider((_, __) => true, true) }
);
//or
//ILoggerFactory loggerFactory = new LoggerFactory().AddConsole();
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("This is log message.");
}
}
}
This is log message.
In the above example, we created an object of the LoggerFactory
class and assigned it to the ILoggerFactory
type variable, as shown below.
ILoggerFactory loggerFactory = new LoggerFactory( new[] { new ConsoleLoggerProvider ((_, __) => true, true) } );
The LoggerFactory
can contain one or more logging providers, which can be used to log to multiple mediums concurrently.
The constructor of the LoggerFactory
accepts an array of different logger provider objects as new[] { }
.
We want to display logs on the console, so we need to create an object of the console logger provider ConsoleLoggerProvider
.
There are four constructors of the ConsoleLoggerProvider
. Use the one that allows lambda expression (Func<>) for log filtration and includeScope Boolean.
Here, we don't want to filter any information so the lambda expression would always return true (_, __) => true
, as shown below.
new ConsoleLoggerProvider((_, __) => true, true)
Then, we can use this object of the LoggerFactory
to create a logger using which we can actually log information, errors, warnings, traces, debugs etc. loggerFactory.CreateLogger<Program>()
creates a logger specific to the Program
class so that the logger will display a message with context info, e.g. DotnetCoreConsoleApp.Program[0].
Most logging providers include an extension method of ILoggerFactory
, which is a shortcut to add a provider to the logger factory.
For example, to add a console logger provider to the LoggerFactory
, just call the LoggerFactory.AddConsole()
extension method with the same parameters as ConsoleLoggerProvider
, as shown below.
public ILoggerFactory loggerFactory = new LoggerFactory().AddConsole();
This is more readable and maintainable than creating a logger provider manually. The above logger factory will display the same output as above.
Log Levels
Log levels indicate the importance or severity of log messages. Built-in log providers include extension methods to indicate log levels.
The following table lists log levels in .NET Core.
Log Level | Severity | Extension Method | Description |
---|---|---|---|
Trace | 0 | LogTrace() | Logs messages only for tracing purposes for the developers. |
Debug | 1 | LogDebug() | Logs messages for short-term debugging purposes. |
Information | 2 | LogInformation() | Logs messages for the flow of the application. |
Warning | 3 | LogWarning() | Logs messages for abnormal or unexpected events in the application flow. |
Error | 4 | LogError() | Logs error messages. |
Critical | 5 | LogCritical() | Logs failures messages that require immediate attention. |
We can use extension methods to indicate the level of the log messages as shown below.
namespace DotnetCoreConsoleApp
{
class Program
{
static void Main(string[] args)
{
ILoggerFactory loggerFactory = new LoggerFactory().AddConsole((_, __) => true);
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Logging information.");
logger.LogCritical("Logging critical information.");
logger.LogDebug("Logging debug information.");
logger.LogError("Logging error information.");
logger.LogTrace("Logging trace");
logger.LogWarning("Logging warning.");
}
}
}
The above example will display the following output:
Visit Logging in .NET Core for more detailed information.