Logging in .NET Core using ILogger

Logging in .NET Core using ILogger

Logging is an important part of software development. It helps us know that tasks have been completed, monitor applications and provides a trail to follow when things don’t work.

Microsoft has included a logging framework in .NET Core and ASP.NET Core to allow developers to easily implement logging and choose their own logging provider (this is the part which decides how to store your log messages).

A good logging solution can be invaluable when an application stops working as expected. I’ve also made some suggestions on making sure log messages are useful.

What is ILogger?

Microsoft introduced ILogger and ILoggerFactory in .NET Core to create a layer of abstraction developers can use to add logging to their applications.

The application can select from a variety of logging providers to record messages from the logging abstraction. These can record the log messages to different file formats, automatically add extra information (such as the machine name) or send the messages to a log server to be stored.

How to use ILogger

Making use of ILogger is pretty simple. You inject an instance of the logger into the constructor of your class and store it in a private variable. The example below relies on the dependency injection container built in to ASP.NET Core.

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }
}

This allows you to make use of the logger as needed throughout the rest of your class. There are some helpful guidelines which are good to follow when making use of ILogger.

Use the ILogger extension methods

The best way to use ILogger is to use the built in extension methods, such as LogWarning and LogInformation.

_logger.LogInformation("This is my log message");

Using these methods ensures that your log statements have their log level set appropriately and keeps your intention clear to other developers.

Use parameters and not string interpolation

When you are using the logging statements it is easy to use string interpolation for your messages.

var userId = Guid.NewGuid();

_logger.LogInformatiown($"The user ID is {UserId}.");

This approach records the message as a single string which works well for simple logging providers. Another approach is to use parameterisation to add information from variables to your log messages.

var userId = Guid.NewGuid();

_logger.LogInformation("This user ID is {UserID}.", userId);

Parameterisation will allow logging providers which support it to filter and search on those parameters. This can be extremely useful when attempting to diagnose specific errors which are reported.

Pass exceptions as the first parameter

Passing exceptions as the first parameter in the method ensures that they are recorded. If they are entered as a message parameter they may not be fully recorded or omitted entirely if there is no placeholder in the message.

_logger.LogError(exception, "This is my error log message with an exception.");

This approach also allows log providers to adjust how they record the exception along with the log message. Typically this is by appending the exception information to the log message when it is recorded.

Use logging scopes to add additional information to log entries

Log scopes can be used to build up and add additional information to log messages. You can use the BeginScope method to start your scope. When you are done the scope will be ended at the end of a using block or by calling the Dispose method.

using (_logger.BeginScope("This will be included with every log message."))
{
    _logger.LogInformation("Log message");
}

The use of log scopes allows you to automatically attach a scoped message to all log messages recorded within the scope. This could be information such as request or transaction IDs. The use of log scopes does rely upon your chosen log provider supporting the functionality.

Conclusion

The logging abstraction included in .NET Core makes it easy to include logging in your application. The ILogger interface and accompanying extension methods let you record log messages effectively. While also making it easy to use a variety of log providers.