Skip to content

int80x0/Pine

Repository files navigation

🌲 Pine Logger

A modern, high-performance logging library for .NET that combines simplicity with powerful features. Now with optimized extension methods and hot-path performance improvements.

.NET License NuGet

✨ Features

  • 🎨 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

πŸš€ Quick Start

Installation

dotnet add package 80x0.pine

Basic Usage

using 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();

Environment-Specific Configuration

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();

⚑ Performance Features

Pine is optimized for maximum performance:

Hot-Path Optimization with Extension Methods

// 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

Extension Methods for Better Performance

// 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" });

πŸ“Š Log Rotation

File Rotation by Size

.WriteToRotatingFile("logs/app.log", 
    maxFileSize: 50 * 1024 * 1024,  // 50MB
    maxFiles: 10,                   // Keep 10 files
    compress: true)                 // Compress old files with gzip

JSON File Rotation

.WriteToRotatingJsonFile("logs/structured.json", 
    maxFileSize: 25 * 1024 * 1024, 
    maxFiles: 5)

Files are rotated with timestamps: app.20241215-143022.log.gz

🌐 Environment-Aware Logging

Pine automatically detects your environment using DOTNET_ENVIRONMENT or ASPNETCORE_ENVIRONMENT:

Conditional Targets

// 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")

Environment Detection

// Set environment variables:
// DOTNET_ENVIRONMENT=Development
// ASPNETCORE_ENVIRONMENT=Production

EnvironmentHelper.IsDevelopment();  // true/false
EnvironmentHelper.IsProduction();   // true/false  
EnvironmentHelper.GetEnvironment(); // "Development", "Production", etc.

πŸ“Š Log Levels

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

🎯 Targets

Console Target

.WriteToConsole()                    // Default formatter with colors
.WriteToConsole(myFormatter)         // Custom formatter
.WriteToConsoleInDevelopment()       // Only in Development

File Targets

// 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)

JSON File Targets

.WriteToJsonFile("logs/app.json")           // Basic JSON logging
.WriteToRotatingJsonFile("logs/app.json",   // Rotating JSON logs
    maxFileSize: 25_000_000, maxFiles: 5)

πŸ› οΈ Advanced Usage

Category-Based Logging

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);

Structured Logging

logger.Info("Order processed", new Dictionary<string, object>
{
    ["OrderId"] = "ORD-001",
    ["CustomerId"] = 12345,
    ["Amount"] = 99.99m,
    ["ProcessingTimeMs"] = 250,
    ["Items"] = new[] { "Item1", "Item2" }
});

Exception Handling

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);
}

Custom Targets

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();

πŸ“ˆ Performance Benchmarks

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 allocates

πŸ—οΈ Architecture

Pine/
β”œβ”€β”€ 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

πŸ”§ Configuration Examples

Development Setup

var logger = PineLogger.Create()
    .MinimumLevel(LogLevel.Debug)
    .WriteToConsoleInDevelopment()
    .WithDefaultCategory("DevApp")
    .Build();

Production Setup

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();

Multi-Environment Setup

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();

πŸ“ Best Practices

  1. Use hot-path optimized methods - Always use template-based logging for performance
  2. Set appropriate minimum levels - Use Debug in dev, Info+ in production
  3. Configure environment-specific targets - Console for dev, files for production
  4. Use log rotation - Prevent disk space issues with automatic rotation
  5. Include relevant context - Add properties and categories for better debugging
  6. Handle exceptions properly - Always pass exception objects to Error/Fatal
  7. Dispose properly - Call Dispose() or use using statements
  8. Use compression in production - Save disk space with compressed rotated files

πŸ”„ Migration from Other Loggers

From Serilog

// 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();

From NLog

// NLog
var logger = LogManager.GetCurrentClassLogger();

// Pine equivalent  
var logger = PineLogger.Create()
    .WithDefaultCategory(nameof(MyClass))
    .WriteToConsoleInDevelopment()
    .WriteToRotatingFileInProduction("logs/app.log")
    .Build();

🌟 What's New in v2.1.0

  • πŸš€ 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

🀝 Contributing

Contributions are welcome! Please feel free to:

  • πŸ› Report bugs
  • πŸ’‘ Suggest features
  • πŸ“ Improve documentation
  • πŸ”§ Submit pull requests

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

🌟 Why Pine?

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! 🌲

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages