AOP.Logging.SourceGenerator
1.2.2
See the version list below for details.
dotnet add package AOP.Logging.SourceGenerator --version 1.2.2
NuGet\Install-Package AOP.Logging.SourceGenerator -Version 1.2.2
<PackageReference Include="AOP.Logging.SourceGenerator" Version="1.2.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="AOP.Logging.SourceGenerator" Version="1.2.2" />
<PackageReference Include="AOP.Logging.SourceGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add AOP.Logging.SourceGenerator --version 1.2.2
#r "nuget: AOP.Logging.SourceGenerator, 1.2.2"
#:package AOP.Logging.SourceGenerator@1.2.2
#addin nuget:?package=AOP.Logging.SourceGenerator&version=1.2.2
#tool nuget:?package=AOP.Logging.SourceGenerator&version=1.2.2
AOP.Logging.NET
A powerful, attribute-based Aspect-Oriented Programming (AOP) logging framework for C# that provides seamless method interception and automatic logging using Source Generators.
Features
- Attribute-Based Logging: Simple, declarative logging with
[LogClass],[LogMethod], and related attributes - Compile-Time Source Generation: Zero runtime overhead with C# Source Generators
- Microsoft.Extensions.Logging Integration: Works with your existing logging infrastructure
- Async/Await Support: Full support for async methods and Task-based operations
- Sensitive Data Protection: Automatically mask sensitive data with
[SensitiveData]attribute - Structured Logging: Rich, contextual logging with proper parameter serialization
- Configurable: Fine-grained control over what gets logged and how
- Dependency Injection: First-class support for Microsoft.Extensions.DependencyInjection
- Performance Optimized: Minimal overhead with intelligent logging decisions
Installation
Install the NuGet packages:
# Core library with attributes
dotnet add package AOP.Logging.Core
# Source Generator (required for compile-time code generation)
dotnet add package AOP.Logging.SourceGenerator
# Dependency Injection extensions
dotnet add package AOP.Logging.DependencyInjection
Quick Start
1. Configure Services
using AOP.Logging.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// Add AOP logging
services.AddAopLogging(options =>
{
options.DefaultLogLevel = LogLevel.Information;
options.LogExecutionTime = true;
options.LogParameters = true;
options.LogReturnValues = true;
});
// Register your services with logging
services.AddTransientWithLogging<IMyService, MyService>();
})
.Build();
await host.RunAsync();
2. Add Logging to Your Classes
using AOP.Logging.Core.Attributes;
[LogClass]
public partial class MyService : IMyService
{
// Implement your business logic in private *Core methods
private int AddCore(int a, int b)
{
return a + b;
}
[LogMethod(LogLevel.Debug)]
private async Task<string> GetDataAsyncCore(int id)
{
await Task.Delay(100);
return $"Data for {id}";
}
// The Source Generator automatically creates public wrapper methods:
// - public int Add(int a, int b) - with automatic logging
// - public async Task<string> GetDataAsync(int id) - with automatic logging
}
Important:
- Classes using AOP logging must be declared as
partial. - Implement your business logic in
privatemethods ending withCoresuffix. - The Source Generator automatically creates public wrapper methods with logging.
3. Run and See the Logs
info: MyService[0]
Entering MyService.Add
info: MyService[0]
Exiting MyService.Add (took 0ms)
Usage Examples
Note: The examples below show the business logic implementation. In practice, you should implement your methods as
private *Coremethods (e.g.,AddCore,ProcessDataCore), and the Source Generator will automatically create the corresponding public wrapper methods with logging enabled.
Basic Method Logging
[LogClass]
public partial class CalculatorService
{
private int AddCore(int a, int b) => a + b;
private int MultiplyCore(int a, int b) => a * b;
// Source Generator creates: public int Add(int a, int b) and public int Multiply(int a, int b)
}
Custom Log Levels
[LogClass(LogLevel.Debug)]
public partial class DebugService
{
[LogMethod(LogLevel.Warning)]
public void PerformCriticalOperation()
{
// This method will log at Warning level
}
}
Sensitive Data Protection
[LogClass]
public partial class UserService
{
public async Task<User> CreateUserAsync(
string email,
[SensitiveData] string password)
{
// password will appear as "***SENSITIVE***" in logs
var user = new User { Email = email };
return user;
}
}
Exception Logging
[LogClass]
public partial class DataService
{
[LogException(LogLevel.Error)]
public void ProcessData(string data)
{
if (string.IsNullOrEmpty(data))
{
throw new ArgumentException("Data cannot be null");
}
// Exception will be automatically logged
}
}
Async Method Support
[LogClass]
public partial class ApiService
{
public async Task<ApiResponse> FetchDataAsync(string endpoint)
{
await Task.Delay(100);
return new ApiResponse { Data = "Success" };
}
public async Task<T> GetAsync<T>(string url)
{
// Generic async methods are fully supported
await Task.Delay(50);
return default(T)!;
}
}
Parameter Control
[LogClass]
public partial class ReportService
{
public Report Generate(
[LogParameter(Name = "ReportId")] int id,
[LogParameter(Skip = true)] string internalToken,
[LogParameter(MaxLength = 50)] string description)
{
// internalToken won't be logged
// description will be truncated to 50 characters
return new Report { Id = id };
}
}
Return Value Logging
[LogClass]
public partial class CalculationService
{
[LogResult(Name = "CalculationResult")]
public double Calculate(double x, double y)
{
return Math.Sqrt(x * x + y * y);
}
[LogResult(Skip = true)]
public byte[] GetBinaryData()
{
// Return value won't be logged (useful for large data)
return new byte[1024];
}
}
Selective Method Logging
[LogClass]
public partial class MixedService
{
public void LoggedMethod()
{
// This will be logged
}
[LogMethod(Skip = true)]
public void NotLoggedMethod()
{
// This will NOT be logged
}
}
Configuration
Global Options
services.AddAopLogging(options =>
{
// Default log level
options.DefaultLogLevel = LogLevel.Information;
// Execution time tracking
options.LogExecutionTime = true;
// Parameter and return value logging
options.LogParameters = true;
options.LogReturnValues = true;
// Exception logging
options.LogExceptions = true;
// String and collection limits
options.MaxStringLength = 1000;
options.MaxCollectionSize = 10;
// Structured logging
options.UseStructuredLogging = true;
// Namespace filtering
options.IncludedNamespaces.Add("MyApp.Services");
options.ExcludedNamespaces.Add("MyApp.Internal");
// Class filtering with wildcards
options.IncludedClasses.Add("*Service");
options.ExcludedClasses.Add("*Internal");
// Custom message formats
options.EntryMessageFormat = "→ {ClassName}.{MethodName}";
options.ExitMessageFormat = "← {ClassName}.{MethodName} ({ExecutionTime}ms)";
options.ExceptionMessageFormat = "✗ {ClassName}.{MethodName}: {ExceptionMessage}";
});
Message Format Placeholders
Entry Messages:
{ClassName}- The name of the class{MethodName}- The name of the method{Parameters}- Formatted parameter list
Exit Messages:
{ClassName}- The name of the class{MethodName}- The name of the method{ReturnValue}- The return value{ExecutionTime}- Execution time in milliseconds
Exception Messages:
{ClassName}- The name of the class{MethodName}- The name of the method{ExceptionType}- The exception type name{ExceptionMessage}- The exception message{ExecutionTime}- Execution time before exception
Attributes Reference
[LogClass]
Marks a class for automatic logging of all public methods.
[LogClass(LogLevel.Information)]
public partial class MyService { }
Properties:
LogLevel- Log level for all methods (default: Information)LogExecutionTime- Track execution time (default: true)LogParameters- Log method parameters (default: true)LogReturnValue- Log return values (default: true)LogExceptions- Log exceptions (default: true)
[LogMethod]
Controls logging for a specific method, overriding class-level settings.
[LogMethod(LogLevel.Debug)]
public void MyMethod() { }
Properties:
LogLevel- Log level for this methodLogExecutionTime- Track execution timeLogParameters- Log method parametersLogReturnValue- Log return valueLogExceptions- Log exceptionsSkip- Skip logging for this methodEntryMessage- Custom entry message templateExitMessage- Custom exit message template
[LogParameter]
Controls logging for a specific parameter.
public void MyMethod([LogParameter(Name = "UserId")] int id) { }
Properties:
Skip- Skip logging this parameterName- Custom name in logsMaxLength- Maximum length for string values
[LogResult]
Controls logging for method return values.
[LogResult(Name = "Result")]
public int Calculate() => 42;
Properties:
Skip- Skip logging the return valueName- Custom name in logsMaxLength- Maximum length for string values
[LogException]
Controls exception logging behavior.
[LogException(LogLevel.Error)]
public void RiskyOperation() { }
Properties:
LogLevel- Log level for exceptions (default: Error)IncludeDetails- Include stack trace and inner exceptions (default: true)Rethrow- Rethrow the exception after logging (default: true)Message- Custom exception message template
[SensitiveData]
Marks data as sensitive, preventing it from being logged.
public void Login([SensitiveData] string password) { }
Properties:
MaskValue- The mask to use (default: "SENSITIVE")ShowLength- Show the length of sensitive data (default: false)
Dependency Injection Extensions
Service Registration with Logging
// Transient
services.AddTransientWithLogging<IMyService, MyService>();
// Scoped
services.AddScopedWithLogging<IMyService, MyService>();
// Singleton
services.AddSingletonWithLogging<IMyService, MyService>();
These extension methods automatically inject the IMethodLogger into your services.
Best Practices
- Use
partialclasses: Classes with logging attributes must be declared aspartial - Protect sensitive data: Always use
[SensitiveData]for passwords, tokens, and PII - Choose appropriate log levels: Use Debug for verbose logging, Information for normal flow, Warning for unusual situations
- Limit collection sizes: Set
MaxCollectionSizeto prevent logging large collections - Skip unnecessary logging: Use
Skip = truefor methods that don't need logging - Use structured logging: Enable
UseStructuredLoggingfor better log analysis
Performance Considerations
- Compile-time generation: All logging code is generated at compile time, not runtime
- Zero reflection: No reflection is used during logging execution
- Conditional logging: Logs are only formatted when the log level is enabled
- Minimal allocations: Optimized for low memory allocation
- Async-friendly: Async methods are properly handled without blocking
Requirements
- .NET 8.0 or .NET 10.0
- C# 11.0 or higher
- Microsoft.Extensions.Logging 8.0+
Sample Project
Check out the sample project for complete working examples demonstrating all features.
To run the sample:
cd samples/AOP.Logging.Sample
dotnet run
Versioning
This project follows Semantic Versioning and uses Conventional Commits for automated version management.
Release Process
- Automatic Versioning: Versions are calculated automatically based on commit messages
- Conventional Commits: All commits must follow the conventional commits specification
- semantic-release: Automated version calculation and release management
See VERSIONING.md for detailed information about our versioning strategy.
Commit Message Format
# Features (bumps MINOR version)
feat: add custom interceptor support
# Bug fixes (bumps PATCH version)
fix: resolve null reference in logger
# Breaking changes (bumps MAJOR version)
breaking: redesign attribute API
Contributing
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
Important: All commits must follow Conventional Commits format for proper version management.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Roadmap
- Custom interceptor support
- Performance counters integration
- OpenTelemetry integration
- Configuration from appsettings.json
- Advanced filtering expressions
- Log correlation support
Made with ❤️ by the AOP.Logging community
Learn more about Target Frameworks and .NET Standard.
This package has 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.