CoreDesign.Logging
1.0.4
dotnet add package CoreDesign.Logging --version 1.0.4
NuGet\Install-Package CoreDesign.Logging -Version 1.0.4
<PackageReference Include="CoreDesign.Logging" Version="1.0.4" />
<PackageVersion Include="CoreDesign.Logging" Version="1.0.4" />
<PackageReference Include="CoreDesign.Logging" />
paket add CoreDesign.Logging --version 1.0.4
#r "nuget: CoreDesign.Logging, 1.0.4"
#:package CoreDesign.Logging@1.0.4
#addin nuget:?package=CoreDesign.Logging&version=1.0.4
#tool nuget:?package=CoreDesign.Logging&version=1.0.4
CoreDesign.Logging
CoreDesign.Logging provides a DispatchProxy-based logging middleware that wraps any class behind an interface and automatically logs every method invocation, return value, and exception. Classes stay free of log statements while still producing structured, consistent log output for every operation.
Installation
dotnet add package CoreDesign.Logging
Usage
Register a single class with the logging proxy
Replace the standard AddTransient (or AddScoped) call with AddWithLogging:
services.AddWithLogging<IWeatherForecastService, WeatherForecastService>();
The DI container will resolve IWeatherForecastService as a proxy-wrapped instance. The concrete class needs no changes.
Automatic registration with ILoggable
For larger applications, implement the ILoggable marker interface on any class to opt it into automatic logging registration. ILoggable can be applied to services, handlers, or any other class in your application regardless of naming convention.
public class CreateForecastHandler(...) : ICreateForecastHandler, ILoggable { ... }
public class GetForecastHandler(...) : IGetForecastHandler, ILoggable { ... }
public class OrderProcessingService(...) : IOrderProcessingService, ILoggable { ... }
Then register all marked classes in a single call:
services.AddWithLogging(typeof(Program).Assembly);
The overload scans the assembly for every non-abstract class implementing ILoggable, pairs it with each of its non-marker interfaces, and registers a logging proxy for each one. Renaming a class has no effect on whether it gets logging — only the presence of ILoggable matters.
Choosing between the two approaches
| Approach | When to use |
|---|---|
AddWithLogging<TInterface, TImplementation>() |
Explicit, per-class control. Useful when only a small number of classes need logging, or when you want each registration to be visible at the call site. |
AddWithLogging(assembly) |
Opt-in at the class level via ILoggable. Useful when many classes across an assembly should be logged and you want a single registration call. |
What gets logged
| Situation | Level |
|---|---|
| Method called | Information (method name and serialized parameters) |
| Method returned a success result | Information (method name and serialized return value, truncated to 500 chars by default) |
Method returned a NotFoundMessage or BadRequestMessage |
Warning (same truncation applies) |
| Method threw an exception | Error (exception and method name) |
Both synchronous and Task/Task<T> methods are fully supported.
Lifetime
Both overloads default to Transient. Pass a different lifetime when needed:
services.AddWithLogging<IMyService, MyService>(ServiceLifetime.Scoped);
services.AddWithLogging(typeof(Program).Assembly, ServiceLifetime.Scoped);
Sensitive Data
By default, LoggingMiddleware serializes all method parameters and return values into the log output. Two attributes give you control over methods that handle passwords, tokens, or other sensitive information.
[Redact]
Apply [Redact] to any parameter on the interface method that should not appear in logs. The middleware replaces that argument with "[REDACTED]" while still logging all other parameters normally.
public interface IAuthService
{
Task<LoginResult> LoginAsync(string username, [Redact] string password);
}
The log entry for the example above will include the username value and show "[REDACTED]" in place of password. The actual value is passed to the implementation unchanged.
[Suppress]
Apply [Suppress] to a method on the interface to skip all logging for that method. No invocation, result, or exception entries are written.
public interface ITokenService
{
[Suppress]
Task<string> IssueTokenAsync(string userId);
}
Use [Suppress] when the method name or parameter shape itself would be too revealing, or when call volume is high enough that logging every invocation creates more noise than value.
[TruncateLog]
Return values are serialized to JSON and truncated at 500 characters by default. Any result longer than this limit is cut and a note is appended showing the total length:
WeatherForecastService.GetAllAsync returned [{"id":"..."}... [truncated, total 3842 chars]
Apply [TruncateLog] to a method on the interface to override the limit for that method:
public interface IWeatherForecastService
{
// Raise the limit for a method expected to return larger payloads.
[TruncateLog(2000)]
Task<IReadOnlyList<WeatherForecast>> GetAllAsync(CancellationToken ct);
// Disable truncation entirely for a method that returns a small, critical diagnostic object.
[TruncateLog(0)]
Task<ServiceStatus> GetStatusAsync();
}
The default limit of 500 characters is defined by LoggingMiddleware.DefaultMaxResultLength. Parameters are not truncated; use [Redact] to suppress a sensitive parameter entirely.
Further Reading
Design rationale and comparison with Serilog and Serilog.Enrichers.Sensitive: SerilogVsMiddleware.md
Dependencies
CoreDesign.SharedforNotFoundMessageandBadRequestMessageresult typesOneOffor discriminated-union result inspectionMicrosoft.Extensions.Logging.AbstractionsMicrosoft.Extensions.DependencyInjection.Abstractions
Feedback
Feedback on this package is welcome. If you run into a missing feature, an unexpected behavior, or something that required more effort than it should have, open an issue at github.com/codyskidmore/CoreDesign/issues or tag @codyskidmore. Suggestions about missing features and priority input are especially appreciated.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CoreDesign.Shared (>= 1.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- OneOf (>= 3.0.271)
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.4 | 54 | 5/17/2026 |
1.0.4
- Added ILoggable marker interface. Classes implementing ILoggable are discovered by the new assembly-scanning overload of AddWithLogging.
- Added AddWithLogging(IServiceCollection, Assembly, ServiceLifetime) overload that registers all ILoggable classes in the assembly paired with their interfaces.
1.0.2
- Renamed [SensitiveParameter] attribute to [Redact] and renamed [NoLog] to [Suppress] for clarity and consistency with other CoreDesign libraries.
1.0.1
- Initial release