Speeding Up Logging In .NET 6

In a recent article, I wrote and demonstrated how to speed up logging using LoggerMessage in .NET. Not long after I wrote that article, I learned of an even faster way to log using .NET 6. This article will show you how you can use this new way of logging and show the results of benchmark tests.

The Standard Way of Logging

For years now, we have been using Microsoft.Extensions.Logging NuGet package to log errors etc. This package supports .NET 6, .NET Standard 2.0 and .NET Framework 4.62. Logging these messages is straightforward using ILogger.

this._logger.LogError(eventId: 100, exception: ex, message: "Something really bad happened!");

Let’s look at the performance of these calls.

Speeding Up Logging in dotNET

This is fast, but .NET 6 with a source generator can do better!

The New Way of Logging in .NET 6

The release of .NET 6 includes a new source generator that uses LoggerMessage that as you will see is even faster than the code shown above or using manually. I have added the ability to use this new source generator in Spargine as I will show below. It’s very simple.

I first created a partial class called EasyLogger. Using the LoggerMessageAttribute, I added methods for all of the available logging levels. They are, LogLevel.Critical, LogLevel.Debug, LogLevel.Error, LogLevel.Information, LogLevel.Trace and LogLevel.Warning. Here is an example:

[LoggerMessage(EventId = 100, Level = LogLevel.Critical, EventName = "CRITICAL", Message = "{message}")]
public static partial void LogCritical(ILogger logger, string message, Exception ex);

With this attribute, you can log the event id, logging level, event name, message, and of course the Exception (for Error and Critical). You can also log the type id and skip the IsEnabled check. Now you can log your messages using an ILogger object like this:

EasyLogger.LogCritical(logger: this._logger, message: "Something really, really bad happened!", ex: ex);

When the LoggerMessageAttribute is used, it generates a partial method behind the scenes that looks like this for LogCritical:

public static partial void LogCritical(global::Microsoft.Extensions.Logging.ILogger logger, global::System.String message, global::System.Exception ex) {
    if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Critical)) {
        __LogCriticalCallback(logger, message, ex);
    }
}

For each method, it also creates a private method, in this case, __LogCriticalCallback that does the actual logging using LoggerMessage.

Now, let us look at the performance using the LoggerMessageAttribute.

Speeding Up Logging in dotNET

Wow, as you can see, using the LoggerMessageAttribute improves the performance from 2 to 10 times! I do hope the team will work on the performance when logging Exceptions. This is another reason to move your projects to .NET 6, now!

Summary

We all need to speed up our code, especially in the cloud, and using the LoggerMessageAttribute in .NET 6 will help with that. Make sure you log as much and as often as you can. This is the best way to track down issues in your code! Also, don’t forget to log events.

Spargine is OSS and is available as NuGet packages. To learn more, please go here: https://dotnettips.wordpress.com/spargine/. Go here to view the EasyLogger class: dotNetTips.Spargine/EasyLogger.cs at main · RealDotNetDave/dotNetTips.Spargine (github.com).

Do you have any questions or comments? Please make them below.


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