A modern, high-performance logging library for .NET that combines simplicity with powerful features. Now with optimized extension methods and hot-path performance improvements.
- π¨ Colorized Console Output - Beautiful, color-coded log levels
- π Multiple Targets - Console, File, JSON file support with rotation
- π Log Rotation - Automatic file rotation by size with compression
- β‘ High Performance - Hot-path optimization, extension methods and async logging
- π§΅ Thread Safe - Built for concurrent applications
- π§ Flexible Configuration - Fluent API with environment-specific settings
- π Structured Logging - JSON format support with custom properties
- π·οΈ Categorized Logging - Organize logs by category/component
- π Environment Aware - Different targets for Development/Production
- π Modern C# - Leverages latest .NET 9 features with optimized extension methods and template-based logging
dotnet add package 80x0.pineusing Pine;
// Create logger with environment-specific configuration
var logger = PineLogger.Create()
.MinimumLevel(LogLevel.Info)
.WriteToConsoleInDevelopment() // Only in Development
.WriteToRotatingFileInProduction("logs/app.log") // Only in Production
.Build();
// High-performance extension methods for logging
logger.Info("User {UserId} performed {Action}", 123, "Login");
logger.Error("Failed to process order {OrderId}", orderId, exception);
// Async extension methods available too
await logger.InfoAsync("Async operation {Operation} completed", "UserSync");
// Cleanup
logger.Dispose();var logger = PineLogger.Create()
.MinimumLevel(LogLevel.Debug)
.WriteToConsole().OnlyInDevelopment()
.WriteToRotatingFile("logs/app.log", maxFileSize: 100_000_000, maxFiles: 7, compress: true).OnlyInProduction()
.WriteToRotatingJsonFile("logs/structured.json").OnlyInEnvironment("Staging")
.WithDefaultCategory("MyApp")
.Build();Pine is optimized for maximum performance:
// Extension methods with aggressive inlining - no string formatting if level is disabled
logger.Debug("Processing {ItemId} for {UserId}", itemId, userId); // β
Ultra Fast Extension Method
logger.Log(LogLevel.Debug, "Processing {ItemId} for {UserId}", itemId, userId); // β
Fast Core Method
logger.Debug($"Processing {itemId} for {userId}"); // β Always allocates// Optimized extension methods with aggressive inlining
logger.Info("User {UserId} action {Action}", 123, "Login");
logger.Error("Failed {Operation} for {Resource}", "Save", "Order", exception);
// Async extension methods for non-blocking operations
await logger.InfoAsync("Async operation {Operation} completed", "DataSync");
await logger.ErrorAsync("Async error in {Module}", "PaymentProcessor", exception);
// Traditional logging still supported
logger.Info("Traditional message", new Dictionary<string, object> { ["Key"] = "Value" });.WriteToRotatingFile("logs/app.log",
maxFileSize: 50 * 1024 * 1024, // 50MB
maxFiles: 10, // Keep 10 files
compress: true) // Compress old files with gzip.WriteToRotatingJsonFile("logs/structured.json",
maxFileSize: 25 * 1024 * 1024,
maxFiles: 5)Files are rotated with timestamps: app.20241215-143022.log.gz
Pine automatically detects your environment using DOTNET_ENVIRONMENT or ASPNETCORE_ENVIRONMENT:
// Method 1: Fluent conditions
.WriteToConsole().OnlyInDevelopment()
.WriteToFile("logs/prod.log").OnlyInProduction()
.WriteToRotatingFile("logs/staging.log").OnlyInStaging()
// Method 2: Convenience methods
.WriteToConsoleInDevelopment()
.WriteToRotatingFileInProduction("logs/app.log")
// Method 3: Custom conditions
.WriteToFile("logs/special.log").OnlyWhen(() => Environment.MachineName == "PROD-SERVER")// Set environment variables:
// DOTNET_ENVIRONMENT=Development
// ASPNETCORE_ENVIRONMENT=Production
EnvironmentHelper.IsDevelopment(); // true/false
EnvironmentHelper.IsProduction(); // true/false
EnvironmentHelper.GetEnvironment(); // "Development", "Production", etc.Pine supports 6 log levels with distinct colors and hot-path optimization:
| Level | Color | Description |
|---|---|---|
| Trace | Gray | Detailed diagnostic information |
| Debug | Blue | Debug information for development |
| Info | Green | General informational messages |
| Warning | Yellow | Warning messages for potential issues |
| Error | Red | Error messages for failures |
| Fatal | Magenta | Critical failures requiring attention |
.WriteToConsole() // Default formatter with colors
.WriteToConsole(myFormatter) // Custom formatter
.WriteToConsoleInDevelopment() // Only in Development// Basic file logging
.WriteToFile("logs/app.log")
// Rotating file with compression
.WriteToRotatingFile("logs/app.log",
maxFileSize: 100_000_000, // 100MB
maxFiles: 7, // Keep 7 files
compress: true) // Gzip compression
// Production-only rotating files
.WriteToRotatingFileInProduction("logs/prod.log",
maxFileSize: 500_000_000, maxFiles: 30, compress: true).WriteToJsonFile("logs/app.json") // Basic JSON logging
.WriteToRotatingJsonFile("logs/app.json", // Rotating JSON logs
maxFileSize: 25_000_000, maxFiles: 5)var apiLogger = logger.ForCategory("API");
var dbLogger = logger.ForCategory("Database");
apiLogger.Info("Request {Method} {Path} completed in {Duration}ms",
"GET", "/users/123", 45);
dbLogger.Debug("Query executed: {Query}", sql);logger.Info("Order processed", new Dictionary<string, object>
{
["OrderId"] = "ORD-001",
["CustomerId"] = 12345,
["Amount"] = 99.99m,
["ProcessingTimeMs"] = 250,
["Items"] = new[] { "Item1", "Item2" }
});try
{
await ProcessOrderAsync(order);
}
catch (ValidationException ex)
{
logger.Warning("Order validation failed for {OrderId}", order.Id, ex);
}
catch (Exception ex)
{
logger.Error("Unexpected error processing {OrderId}", order.Id, ex);
}public class DatabaseTarget : ILogTarget
{
public async Task WriteAsync(LogEntry entry)
{
// Save to database
await SaveToDatabase(entry);
}
public void Dispose() { /* cleanup */ }
}
// Usage
var logger = PineLogger.Create()
.AddTarget(new DatabaseTarget())
.Build();Pine's hot-path optimization provides significant performance benefits:
- π Zero Allocation - Disabled log levels cause zero allocations with extension methods
- β‘ Extension Methods - Aggressive inlining for maximum performance
- π― Span-Based Templates - Ultra-fast template processing with Span
- π Async Batching - File writes are batched for efficiency
- πΎ Smart Buffering - Automatic flush strategies
// Performance comparison
logger.Debug("Processing item {Id}", itemId); // β
~1ns when disabled (extension method)
logger.Log(LogLevel.Debug, "Processing item {Id}", itemId); // β
~2ns when disabled (core method)
logger.Debug($"Processing item {itemId}"); // β ~50ns always allocates
logger.Debug("Processing item " + itemId); // β ~80ns always allocatesPine/
βββ PineLogger.cs # Main logger with hot-path optimization
βββ LoggingExtensions.cs # Extension methods for maximum performance
βββ LogEntry.cs # Immutable log entry record
βββ ILogTarget.cs # Target interface
βββ Helpers/ # Performance utilities
β βββ TemplateHelper.cs # Span-based template processing
β βββ EnvironmentHelper.cs # Environment detection
βββ Targets/ # Built-in targets
β βββ ConsoleTarget.cs # Colorized console output
β βββ FileTarget.cs # Basic file writing with batching
β βββ RotatingFileTarget.cs # File rotation with compression
β βββ JsonFileTarget.cs # JSON structured logging
β βββ ConditionalTarget.cs # Environment-based conditions
βββ Formatters/ # Message formatters
β βββ ILogFormatter.cs # Formatter interface
β βββ DefaultFormatter.cs # Standard text format
β βββ JsonFormatter.cs # JSON format
βββ Configuration/ # Builder pattern setup
βββ PineConfiguration.cs # Configuration options
βββ LoggerBuilder.cs # Enhanced fluent builder
var logger = PineLogger.Create()
.MinimumLevel(LogLevel.Debug)
.WriteToConsoleInDevelopment()
.WithDefaultCategory("DevApp")
.Build();var logger = PineLogger.Create()
.MinimumLevel(LogLevel.Info)
.WriteToRotatingFileInProduction("logs/app.log",
maxFileSize: 100_000_000, maxFiles: 30, compress: true)
.WriteToRotatingJsonFile("logs/structured.json",
maxFileSize: 50_000_000, maxFiles: 15)
.WithDefaultCategory("ProdApp")
.Build();var logger = PineLogger.Create()
.MinimumLevel(LogLevel.Debug)
.WriteToConsole().OnlyInDevelopment()
.WriteToRotatingFile("logs/staging.log").OnlyInStaging()
.WriteToRotatingFile("logs/production.log",
maxFileSize: 200_000_000, maxFiles: 50, compress: true).OnlyInProduction()
.WriteToRotatingJsonFile("logs/audit.json").OnlyWhen(() =>
Environment.GetEnvironmentVariable("ENABLE_AUDIT") == "true")
.WithDefaultCategory("MultiEnvApp")
.Build();- Use hot-path optimized methods - Always use template-based logging for performance
- Set appropriate minimum levels - Use Debug in dev, Info+ in production
- Configure environment-specific targets - Console for dev, files for production
- Use log rotation - Prevent disk space issues with automatic rotation
- Include relevant context - Add properties and categories for better debugging
- Handle exceptions properly - Always pass exception objects to Error/Fatal
- Dispose properly - Call Dispose() or use using statements
- Use compression in production - Save disk space with compressed rotated files
// Serilog
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/app.log")
.CreateLogger();
// Pine equivalent
var logger = PineLogger.Create()
.WriteToConsole()
.WriteToRotatingFile("logs/app.log")
.Build();// NLog
var logger = LogManager.GetCurrentClassLogger();
// Pine equivalent
var logger = PineLogger.Create()
.WithDefaultCategory(nameof(MyClass))
.WriteToConsoleInDevelopment()
.WriteToRotatingFileInProduction("logs/app.log")
.Build();- π Extension Methods - Ultra-fast logging with aggressive inlining
- β‘ Span-Based Templates - Zero-allocation template processing with Span
- π― Simplified API - PineLogger reduced from 267 to 85 lines
- π§ Better Organization - Helper classes for cleaner architecture
- π Enhanced Async - Proper ConfigureAwait(false) throughout
- πΎ Resource Management - Improved disposal patterns in FileTarget
- π¦ Code Reduction - Eliminated 200+ lines of duplicate code
Contributions are welcome! Please feel free to:
- π Report bugs
- π‘ Suggest features
- π Improve documentation
- π§ Submit pull requests
This project is licensed under the MIT License - see the LICENSE file for details.
Pine combines the simplicity you need for quick development with the power required for production applications. With hot-path optimization, automatic log rotation, and environment-aware configuration, Pine scales from development to enterprise.
Perfect for:
- β ASP.NET Core applications
- β Console applications
- β Background services
- β Microservices
- β Desktop applications
- β High-performance applications
Happy logging with Pine! π²