Speed Up Logging In .NET

The team at Microsoft has added another way to do logging that touts that it’s faster than using the old new way (ILogger). In this article, I will discuss the old way of logging and introduce the new LoggerMessage class.

The Old New Way of Logging

Ever since ILogger was introduced in .NET, this is how we have been logging,

private readonly ILogger _logger = new LoggerFactory().CreateLogger<PersonCollection>();
// In a method
this._logger.LogError(ex, "Person cannot be null.");

For the different types of log levels, you would choose one of these methods when logging:

  • LogCritical
  • LogDebug
  • LogError
  • LogInformation
  • LogTrace
  • LogWarning

Next, let’s look at the new LoggerMessage in .NET which you can find in the Microsoft.Extensions.Logging.Abstractions NuGet package.

The New LoggerMessage

The new way of logging is to use LoggerMessage. LoggerMessage creates a delegate that should be cached to log messages faster. There are two steps to log a message with LoggerMessage.

Step 1: Create the Delegate

To create a simple error log, the delegate is created by using the Define() method.

private static Action <ILogger, string, Exception> _loggerMessage = 
    LoggerMessage.Define<string>(LogLevel.Error, eventId: 
    new EventId(id: 0, name: "ERROR"), formatString: "{Message}");

There are a few things to note here. When using Define<T>, you can add as many value types such as string, DateTime, and more which makes LoggerMessage very flexible. Those values will be inserted in formatString. In this case, I only want to log a message, so I just defined a string. The placeholders must start with uppercase (not sure why).

Secondly, you must store these delegates in a field so that they will be cached. If you don’t, it will slow down logging about 4 times over using Logger.LogError().

Step 2: Invoke Delegate

To log the actual message, this is how you do it:

_loggerMessage(this._logger, "Person cannot be null.",  ex);

Now you see that this way of logging takes more code since the LoggerMessage must be defined first and then invoked. Next, I will show you how to log when using LoggerMessage as easy as using one of the methods in ILogger.

Making LoggerMessage Easier to Use with Spargine

As you can see from above, logging a message using LoggerMessage takes a bit more code to implement. I wished that the team at Microsoft made this as easy as calling Logger.LogDebug(). So as usual, I came up with a method and an extension method to make this as easy as before. This code can be found in my Spargine open-source project. Most of the time when we log, we just need to log text and the exception (if there is one).

LoggingHelper.FastLogger

In the dotNetTips.Spargine.Core assembly you will find the LoggingHelper class that contains the method FastLogger(). Here is an example of how to use it:

LoggingHelper.FastLogger(_logger, LogLevel.Error, "Person cannot be null.", ex);

FastLogger Extension Method

In the dotNetTips.Spargine.Extensions assembly I have added an extension method for ILogger called FastLogger(). Here is how to use it:

_logger.FastLogger(LogLevel.Error, "Person cannot be null.", ex);

Performance

Is using LoggerMessage faster? Let’s look at the results below from my benchmark tests.

Speed Up Logging in .NET

As you can see, using LoggerMessage is almost 2X faster than using ILogger! To make it easy to switch to this new way of coding I hope you will use one of the methods I have provided in Spargine. I’m not sure why LoggerMessage is less performant in .NET 6. Let’s hope the team works on that!

Summary

We all need to speed up our code, especially in the cloud, and using LoggerMessage will help with that. I wished this did not take more coding since I feel that most teams will just continue to use what they have. My feeling is that the more it takes to implement something, the fewer developers will embrace it. That’s why I made it easier on you in Spargine. Make sure you log as much and as often as you can. This is the best way to track down issues in your code!

Spargine is also available as NuGet packages. To learn more, please go here: https://dotnettips.wordpress.com/spargine/. Do you have any questions or comments? Please make them below.


McCarter Consulting
Software architecture, code & app performance, code quality, Microsoft .NET & mentoring. Available!