LayeredCraft.StructuredLogging
1.0.0.3
See the version list below for details.
dotnet add package LayeredCraft.StructuredLogging --version 1.0.0.3
NuGet\Install-Package LayeredCraft.StructuredLogging -Version 1.0.0.3
<PackageReference Include="LayeredCraft.StructuredLogging" Version="1.0.0.3" />
<PackageVersion Include="LayeredCraft.StructuredLogging" Version="1.0.0.3" />
<PackageReference Include="LayeredCraft.StructuredLogging" />
paket add LayeredCraft.StructuredLogging --version 1.0.0.3
#r "nuget: LayeredCraft.StructuredLogging, 1.0.0.3"
#addin nuget:?package=LayeredCraft.StructuredLogging&version=1.0.0.3
#tool nuget:?package=LayeredCraft.StructuredLogging&version=1.0.0.3
LayeredCraft.StructuredLogging
Simplified, structured logging for modern .NET apps — overloads, conditionals, and performance built-in.
Features
- 🚀 High Performance - Built-in level checks and efficient parameter handling
- 📊 Structured Logging - Rich contextual data with strongly-typed parameters
- 🔧 Easy Integration - Drop-in replacement for standard ILogger calls
- 🎯 Scope Management - Comprehensive scope tracking with automatic disposal
- ⚡ Performance Monitoring - Built-in timing and performance tracking
- 🧪 Testing Support - Complete testing framework with assertions and mocking
- 📦 Multi-Target - Supports .NET 8.0, .NET 9.0, and .NET Standard 2.1
Installation
dotnet add package LayeredCraft.StructuredLogging
Quick Start
using LayeredCraft.StructuredLogging;
using Microsoft.Extensions.Logging;
// Basic logging
logger.Information("User logged in successfully");
logger.Warning("Rate limit exceeded for user {UserId}", userId);
logger.Error(exception, "Failed to process order {OrderId}", orderId);
// Structured logging with multiple parameters
logger.Information("Order processed for user {UserId} with total {Total:C}",
userId, orderTotal);
// Performance monitoring
using (logger.TimeOperation("Database operation"))
{
// Your database code here
} // Automatically logs execution time
// Enriched logging with context
logger.LogWithContext(LogLevel.Information, "Starting order processing", "UserId", userId);
logger.InformationWithUserId(userId, "Order processing started");
Core Extensions
Log Level Extensions
All standard log levels are supported with convenient extension methods:
// Debug logging
logger.Debug("Debug information");
logger.Debug("Processing item {ItemId}", itemId);
// Verbose/Trace logging
logger.Verbose("Detailed trace information");
logger.Verbose("Entering method {MethodName}", methodName);
// Information logging
logger.Information("Operation completed successfully");
logger.Information("User {UserId} performed action {Action}", userId, action);
// Warning logging
logger.Warning("Performance threshold exceeded");
logger.Warning("Retry attempt {AttemptNumber} for operation {OperationId}",
attemptNumber, operationId);
// Error logging
logger.Error("Operation failed");
logger.Error(exception, "Failed to save entity {EntityId}", entityId);
// Critical logging
logger.Critical("System is in critical state");
logger.Critical(exception, "Database connection lost");
Scope Management
Create logging scopes for better context tracking:
// Simple scopes
using (logger.BeginScope("UserRegistration"))
{
logger.Information("Starting user registration");
// Registration logic
}
// Structured scopes with properties
using (logger.BeginScope("OrderId", orderId))
{
logger.Information("Processing order");
// Order processing logic
}
// Complex scopes with multiple properties
using (logger.BeginScopeWith(new { UserId = userId, SessionId = sessionId }))
{
logger.Information("User session started");
// Session logic
}
// Timed scopes for performance monitoring
using (logger.TimeOperation("DatabaseQuery"))
{
// Database operation
} // Automatically logs execution time
Enrichment
Add contextual information to log entries:
// Context-specific logging methods
logger.LogWithUserId(LogLevel.Information, userId, "User operation completed");
logger.LogWithRequestId(LogLevel.Information, requestId, "Request processed");
logger.LogWithCorrelationId(LogLevel.Information, correlationId, "Service call completed");
// Convenience methods for common log levels
logger.InformationWithUserId(userId, "User profile updated");
logger.WarningWithRequestId(requestId, "Request took longer than expected");
logger.ErrorWithCorrelationId(correlationId, "Service call failed", exception);
// Custom context enrichment
logger.LogWithContext(LogLevel.Information, "Operation completed", "Duration", duration);
logger.LogWithContext(LogLevel.Warning, "Rate limit approaching", "UserId", userId);
// Automatic caller information
logger.LogWithCaller(LogLevel.Debug, "Method execution completed");
logger.InformationWithCaller("Operation finished successfully");
Performance Monitoring
Built-in performance tracking capabilities:
// Timed operations
using (logger.TimeOperation("DatabaseQuery"))
{
// Your database code
} // Logs: "DatabaseQuery completed in 150ms"
// Synchronous timed operations
var result = logger.Time("CalculateSum", () =>
{
return numbers.Sum();
});
// Asynchronous timed operations
await logger.TimeAsync("FetchUserData", async () =>
{
await userService.GetUserAsync(userId);
});
// Method-level timing with caller info
using (logger.TimeMethod())
{
// Current method is automatically timed
}
Testing Support
Comprehensive testing framework for verifying logging behavior:
[Test]
public void Should_Log_User_Registration()
{
// Arrange
var testLogger = new TestLogger();
var userService = new UserService(testLogger);
// Act
userService.RegisterUser("john@example.com");
// Assert
testLogger.Should().HaveLoggedInformation()
.WithMessage("User registered successfully")
.WithProperty("Email", "john@example.com");
// Alternative assertion syntax
testLogger.AssertLogEntry(LogLevel.Information, "User registered");
testLogger.AssertLogCount(1);
testLogger.Should().HaveExactly(1).LogEntries();
}
[Test]
public void Should_Handle_Registration_Errors()
{
// Arrange
var testLogger = new TestLogger();
var userService = new UserService(testLogger);
// Act & Assert
Assert.Throws<ValidationException>(() =>
userService.RegisterUser("invalid-email"));
testLogger.Should().HaveLoggedError()
.WithException<ValidationException>()
.WithMessage("Invalid email format");
}
TestLogger Features
// Get specific log entries
var lastEntry = testLogger.GetLastLogEntry();
var errorEntries = testLogger.GetLogEntries(LogLevel.Error);
var entriesWithException = testLogger.GetLogEntriesWithException<ArgumentException>();
// Search log entries
var userEntries = testLogger.GetLogEntriesContaining("user");
var hasError = testLogger.HasLogEntry(LogLevel.Error, "failed");
// Assertions
testLogger.AssertLogCount(5);
testLogger.AssertLogEntry(LogLevel.Information, "expected message");
testLogger.AssertNoLogEntries(LogLevel.Error);
// Clear logs between tests
testLogger.Clear();
Advanced Usage
Conditional Logging
All logging methods include built-in level checks for optimal performance:
// These methods automatically check if the level is enabled
logger.Debug("Expensive debug info: {Data}", ExpensiveOperation());
// ExpensiveOperation() only called if Debug level is enabled
Exception Handling
Robust exception logging with context:
try
{
// Risky operation
}
catch (Exception ex)
{
logger.Error(ex, "Operation failed for user {UserId} in context {Context}",
userId, operationContext);
throw;
}
Integration with Dependency Injection
// Program.cs / Startup.cs
services.AddLogging(builder =>
{
builder.AddConsole();
builder.AddSerilog(); // or any other provider
});
// In your services
public class OrderService
{
private readonly ILogger<OrderService> _logger;
public OrderService(ILogger<OrderService> logger)
{
_logger = logger;
}
public async Task ProcessOrderAsync(int orderId)
{
using (_logger.TimeOperation("OrderProcessing"))
{
_logger.Information("Starting order processing for {OrderId}", orderId);
try
{
// Processing logic
_logger.Information("Order {OrderId} processed successfully", orderId);
}
catch (Exception ex)
{
_logger.Error(ex, "Failed to process order {OrderId}", orderId);
throw;
}
}
}
}
Configuration
The library works with any ILogger
implementation and follows standard .NET logging configuration:
// appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"System": "Warning"
}
}
}
Performance Considerations
- All methods include automatic level checks to avoid expensive operations
- Structured parameters use efficient formatting
- Scopes are implemented with minimal overhead
- Testing framework is optimized for fast test execution
Contributing
We welcome contributions! Please see our Contributing Guide for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for a detailed history of changes.
Built with ❤️ by LayeredCraft
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.5)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.5)
-
net9.0
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.5)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on LayeredCraft.StructuredLogging:
Package | Downloads |
---|---|
AlexaVoxCraft.MediatR
MediatR support for Alexa skill development, enabling clean request routing and handler composition. |
|
AlexaVoxCraft.Logging
Provides Alexa-specific logging components including an AWS CloudWatch-compatible JSON formatter. Built on LayeredCraft.StructuredLogging. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release of LayeredCraft.StructuredLogging with comprehensive logging extensions, scope management, enrichment capabilities, performance monitoring, and testing framework support.