skills/im5tu/dotnet-skills/dotnet-source-gen-logging

dotnet-source-gen-logging

SKILL.md

Convert existing logging calls to use the LoggerMessage source generator for high-performance, AOT-compatible logging with no boxing overhead and compile-time template parsing.

When to Use

  • Optimizing logging performance in hot paths
  • Preparing for Native AOT deployment
  • Organizing scattered log messages into logical groupings
  • Standardizing EventIds across the codebase

Steps

  1. Find ILogger usages and logging calls

    • Search for ILogger field/parameter declarations
    • Find all logging calls: LogInformation, LogWarning, LogError, LogDebug, LogTrace, LogCritical
    • Note the log message templates and parameters
  2. Organize into logical groupings by domain

    • Group related log messages by their functional area, eg:
      • LoggingValidationExtensions - validation-related logs
      • LoggingAuthenticationExtensions - auth-related logs
      • LoggingDatabaseExtensions - database-related logs
      • LoggingHttpExtensions - HTTP-related logs
      • LoggingCacheExtensions - caching-related logs
      • LoggingMessagingExtensions - messaging/queue-related logs
  3. Create partial static classes with extension methods

    public static partial class LoggingValidationExtensions
    {
        [LoggerMessage(
            EventId = 1001,
            Level = LogLevel.Warning,
            Message = "Validation failed for {EntityType}: {Errors}")]
        public static partial void ValidationFailed(
            this ILogger logger, string entityType, string errors);
    }
    
  4. Use EventId ranges per category

    • 1000-1999: Validation
    • 2000-2999: Authentication
    • 3000-3999: Database
    • 4000-4999: HTTP
    • 5000-5999: Cache
    • 6000-6999: Messaging
    • 7000-7999: General/Application
  5. Replace inline logging calls with extension method calls

    • Before: _logger.LogWarning("Validation failed for {entityType}: {errors}", type, errs)
    • After: _logger.ValidationFailed(type, errs)
  6. Verify with build

    dotnet build
    
  7. If build fails, review errors:

    • Missing using statements for the extension class namespace
    • Parameter type mismatches
    • Duplicate EventIds
  8. Report results:

    • List all created extension classes
    • Show count of converted log messages per category
    • Confirm build status

Key Notes

  • Requires .NET 6+ - the source generator is built into the SDK
  • Avoids boxing - value types are not boxed when passed to the generated methods
  • Template parsed once - message template is parsed at compile time, not runtime
  • Use PascalCase for placeholders - {EntityType} not {entityType} (matching is case-insensitive, but PascalCase is the recommended convention)
  • Extension methods - allows fluent logger.MethodName() syntax
  • Partial classes - required for source generator to emit the implementation

Example Conversion

Before:

_logger.LogInformation("User {UserId} logged in from {IpAddress}", userId, ip);
_logger.LogWarning("Failed login attempt for {Username}", username);

After:

// In LoggingAuthenticationExtensions.cs
public static partial class LoggingAuthenticationExtensions
{
    [LoggerMessage(
        EventId = 2001,
        Level = LogLevel.Information,
        Message = "User {UserId} logged in from {IpAddress}")]
    public static partial void UserLoggedIn(
        this ILogger logger, string userId, string ipAddress);

    [LoggerMessage(
        EventId = 2002,
        Level = LogLevel.Warning,
        Message = "Failed login attempt for {Username}")]
    public static partial void FailedLoginAttempt(
        this ILogger logger, string username);
}

// Usage
_logger.UserLoggedIn(userId, ip);
_logger.FailedLoginAttempt(username);
Weekly Installs
2
First Seen
Feb 4, 2026
Installed on
claude-code2
mcpjam1
kilo1
junie1
windsurf1
zencoder1