AutoLog.Generator 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package AutoLog.Generator --version 1.0.0
                    
NuGet\Install-Package AutoLog.Generator -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AutoLog.Generator" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AutoLog.Generator" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="AutoLog.Generator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AutoLog.Generator --version 1.0.0
                    
#r "nuget: AutoLog.Generator, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AutoLog.Generator@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AutoLog.Generator&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AutoLog.Generator&version=1.0.0
                    
Install as a Cake Tool

AutoLog.Generator

NuGet NuGet Downloads CI

AutoLog turns simple [Log]-annotated partial methods into high-performance LoggerMessage.Define logging at build time. You keep normal ILogger fields and readable structured log messages; the generator emits cached delegates, EventIds, and partial method bodies for you.

Why AutoLog?

Microsoft's built-in [LoggerMessage] pattern is fast, but it pushes a lot of ceremony into your code:

  • static partial methods
  • explicit logger parameters
  • manual event IDs
  • more boilerplate around every log statement

AutoLog keeps the performance benefits while simplifying the authoring model:

  • Just add [Log] to a partial void method
  • Use your existing ILogger field or property
  • Auto-detects ILogger / ILogger<T>
  • Auto-assigns EventIds per class
  • AOT-safe and zero-reflection

Installation

dotnet add package AutoLog.Generator

Then add a normal ILogger field or property to your partial class.

Quick start

using AutoLog;
using Microsoft.Extensions.Logging;

public partial class OrderService
{
    private readonly ILogger<OrderService> _logger;

    public OrderService(ILogger<OrderService> logger) => _logger = logger;

    [Log(LogLevel.Information, "Processing order {OrderId} for customer {CustomerId}")]
    partial void LogProcessingOrder(int orderId, string customerId);

    [Log(LogLevel.Warning, "Order {OrderId} not found")]
    partial void LogOrderNotFound(int orderId);

    [Log(LogLevel.Error, "Failed to process order {OrderId}")]
    partial void LogProcessingFailed(int orderId, Exception ex);
}

AutoLog generates code like:

// <auto-generated by AutoLog.Generator/>
#nullable enable

partial class OrderService
{
    private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, int, string, global::System.Exception?> _logProcessingOrderAction =
        global::Microsoft.Extensions.Logging.LoggerMessage.Define<int, string>(
            global::Microsoft.Extensions.Logging.LogLevel.Information,
            new global::Microsoft.Extensions.Logging.EventId(1, "LogProcessingOrder"),
            "Processing order {OrderId} for customer {CustomerId}");

    partial void LogProcessingOrder(int orderId, string customerId)
        => _logProcessingOrderAction(_logger, orderId, customerId, null);
}

Comparison with Microsoft's [LoggerMessage]

[LoggerMessage]

using Microsoft.Extensions.Logging;

public static partial class OrderLogs
{
    [LoggerMessage(
        EventId = 1001,
        Level = LogLevel.Information,
        Message = "Processing order {OrderId} for customer {CustomerId}")]
    public static partial void ProcessingOrder(
        ILogger logger,
        int orderId,
        string customerId);
}

AutoLog

using AutoLog;
using Microsoft.Extensions.Logging;

public partial class OrderService
{
    private readonly ILogger<OrderService> _logger;

    [Log(LogLevel.Information, "Processing order {OrderId} for customer {CustomerId}")]
    partial void LogProcessingOrder(int orderId, string customerId);
}

Why it feels simpler

Concern [LoggerMessage] AutoLog
Method shape static partial instance partial void
Logger parameter explicit in every method auto-detected from class
Event IDs manually managed sequential per class
Boilerplate medium low
Generated performance excellent excellent

Exception parameter handling

If the last parameter is Exception, AutoLog maps it to the exception slot of LoggerMessage.Define instead of treating it as a template parameter:

[Log(LogLevel.Error, "Failed to process order {OrderId}")]
partial void LogProcessingFailed(int orderId, Exception ex);

Generates:

private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, int, global::System.Exception?> _logProcessingFailedAction =
    global::Microsoft.Extensions.Logging.LoggerMessage.Define<int>(
        global::Microsoft.Extensions.Logging.LogLevel.Error,
        new global::Microsoft.Extensions.Logging.EventId(1, "LogProcessingFailed"),
        "Failed to process order {OrderId}");

partial void LogProcessingFailed(int orderId, Exception ex)
    => _logProcessingFailedAction(_logger, orderId, ex);

Rules

  • [Log] only works on partial void methods
  • The method must live on a partial class
  • The containing class must expose an instance ILogger or ILogger<T> field/property
  • AutoLog uses the first matching logger member it finds
  • LoggerMessage.Define<T1..T6> supports up to 6 non-exception parameters
  • If a log method exceeds 6 parameters, AutoLog emits AL003 and falls back to an object-array logging path

Diagnostics

Code Severity Message
AL001 Error [Log] on {Method} in {Class} — method must be partial void.
AL002 Error [Log] on {Method} — containing class {Class} has no ILogger or ILogger<T> field or property. Add one to enable log generation.
AL003 Warning [Log] on {Method} has {N} type parameters — LoggerMessage.Define supports a maximum of 6.

Migrating from [LoggerMessage]

Microsoft's source-generated [LoggerMessage] and AutoLog produce the same LoggerMessage.Define output. The difference is ergonomics.

Before ([LoggerMessage])

public static partial class OrderLogs
{
    [LoggerMessage(EventId = 1001, Level = LogLevel.Information,
        Message = "Processing order {OrderId} for customer {CustomerId}")]
    public static partial void ProcessingOrder(ILogger logger, int orderId, string customerId);

    [LoggerMessage(EventId = 1002, Level = LogLevel.Warning,
        Message = "Order {OrderId} not found")]
    public static partial void OrderNotFound(ILogger logger, int orderId);
}

// Call site — must pass logger explicitly every time:
OrderLogs.ProcessingOrder(_logger, order.Id, order.CustomerId);

After (AutoLog)

public partial class OrderService
{
    private readonly ILogger<OrderService> _logger;

    [Log(LogLevel.Information, "Processing order {OrderId} for customer {CustomerId}")]
    partial void LogProcessingOrder(int orderId, string customerId);

    [Log(LogLevel.Warning, "Order {OrderId} not found")]
    partial void LogOrderNotFound(int orderId);
}

// Call site — logger is implicit:
LogProcessingOrder(order.Id, order.CustomerId);

Migration steps

  1. Install AutoLog.Generatordotnet add package AutoLog.Generator
  2. Make your service class partial
  3. Replace static partial log methods with partial void instance methods and [Log]
  4. Remove the explicit ILogger parameter — AutoLog detects it from the field
  5. Remove manual EventIds — auto-assigned sequentially per class
  6. Update call sites — drop ClassName. prefix and the logger argument

Also by the same author

🌐 Full suite overview: swevo.github.io

Package Description
AutoHttpClient.Generator Compile-time typed HTTP client — [HttpClient] on an interface generates a strongly-typed client. AOT-safe Refit alternative.
AutoDispatch.Generator Compile-time CQRS dispatcher — [Handler] generates a strongly-typed IDispatcher. No MediatR, no reflection.
AutoWire Compile-time DI auto-registration — [Scoped]/[Singleton]/[Transient] generates IServiceCollection registration code.
AutoMap.Generator Compile-time object mapping with generated extension methods. AOT-safe AutoMapper alternative.
AutoValidate.Generator Compile-time FluentValidation wiring — discovers validators and generates AddValidators().
AutoResult.Generator Compile-time Result<T>[TryWrap] generates Try*() wrappers for every public method.
AutoQuery.Generator Compile-time LINQ query specs — [QuerySpec] generates a strongly-typed Apply(IQueryable<T>).

License

MIT

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 84 6/30/2026
1.0.0 82 6/30/2026

1.0.0: [Log(Level, Message)] on partial void methods; LoggerMessage.Define generation; ILogger field auto-detection; EventId auto-assignment; AL001/AL002/AL003 diagnostics.