# Dotnet Source Gen Logging

> Converts logging to use the LoggerMessage source generator for high-performance, AOT-compatible logging. Also use when the user mentions "LoggerMessage," "logging source generator," "high-performance logging," "optimize logging," "AOT logging," or "structured logging source gen." For full AOT analysis, see dotnet-aot-analysis.

- Skill: `im5tu-claude/dotnet-source-gen-logging` (Agent Skill)
- Install (CLI): `npx skillmds@latest add im5tu-claude/dotnet-source-gen-logging`
- Raw SKILL.md: https://api.skillmd.com/api/skills/im5tu-claude/dotnet-source-gen-logging/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: Im5tu (https://skillmd.com/u/im5tu-claude)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/im5tu-claude/dotnet-source-gen-logging

---


Convert existing logging calls to use the `LoggerMessage` source generator for 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**
   ```csharp
   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**
   ```bash
   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:
```csharp
_logger.LogInformation("User {UserId} logged in from {IpAddress}", userId, ip);
_logger.LogWarning("Failed login attempt for {Username}", username);
```

After:
```csharp
// 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);
```

