Skip to content

A source generator that automatically migrates your logging calls to the LoggerMessage version

License

Notifications You must be signed in to change notification settings

stbychkov/AutoLoggerMessage

Repository files navigation

AutoLoggerMessage

NuGet License GitHub Build

Welcome to AutoLoggerMessage, a source generator that automatically creates LoggerMessage methods, enabling high-performance logging.

Demo

Demo

Getting started

Just follow these two simple steps:

1. Install the Package from NuGet

dotnet add package stbychkov.AutoLoggerMessage

2. Enable interceptors

Interceptors can be enabled either for a specific project or globally by defining them in the Directory.Build.props file

<PropertyGroup>
    <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.Extensions.Logging.AutoLoggerMessage</InterceptorsPreviewNamespaces>
</PropertyGroup>

Check this page for configuration options that can tweak the source generation process.

Benchmarks

You can achieve performance boosts of up to 90% according to my benchmarks just by including this source generator in your project.

Configuration Mean Ratio Allocated
Default implementation 38.149 ns 1.00 216 B
Default + AutoLogger 3.734 ns 0.10 -
AutoLoggerMessage 3.747 ns 0.10 -

Take a look at benchmark page for more details.

Known Limitations

  • It supports only static EventId parameter. If you pass the explicit EventId parameter, which basically no one does as far as I can tell, it generates a new EventId and the existing one will be passed to the formatter state, but it won't be logged. This limitation comes from the original LoggerMessage generator as they don't support the explicit parameter ~~ yet~~.
  • Log.Define supports only 6 message parameters (src) so if you pass more than that, the default Logger.Log(*, params object[] args) will be executed.
  • As this solution is based on interceptors, only .NET 8+ is supported

Is something wrong?

If something is not working as expected, you can fall back on the default implementation of ILogger extensions. To do this, call the extensions directly, for example:

logger.LogInformation("Some message"); // instead of this
LoggerExtensions.LogInformation(logger, "Some message"); // use this

In such case, the source generator will bypass the log call, ensuring you get the expected behavior.

If you require functionality from the LoggerMessage source generator that is not supported by this library, you can manually create your own source-generated version. Simply define your own partial class and partial method, annotated with the [LoggerMessage] attribute.

logger.LogInformation("Some message"); // instead of this

[LoggerMessage(LogLevel = LogLevel.Information, Message = "Some message")]
public partial void LogSomeMessage(); // use this

But for both scenarios, it’s recommended to report the issue, as it shouldn't happen under normal circumstances. Your feedback can help improve the library and address potential shortcomings. Thank you!

Motivation

Source-generated logging is increasingly recognized as a modern and efficient approach. Check this page to see why.

But let’s be real, when you’ve got a mid-sized project, migrating to the new logging approach is not exactly a simple task. And even when starting a new project, marking every class as partial or depending on an external partial class for logging messages can feel disconnected from the code where they are actually used.

This library handles most of the heavy lifting for you, so you can spend your time doing more important things!

But I hope this is a temporary solution — maybe one day, something similar will be added to the core library. Check this discussion for updates.

How It Works

This source generator searches for all logger.Log* methods in your code and, based on their parameters, automatically creates partial methods for LoggerMessage. It also generates a set of interceptors to forward the logging calls to the newly generated LoggerMessage methods.

For more details, see the How It Works documentation

Questions?

I bet you have some questions about why things are set up the way they are. Refer to the ADR files for detailed explanations of the design decisions behind this package.

About

A source generator that automatically migrates your logging calls to the LoggerMessage version

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages