---
title: "A more flexible and enhanced way of logging in .NET 8"
description: "The latest version of the .NET (version 8) has introduced a \"better\" way of logging. This new way of logging is more flexible and enhanced than the previous versions. It is about the `LoggerMessageAttribute`."
updated: 2023-11-15
tags: ["C#", ".NET", "Logging"]
canonical: "https://steven-giesel.com/blogPost/1add3827-4233-4e31-9ce9-bcc34d64e76f/a-more-flexible-and-enhanced-way-of-logging-in-net-8"
---

# A more flexible and enhanced way of logging in .NET 8

The latest version of the .NET (version 8) has introduced a "better" way of logging. This new way of logging is more flexible and enhanced than the previous versions. It is about the `LoggerMessageAttribute`.

In the old way, you would write code like this:

```csharp
public sealed class Repository<TEntity> : IRepository<TEntity>
    where TEntity : Entity
{
    public async ValueTask DeleteBulkAsync(IEnumerable<string> ids)
    {
        ...
        for (var batch = 0; batch < totalBatches; batch++)
        {
            logger.LogDebug("Deleted Batch {BatchNumber}. In total {TotalDeleted} elements deleted", batch + 1, (batch + 1) * batchSize);
        }
    }
}
```

With .NET 8, the `LoggerMessageAttribute` got some extensions, that halp you to define exactly that with source generators:
```csharp
public sealed partial class Repository<TEntity> : IRepository<TEntity>
    where TEntity : Entity
{
    public async ValueTask DeleteBulkAsync(IEnumerable<string> ids)
    {
        ...
        for (var batch = 0; batch < totalBatches; batch++)
        {
            LogDeleteBatch(batch + 1, (batch + 1) * batchSize);
        }
    }

    [LoggerMessage(LogLevel.Debug, "Deleted Batch {BatchNumber}. In total {TotalDeleted} elements deleted")]
    private partial void LogDeleteBatch(int batchNumber, int totalDeleted);
}
```

To make source generators work, we have to define the class as a `partial` class. The source generator will then generate the missing part of the class. 
Personally, it is nicer to read with less<sup>1</sup> code. You can also save some precious allocations and a bit of performance, even though in 99% of cases, that shouldn't matter. But it is nice if it comes "free" with it.

<sup>1</sup> "Less" in the sense of less complexity and mental capacity needed to process. `LogDeleteBatch(batch + 1, (batch + 1) * batchSize);` is way easier to process than `logger.LogDebug("Deleted Batch {BatchNumber}. In total {TotalDeleted} elements deleted", batch + 1, (batch + 1) * batchSize);
        }`. It isn't necessary less code.

## Resources
If you want to know more about the `LoggerMessageAttribute`, you can the "update" on the [official announcement of .NET 8 Preview 6](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-6/#expanding-loggermessageattribute-constructor-overloads-for-enhanced-functionality).