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:
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:
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 less1 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.
1 "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.