Mariodbx.AspectLogging
2.0.0
See the version list below for details.
dotnet add package Mariodbx.AspectLogging --version 2.0.0
NuGet\Install-Package Mariodbx.AspectLogging -Version 2.0.0
<PackageReference Include="Mariodbx.AspectLogging" Version="2.0.0" />
<PackageVersion Include="Mariodbx.AspectLogging" Version="2.0.0" />
<PackageReference Include="Mariodbx.AspectLogging" />
paket add Mariodbx.AspectLogging --version 2.0.0
#r "nuget: Mariodbx.AspectLogging, 2.0.0"
#:package Mariodbx.AspectLogging@2.0.0
#addin nuget:?package=Mariodbx.AspectLogging&version=2.0.0
#tool nuget:?package=Mariodbx.AspectLogging&version=2.0.0
AspectLogging
A powerful Aspect-Oriented Programming (AOP) library for .NET that provides transparent, non-invasive logging of method calls using dynamic proxies. AspectLogging enables comprehensive observability without modifying your business logic.
Table of Contents
- Overview
- Architecture
- Key Features
- Installation
- Quick Start
- Configuration
- Advanced Usage
- How It Works
- Performance Considerations
- API Reference
- Contributing
- License
Overview
AspectLogging implements Aspect-Oriented Programming principles to separate cross-cutting concerns (logging) from business logic. It uses .NET's DispatchProxy to create dynamic proxies that intercept method calls, providing comprehensive logging without requiring changes to your existing codebase.
Core Capabilities
- Transparent Interception: Automatically wraps service interfaces with logging behavior
- Async/Await Support: Full support for asynchronous method interception
- Configurable Behavior: Fine-grained control over what and how to log
- HTTP Middleware: Optional middleware for request/response logging
- Performance-Aware: Configurable performance thresholds and filtering
- Structured Logging: Native support for structured logging with Microsoft.Extensions.Logging
- Real-time Dashboard: Web-based dashboard for monitoring logs in real-time (like Hangfire)
- Zero External Dependencies: Uses only Microsoft's built-in libraries
Architecture
System Architecture
graph TB
subgraph "Client Layer"
Controller[ASP.NET Controller]
Consumer[Service Consumer]
end
subgraph "Proxy Layer"
LoggingProxy[LoggingProxy<T>]
DispatchProxy[DispatchProxy Base]
end
subgraph "Service Layer"
Interface[IService Interface]
Implementation[Service Implementation]
end
subgraph "Cross-Cutting Concerns"
Logger[ILogger]
HttpContext[HttpContextAccessor]
Options[LoggingProxyOptions]
end
subgraph "Middleware Layer"
LoggingMiddleware[HTTP Logging Middleware]
Pipeline[ASP.NET Pipeline]
end
Controller --> LoggingProxy
Consumer --> LoggingProxy
LoggingProxy -.inherits.-> DispatchProxy
LoggingProxy --> Interface
Interface -.implemented by.-> Implementation
LoggingProxy --> Logger
LoggingProxy --> HttpContext
LoggingProxy --> Options
Pipeline --> LoggingMiddleware
LoggingMiddleware --> Pipeline
style LoggingProxy fill:#e1f5ff
style Implementation fill:#fff4e1
style Logger fill:#e8f5e9
Component Diagram
graph LR
subgraph "AspectLogging Library"
subgraph "Core Components"
LP[LoggingProxy<T>]
SCE[ServiceCollectionExtensions]
end
subgraph "Configuration"
LPO[LoggingProxyOptions]
Preset[LoggingPreset]
end
subgraph "Formatting"
VF[ValueFormatter]
TF[TypeFormatter]
end
subgraph "Attributes"
NLA[NoLogAttribute]
end
subgraph "Middleware"
LM[LoggingMiddleware]
end
end
SCE --> LP
SCE --> LPO
SCE --> Preset
LP --> LPO
LP --> VF
LP --> NLA
VF --> TF
style LP fill:#e1f5ff
style SCE fill:#e1f5ff
style LPO fill:#fff4e1
Key Features
1. Dynamic Proxy Interception
AspectLogging uses DispatchProxy to create runtime proxies that wrap your service interfaces:
sequenceDiagram
participant Client
participant Proxy as LoggingProxy
participant Logger
participant Service as Service Implementation
Client->>Proxy: CallMethod(args)
activate Proxy
Proxy->>Logger: Log Entry (Method, Args)
Proxy->>Service: Invoke Method(args)
activate Service
alt Success
Service-->>Proxy: Return Result
Proxy->>Logger: Log Exit (Duration, Result)
Proxy-->>Client: Return Result
else Exception
Service--xProxy: Throw Exception
Proxy->>Logger: Log Exception (Duration, Error)
Proxy--xClient: Rethrow Exception
end
deactivate Service
deactivate Proxy
2. Asynchronous Method Support
Full support for Task and Task<T> return types with proper async/await handling:
sequenceDiagram
participant Client
participant Proxy as LoggingProxy<IService>
participant Logger
participant Service as Async Service
Client->>Proxy: CallAsyncMethod()
activate Proxy
Proxy->>Logger: Log Entry
Proxy->>Service: Invoke Async Method
Note over Proxy: Start Stopwatch
Proxy-->>Client: Return Task
deactivate Proxy
Note over Service: Async Operation
Service-->>Proxy: Task Completes
activate Proxy
Note over Proxy: Stop Stopwatch
Proxy->>Logger: Log Exit (Duration, Result)
deactivate Proxy
3. Dependency Injection Integration
Seamless integration with Microsoft.Extensions.DependencyInjection:
graph TD
subgraph "Service Registration Flow"
A[IServiceCollection] --> B{AddAspectLogging}
B --> C[Scan Registered Services]
C --> D{Is Interface?}
D -->|Yes| E{Matches Namespace?}
D -->|No| F[Skip]
E -->|Yes| G{Is Excluded?}
E -->|No| F
G -->|No| H[Create Proxy Decorator]
G -->|Yes| F
H --> I[Replace Service Registration]
I --> J[Original Service as Decorated]
J --> K[Proxy as Service]
end
style B fill:#e1f5ff
style H fill:#e1f5ff
style K fill:#c8e6c9
4. Real-time Logging Dashboard
Monitor your application's logs in real-time through a web-based dashboard:
graph TD
subgraph "Dashboard Architecture"
A[ASP.NET MVC] --> B[SignalR Hub]
B --> C[DashboardLoggerProvider]
C --> D[In-Memory Log Store]
D --> E[Configurable Buffer]
F[Web Client] --> G[SignalR Connection]
G --> B
F --> H[REST API]
H --> I[Log Filtering & Search]
J[Application Logs] --> C
end
style B fill:#e1f5ff
style D fill:#fff4e1
style G fill:#c8e6c9
Features:
- Real-time log streaming via SignalR
- Configurable log buffer size
- RESTful API for log retrieval
- Web-based UI for monitoring
- Log filtering and search capabilities
5. Persistent Database Storage
Store logs and performance metrics in a database for long-term analysis:
graph TD
subgraph "Database Storage"
A[Application] --> B[DatabaseLoggerProvider]
B --> C[Batch Processing]
C --> D[AspectLoggingDbContext]
D --> E[(Database)]
F[Dashboard] --> G[REST API]
G --> D
F --> H[Statistics Queries]
H --> I[Method Performance]
H --> J[Error Analysis]
end
style D fill:#e1f5ff
style E fill:#fff4e1
Supported Databases:
- SQLite (default, file-based)
- SQL Server
- MySQL
- PostgreSQL
Features:
- Automatic schema creation
- Method call statistics tracking
- Performance metrics collection
- Slowest queries analysis
- Configurable data retention
Installation
Install via NuGet Package Manager:
dotnet add package Mariodbx.AspectLogging
Or via Package Manager Console:
Install-Package Mariodbx.AspectLogging
Quick Start
Basic Setup
using AspectLogging;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register your services
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IOrderService, OrderService>();
// Add aspect logging with auto-detection
builder.Services.AddAspectLogging();
var app = builder.Build();
With Specific Namespaces
// Only log services in specific namespaces
builder.Services.AddAspectLogging("MyCompany.Services", "MyCompany.Repositories");
With Presets
// Development: Verbose logging, all details
builder.Services.AddAspectLogging(LoggingPreset.Development);
// Production: Exceptions and slow operations only
builder.Services.AddAspectLogging(LoggingPreset.Production);
// Balanced: Recommended for most scenarios
builder.Services.AddAspectLogging(LoggingPreset.Balanced);
Add Database Storage (Optional)
For persistent storage and analytics, add database support:
// SQLite (default)
builder.Services.AddAspectLoggingDatabase();
// SQL Server
builder.Services.AddAspectLoggingSqlServer("Server=...;Database=...;");
// MySQL
builder.Services.AddAspectLoggingMySql("Server=...;Database=...;");
// PostgreSQL
builder.Services.AddAspectLoggingPostgreSql("Host=...;Database=...;");
Add Real-time Dashboard (Optional)
// In ConfigureServices
builder.Services.AddAspectLoggingDashboard(maxLogEntries: 2000);
// In Configure (after UseRouting)
app.UseAspectLoggingDashboard("/logging");
Access the dashboard at: https://yourapp/logging
Configuration
Configuration via Code
builder.Services.AddLoggingProxyForInterfaces(options =>
{
options.Enabled = true;
options.IncludeNamespacePrefixes = new[] { "MyApp" };
options.LogEntry = true;
options.LogExit = true;
options.LogExceptions = true;
options.LogDetailedArgs = true;
options.LogDetailedReturns = true;
options.MinimumDurationMs = 10;
options.MaxReturnValueLength = 500;
options.EntryLogLevel = LogLevel.Information;
options.ExitLogLevel = LogLevel.Information;
options.ExceptionLogLevel = LogLevel.Error;
});
Configuration via appsettings.json
{
"LoggingProxy": {
"Enabled": true,
"IncludeNamespacePrefixes": ["MyApp.Services", "MyApp.Repositories"],
"ExcludedServiceTypeFullNames": ["MyApp.Services.IHealthCheckService"],
"IgnoredMethods": ["MyApp.Services.IUserService.GetUserTypesAsync"],
"LogEntry": true,
"LogExit": true,
"LogExceptions": true,
"LogDetailedArgs": true,
"LogDetailedReturns": true,
"MinimumDurationMs": 10,
"MaxReturnValueLength": 500,
"IncludeRequestId": true,
"UseStructuredLogging": true,
"SwallowLoggingErrors": true
}
}
Configuration Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
Enabled |
bool | true | Enable/disable logging proxy globally |
IncludeNamespacePrefixes |
string[] | ["AspectLogging"] | Only wrap services matching these namespace prefixes |
ExcludedServiceTypeFullNames |
string[] | [] | Service types to never wrap |
IgnoredMethods |
string[] | [] | Specific methods to exclude from logging |
LogEntry |
bool | true | Log method entry |
LogExit |
bool | true | Log method exit |
LogExceptions |
bool | true | Log exceptions |
LogDetailedArgs |
bool | true | Log detailed argument values (vs. type names only) |
LogDetailedReturns |
bool | true | Log detailed return values (vs. type name only) |
MinimumDurationMs |
long | 0 | Only log methods taking longer than this (milliseconds) |
MaxReturnValueLength |
int | 500 | Maximum length for logged values (truncates beyond) |
IncludeRequestId |
bool | true | Include HTTP request ID in logs |
UseStructuredLogging |
bool | true | Use structured logging format |
EntryLogLevel |
LogLevel | Information | Log level for entry messages |
ExitLogLevel |
LogLevel | Information | Log level for exit messages |
ExceptionLogLevel |
LogLevel | Error | Log level for exception messages |
PerformanceThresholdMs |
long | 1000 | Threshold for performance warnings |
Logging Presets
graph TD
subgraph "Development Preset"
D1[LogEntry: true]
D2[LogExit: true]
D3[LogDetailedArgs: true]
D4[LogDetailedReturns: true]
D5[MinimumDurationMs: 0]
D6[EntryLogLevel: Debug]
end
subgraph "Balanced Preset"
B1[LogEntry: true]
B2[LogExit: true]
B3[LogDetailedArgs: true]
B4[LogDetailedReturns: true]
B5[MinimumDurationMs: 10]
B6[EntryLogLevel: Information]
end
subgraph "Production Preset"
P1[LogEntry: false]
P2[LogExit: true]
P3[LogDetailedArgs: false]
P4[LogDetailedReturns: false]
P5[MinimumDurationMs: 100]
P6[ExitLogLevel: Warning]
end
subgraph "Minimal Preset"
M1[LogEntry: false]
M2[LogExit: false]
M3[LogExceptions: true]
M4[LogDetailedArgs: false]
M5[LogDetailedReturns: false]
end
Advanced Usage
Excluding Specific Methods
Use the [NoLog] attribute to exclude methods from logging:
public interface IUserService
{
Task<User> GetUserAsync(int id);
[NoLog]
Task<string> GetPasswordHashAsync(int userId); // Not logged
}
Custom Type Formatting
The library automatically formats complex types. For collections:
// Input: List<int> { 1, 2, 3, 4, 5 }
// Output: List<int>[5] { 1, 2, 3, 4, 5 }
// Input: Dictionary<string, object>
// Output: Dictionary<string, object>[3] { Key1=Value1, Key2=Value2, Key3=Value3 }
For custom types, properties are serialized:
// Input: User { Id = 1, Name = "John", Email = "john@example.com" }
// Output: User { Id: 1, Name: "John", Email: "john@example.com" }
Performance Filtering
Filter logs based on execution duration:
options.MinimumDurationMs = 50; // Only log methods taking >= 50ms
options.PerformanceThresholdMs = 1000; // Log as Warning if >= 1 second
Structured Logging with Request Correlation
options.IncludeRequestId = true;
options.UseStructuredLogging = true;
Log output includes structured properties:
{
"Timestamp": "2025-11-25T10:30:45.123Z",
"Level": "Information",
"MessageTemplate": "Exit {Method} (ms={Elapsed}) with return {@Return}",
"Properties": {
"Method": "MyApp.Services.IUserService.GetUserAsync",
"Elapsed": 45,
"Return": { "Id": 1, "Name": "John" },
"RequestId": "0HMVQK8B7QKQJ:00000001"
}
}
Logging Dashboard
AspectLogging includes a real-time web-based dashboard for monitoring logs, similar to Hangfire's dashboard. The dashboard provides:
- Real-time log streaming using SignalR
- Filtering by log level and text search
- Request isolation by RequestId
- Clear logs functionality
- Responsive design for desktop and mobile
Setup
- Register the dashboard in
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddAspectLogging();
services.AddAspectLoggingDashboard(maxLogEntries: 2000);
}
- Enable the dashboard in the middleware pipeline:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... other middleware
app.UseAspectLoggingDashboard("/logging");
}
- Access the dashboard at
https://yourapp/logging
Dashboard Features
- Live Updates: New logs appear instantly without page refresh
- Filtering: Filter by log level (Debug, Info, Warning, Error, Critical) or search text
- Request Tracing: Group logs by RequestId to trace complete request flows
- Performance: Keeps last N entries in memory (configurable)
- API Endpoints:
GET /logging/api/logs- Get current logs as JSONPOST /logging/api/clear- Clear all logs
Example Usage
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddControllers();
builder.Services.AddAspectLogging();
builder.Services.AddAspectLoggingDashboard();
var app = builder.Build();
// Configure middleware
app.UseRouting();
app.UseAspectLoggingDashboard();
app.UseEndpoints(endpoints => endpoints.MapControllers());
How It Works
Method Interception Flow
flowchart TD
A[Method Call] --> B{Has NoLog?}
B -->|Yes| C[Direct Invocation]
B -->|No| D{In Ignored Methods?}
D -->|Yes| C
D -->|No| E[Start Stopwatch]
E --> F{LogEntry Enabled?}
F -->|Yes| G[Log Entry with Args]
F -->|No| H[Invoke Target Method]
G --> H
H --> I{Returns Task?}
I -->|Yes| J[Async Interception]
I -->|No| K[Synchronous Handling]
J --> L[Attach Continuation]
L --> M{Task Completes?}
M -->|Success| N[Log Exit with Result]
M -->|Faulted| O[Log Exception]
N --> P[Return Result]
O --> Q[Rethrow Exception]
K --> R{Exception Thrown?}
R -->|Yes| S[Stop Stopwatch]
R -->|No| T[Stop Stopwatch]
S --> U{LogExceptions?}
T --> V{LogExit and Duration OK?}
U -->|Yes| W[Log Exception]
V -->|Yes| X[Log Exit]
W --> Q
X --> P
U -->|No| Q
V -->|No| P
C --> P
style E fill:#e1f5ff
style G fill:#e1f5ff
style N fill:#e1f5ff
style O fill:#ffcdd2
style W fill:#ffcdd2
Service Registration Process
sequenceDiagram
participant App as Application Code
participant DI as IServiceCollection
participant Ext as ServiceCollectionExtensions
participant Factory as Proxy Factory
App->>DI: AddScoped<IService, Service>()
App->>Ext: AddAspectLogging()
activate Ext
Ext->>DI: Get All Descriptors
DI-->>Ext: ServiceDescriptor[]
loop For Each Service
Ext->>Ext: Is Interface & Matches Namespace?
alt Should Wrap
Ext->>Factory: Create Proxy Factory
Factory-->>Ext: Func<IServiceProvider, IService>
Ext->>DI: Remove Original Descriptor
Ext->>DI: Register Decorated (Original)
Ext->>DI: Register Proxy (Interface)
else Skip
Note over Ext: Leave Original Registration
end
end
deactivate Ext
App->>DI: Build ServiceProvider
DI-->>App: IServiceProvider
App->>DI: GetService<IService>()
DI->>Factory: Create Proxy
Factory->>DI: Resolve Decorated Service
DI-->>Factory: Original Service Instance
Factory->>Factory: Create LoggingProxy<IService>
Factory->>Factory: Initialize with Decorated, Logger, Options
Factory-->>DI: Proxy Instance
DI-->>App: LoggingProxy<IService>
Async Method Interception
flowchart TD
A[Async Method Invoked] --> B[Log Entry]
B --> C[Invoke Target Method]
C --> D[Receive Task]
D --> E{Task<T> or Task?}
E -->|Task<T>| F[Use Generic Interception]
E -->|Task| G[Use Non-Generic Interception]
F --> H[Create Continuation Task]
G --> I[Create Continuation Task]
H --> J[Return Task to Caller]
I --> J
subgraph "Background Continuation"
K[Await Original Task]
K --> L{Success?}
L -->|Yes| M[Get Result]
L -->|Exception| N[Catch Exception]
M --> O[Stop Stopwatch]
N --> P[Stop Stopwatch]
O --> Q{Duration >= Min?}
Q -->|Yes| R[Log Exit with Result]
Q -->|No| S[Skip Logging]
R --> T[Return Result]
S --> T
P --> U[Log Exception]
U --> V[Rethrow]
end
J -.continuation.-> K
style H fill:#e1f5ff
style I fill:#e1f5ff
style R fill:#c8e6c9
style U fill:#ffcdd2
HTTP Middleware Flow
sequenceDiagram
participant Client
participant Middleware as LoggingMiddleware
participant Logger
participant Next as Next Middleware
participant App as Application
Client->>Middleware: HTTP Request
activate Middleware
Middleware->>Logger: Log Request (Method, Path, QueryString)
Note over Middleware: Start Stopwatch
alt Has Request Body
Middleware->>Middleware: Buffer & Read Body
Middleware->>Logger: Log Request Body
end
Middleware->>Next: InvokeAsync(context)
activate Next
Next->>App: Process Request
App-->>Next: Response
Next-->>Middleware: Continue
deactivate Next
Note over Middleware: Stop Stopwatch
Middleware->>Logger: Log Response (Status, Duration)
alt Has Response Body
Middleware->>Middleware: Read Response Body
Middleware->>Logger: Log Response Body
end
Middleware-->>Client: HTTP Response
deactivate Middleware
Dashboard Operation Flow
sequenceDiagram
participant Client as Web Browser
participant MVC as ASP.NET MVC
participant Hub as LoggingHub
participant Provider as DashboardLoggerProvider
participant Store as In-Memory Store
Client->>MVC: GET /logging
MVC-->>Client: Dashboard HTML
Client->>Hub: SignalR Connect
activate Hub
Hub->>Provider: Subscribe to Updates
Provider-->>Hub: Initial Log Batch
Hub-->>Client: Send Initial Logs
loop Real-time Updates
Provider->>Hub: New Log Entry
Hub->>Client: Push Log Update
end
Client->>MVC: GET /logging/api/logs?filter=...
MVC->>Provider: Query Logs
Provider->>Store: Filter & Search
Store-->>Provider: Filtered Results
Provider-->>MVC: JSON Response
MVC-->>Client: Filtered Logs
Performance Considerations
Overhead Analysis
graph LR
subgraph "Performance Impact Factors"
A[Proxy Creation] -->|One-time| B[Negligible]
C[Method Interception] -->|Per Call| D[Minimal]
E[Logging Operations] -->|Per Call| F[Configurable]
G[Formatting] -->|Per Value| H[Moderate]
end
subgraph "Optimization Strategies"
I[Use MinimumDurationMs]
J[Disable DetailedArgs/Returns]
K[Use Production Preset]
L[Exclude High-Frequency Methods]
M[Use Async Logging]
end
F --> I
F --> J
F --> K
H --> L
D --> M
style I fill:#c8e6c9
style J fill:#c8e6c9
style K fill:#c8e6c9
style L fill:#c8e6c9
style M fill:#c8e6c9
Recommendations
- Development Environment: Use
Developmentpreset for maximum observability - Staging Environment: Use
Balancedpreset with appropriate duration thresholds - Production Environment: Use
Productionpreset, log exceptions and slow operations - High-Performance Scenarios: Use
Minimalpreset or exclude specific services
Benchmarks
Typical overhead per method call:
- Without detailed logging: < 1 microsecond
- With detailed logging: 5-50 microseconds (depends on argument complexity)
- Async method interception: < 1 microsecond additional overhead
API Reference
Core Classes
LoggingProxy<T>
Dynamic proxy that intercepts method calls on interface T.
Key Methods:
Initialize(T decorated, ILogger logger, Type serviceInterfaceType, LoggingProxyOptions options, IHttpContextAccessor httpContextAccessor)Invoke(MethodInfo targetMethod, object[] args)- Core interception point
ServiceCollectionExtensions
Extension methods for registering logging proxies with DI container.
Methods:
// Auto-detect namespaces and use preset
IServiceCollection AddAspectLogging(
this IServiceCollection services,
LoggingPreset preset = LoggingPreset.Balanced)
// Specify namespaces with preset
IServiceCollection AddAspectLogging(
this IServiceCollection services,
LoggingPreset preset,
params string[] namespaces)
// Manual configuration
IServiceCollection AddLoggingProxyForInterfaces(
this IServiceCollection services,
Action<LoggingProxyOptions> configure)
// Configuration from IConfiguration
IServiceCollection AddLoggingProxyForInterfaces(
this IServiceCollection services,
IConfiguration configuration,
string sectionName = "LoggingProxy")
LoggingProxyOptions
Configuration options for proxy behavior. See Configuration Options Reference.
LoggingMiddleware
ASP.NET Core middleware for HTTP request/response logging.
Constructor:
public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
Dashboard APIs
ServiceCollectionExtensions (Dashboard)
Extension methods for registering the logging dashboard.
Methods:
// Register dashboard with default settings
IServiceCollection AddAspectLoggingDashboard(
this IServiceCollection services)
// Register dashboard with custom buffer size
IServiceCollection AddAspectLoggingDashboard(
this IServiceCollection services,
int maxLogEntries = 1000)
// Register dashboard with custom route
IApplicationBuilder UseAspectLoggingDashboard(
this IApplicationBuilder app,
string routePrefix = "/logging")
LoggingHub
SignalR hub for real-time log streaming.
Methods:
Task SubscribeToLogs()- Subscribe to real-time log updatesTask UnsubscribeFromLogs()- Unsubscribe from log updates
DashboardLoggerProvider
In-memory logger provider that buffers logs for the dashboard.
Constructor:
public DashboardLoggerProvider(
int maxLogEntries = 1000,
LogLevel minimumLevel = LogLevel.Information)
DashboardController
REST API controller for log retrieval and filtering.
Endpoints:
GET /api/logs- Get all logs with optional filteringGET /api/logs/{id}- Get specific log entryDELETE /api/logs- Clear all logs
Query Parameters:
level- Filter by log level (Information, Warning, Error, etc.)category- Filter by logger categorysearch- Search in message textfrom- Start date/time (ISO 8601)to- End date/time (ISO 8601)skip- Number of entries to skiptake- Maximum number of entries to return
Database Classes
AspectLoggingDbContext
Entity Framework Core database context for AspectLogging.
Key Methods:
EnsureDatabaseCreatedAsync()- Creates database and schemaGetLogsAsync(...)- Query logs with filteringGetSlowestMethodsAsync(int top)- Get slowest method callsGetMostCalledMethodsAsync(int top)- Get most frequently called methodsUpdateMethodStatsAsync(string className, string methodName, long durationMs, bool success)- Update method statistics
DatabaseLoggerProvider
Database-backed logger provider that persists logs and collects statistics.
Configuration Options:
Provider- Database provider (Sqlite, SqlServer, MySql, PostgreSql)ConnectionString- Database connection stringEnableAutoMigrations- Whether to enable automatic migrationsLogRetentionDays- Days to keep log entriesMetricsRetentionDays- Days to keep performance metrics
Attributes
[NoLog]
Opt-out attribute to exclude methods, interfaces, or classes from logging.
Usage:
[NoLog]
public interface ISensitiveService { ... }
public interface IUserService
{
[NoLog]
Task<string> GetPasswordHashAsync(int userId);
}
Formatters
ValueFormatter
Formats values for logging with intelligent handling of collections, primitives, and custom types.
Configuration:
public ValueFormatter(
int maxCollectionItems = 10,
int maxPropertyCount = 10)
TypeFormatter
Provides human-readable type names for generic types.
Example:
TypeFormatter.GetFriendlyTypeName(typeof(List<int>))
// Returns: "List<int>"
TypeFormatter.GetFriendlyTypeName(typeof(Dictionary<string, List<User>>))
// Returns: "Dictionary<string, List<User>>"
System Requirements
- .NET: 8.0 or higher
- Dependencies:
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0)
- Dashboard Dependencies (optional):
- Microsoft.AspNetCore.SignalR (>= 8.0.0)
- Microsoft.AspNetCore.Mvc (>= 8.0.0)
- System.Text.Json (>= 8.0.0)
- Database Dependencies (optional):
- Microsoft.EntityFrameworkCore (>= 8.0.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.0) - for SQL Server
- Pomelo.EntityFrameworkCore.MySql (>= 8.0.0) - for MySQL
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 8.0.0) - for PostgreSQL
Contributing
Contributions are welcome. Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
Development Setup
- Clone the repository
- Restore dependencies:
dotnet restore - Build the solution:
dotnet build - Run tests:
dotnet test
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built on .NET's
DispatchProxyfor dynamic proxy generation - Designed for integration with Microsoft.Extensions.Logging
- Optimized for Microsoft.Extensions.Logging structured logging
Support
For issues, questions, or contributions, please visit:
- GitHub Issues: https://github.com/mariodbx/aspect-logging/issues
- Documentation: https://github.com/mariodbx/aspect-logging
- NuGet Package: https://www.nuget.org/packages/Mariodbx.AspectLogging
Version: 1.0.1
Author: Mario De Benedictis
Repository: https://github.com/mariodbx/aspect-logging
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net8.0
- Microsoft.AspNetCore.Http (>= 2.2.2)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0)
- Microsoft.AspNetCore.Mvc.Core (>= 2.2.5)
- Microsoft.AspNetCore.SignalR (>= 1.1.0)
- Microsoft.EntityFrameworkCore (>= 8.0.0)
- Microsoft.EntityFrameworkCore.Design (>= 8.0.0)
- Microsoft.EntityFrameworkCore.Sqlite (>= 8.0.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 8.0.0)
- Pomelo.EntityFrameworkCore.MySql (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.0.1 - Major Feature Update
- Real-time logging dashboard with SignalR and web UI
- Database storage with multi-provider support (SQLite, SQL Server, MySQL, PostgreSQL)
- Method call statistics and performance analytics (slowest queries, call counts, success rates)
- Automatic database schema creation (like Hangfire)
- REST API for log querying and statistics
- Modern JSON handling with System.Text.Json
- Zero external dependencies (Microsoft libraries only)
- Enhanced dashboard with statistics visualization
v1.0.0 - Initial release
- Dynamic proxy-based method interception
- Configurable via code or appsettings.json
- Async method support
- Custom type and value formatting
- HTTP middleware for request/response logging
- Performance thresholds and filtering
- Structured logging support