Shaunebu.Common.Logging 1.0.0

dotnet add package Shaunebu.Common.Logging --version 1.0.0
                    
NuGet\Install-Package Shaunebu.Common.Logging -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Shaunebu.Common.Logging" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Shaunebu.Common.Logging" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Shaunebu.Common.Logging" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Shaunebu.Common.Logging --version 1.0.0
                    
#r "nuget: Shaunebu.Common.Logging, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Shaunebu.Common.Logging@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Shaunebu.Common.Logging&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Shaunebu.Common.Logging&version=1.0.0
                    
Install as a Cake Tool

Shaunebu.Common.Logging 📝🚀

Platform License Production Ready Performance Easy

NuGet Version NuGet Downloads

NET Support NET Support NET Support MAUI CSharp Architecture

Logging Providers Batching ThreadSafe

Support

Overview ✨

Shaunebu.Common.Logging is a high-performance, extensible logging library built for modern .NET applications with first-class MAUI support. It provides structured logging, lazy evaluation, and enterprise-grade features while maintaining simplicity and excellent performance.


Feature Comparison 🆚


Feature Microsoft.Extensions.Logging Serilog Shaunebu.Common.Logging Benefit
Structured Logging 🏷️ ✅ (With extensions) ✅ Excellent ✅ Built-in Rich, queryable logs
MAUI Optimization 📱 ❌ Generic ❌ Generic ✅ Native Support Mobile-first design
Lazy Evaluation ⚡ ✅ Built-in Zero cost when disabled
Batch Processing 📦 ✅ (Sinks) ✅ Built-in Better performance
File Rotation 📁 ✅ (Sinks) ✅ Built-in Automatic management
Async by Default 🔄 ✅ Optimized Non-blocking operations
Configuration ⚙️ JSON/Code Code/JSON ✅ Fluent API Developer friendly
Dependencies 📦 Minimal Moderate ✅ Lightweight Faster startup
Learning Curve 📚 Low Medium ✅ Very Low Rapid onboarding
Performance 🚀 Good Very Good ✅ Excellent Optimized pipelines

Installation 📦


dotnet add package Shaunebu.Common.Logging

Quick Start 🚀

1. Basic Setup

// In MauiProgram.cs or Startup
builder.Services.AddShaunebuLogging(options =>
{
    options.MinimumLevel = LogLevel.Debug;
    options.ApplicationName = "MyApp";
    options.Environment = "Development";
    options.BatchSize = 50;
    options.BatchInterval = TimeSpan.FromSeconds(2);
})
.AddConsole()
.AddFile(options =>
{
    options.FilePath = "logs/myapp.log";
    options.MaxFileSizeBytes = 5 * 1024 * 1024; // 5MB
});

2. Basic Usage

public class MyService
{
    private readonly ILogger _logger;

    public MyService(ILogger logger)
    {
        _logger = logger;
    }

    public void ProcessOrder(Order order)
    {
        // Basic logging
        _logger.LogInformation("Processing order {OrderId}", order.Id);
        
        // Error handling
        try
        {
            Process(order);
            _logger.LogInformation("Order {OrderId} processed successfully", order.Id);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to process order {OrderId}", order.Id);
        }
    }
}

Core Features 🎯


1. Structured Logging 🏷️

// Automatic property extraction
_logger.LogInformation(
    "User {UserName} with ID {UserId} purchased {ItemCount} items for ${Total}",
    "JohnDoe", 12345, 3, 99.99m);

// Complex objects
var user = new { Id = 123, Name = "John", Email = "john@example.com" };
_logger.LogDebug("User object: {User}", user);

2. Lazy Evaluation ⚡

// Expensive operations only run when level is enabled
_logger.LogDebug(() => {
    var expensiveData = CalculateExpensiveMetrics();
    return $"Performance metrics: {expensiveData}";
});

// Only executes if Debug level is enabled
_logger.LogInformation(() => {
    var stats = GetDatabaseStatistics();
    return $"DB Stats - Connections: {stats.Active}, Memory: {stats.UsedMB}MB";
});

3. Scoped Logging 🔄

using (_logger.BeginScope("ORDER_PROCESSING"))
{
    _logger.LogInformation("Starting order processing");
    
    using (_logger.BeginScope(new Dictionary<string, object>
    {
        ["OrderId"] = order.Id,
        ["CustomerId"] = order.CustomerId,
        ["TotalAmount"] = order.Total
    }))
    {
        _logger.LogDebug("Processing order items");
        // All logs in this scope include order context
    }
    
    _logger.LogInformation("Order processing completed");
}

4. Multiple Providers 🎪

// Console with colors
.AddConsole(options =>
{
    options.MinimumLevel = LogLevel.Debug;
    options.IncludeProperties = true;
    options.TimestampFormat = "HH:mm:ss.fff";
})

// File with rotation
.AddFile(options =>
{
    options.FilePath = "logs/app.log";
    options.MaxFileSizeBytes = 10 * 1024 * 1024; // 10MB
    options.MaxFileCount = 10;
    options.IncludeExceptionStacktrace = true;
})

// Custom providers
.AddCustomProvider<MyCustomLoggingProvider>()

5. Performance Optimization 🚀

// Batch processing - groups logs for better performance
services.AddShaunebuLogging(options =>
{
    options.BatchSize = 100;           // Process in batches of 100
    options.BatchInterval = TimeSpan.FromSeconds(5); // Or every 5 seconds
    options.FlushTimeout = TimeSpan.FromSeconds(30); // Graceful shutdown
});

Advanced Usage 🛠️


Configuration-Based Setup

{
  "Logging": {
    "MinimumLevel": "Information",
    "ApplicationName": "MyApp",
    "Environment": "Production",
    "IncludeScopes": true,
    "BatchSize": 100,
    "BatchInterval": "00:00:05",
    "LevelOverrides": {
      "Microsoft": "Warning",
      "System": "Error",
      "MyApp.Business": "Debug"
    }
  }
}
// Program.cs
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

services.AddShaunebuLogging(configuration.GetSection("Logging"));

Custom Logging Providers

public class CustomLoggingProvider : ILoggingProvider
{
    public string Name => "Custom";
    
    public Task WriteAsync(LogEntry entry)
    {
        // Send to your custom destination
        await SendToExternalService(entry);
        return Task.CompletedTask;
    }
    
    public bool IsEnabled(LogLevel level) => level >= LogLevel.Information;
}

Error Handling and Diagnostics

try
{
    var loggingService = serviceProvider.GetRequiredService<LoggingService>();
    
    // Force flush before shutdown
    await loggingService.FlushAsync(TimeSpan.FromSeconds(10));
}
catch (Exception ex)
{
    // Fallback logging
    Console.WriteLine($"Logging shutdown error: {ex.Message}");
}

MAUI-Specific Features 📱


Lifecycle Integration


public partial class App : Application
{
    private readonly ILogger _logger;
    private readonly LoggingService _loggingService;

    public App(ILogger logger, LoggingService loggingService)
    {
        _logger = logger;
        _loggingService = loggingService;
        InitializeComponent();
        MainPage = new MainPage();
    }

    protected override async void OnStart()
    {
        _logger.LogInformation("App starting");
        base.OnStart();
    }

    protected override async void OnSleep()
    {
        _logger.LogInformation("App going to sleep");
        await _loggingService.FlushAsync();
        base.OnSleep();
    }

    protected override void OnResume()
    {
        _logger.LogInformation("App resuming");
        base.OnResume();
    }
}

Platform-Specific Logging

#if ANDROID
_logger.LogDebug("Android-specific logging");
#elif IOS
_logger.LogDebug("iOS-specific logging");
#elif WINDOWS
_logger.LogDebug("Windows-specific logging");
#endif

Performance Tips 🚀


  1. Use Lazy Evaluation for expensive log message generation

  2. Configure Appropriate Batch Sizes for your workload

  3. Set Proper Minimum Levels in production

  4. Use Scoped Logging for contextual information

  5. Choose Right Providers for your platform needs

Performance Comparison

Scenario Traditional Logging Shaunebu.Common.Logging Improvement
Disabled Debug Logs Message created ✅ No creation 100% faster
High-Volume Logging Immediate write ✅ Batched write 3-5x throughput
Mobile Battery Constant I/O ✅ Optimized batching Better battery life
Startup Time Heavy initialization ✅ Lazy initialization Faster startup

##Best Practices 📝


✅ DO:

// Use structured logging
_logger.LogInformation("User {UserId} completed action {ActionType}", userId, actionType);

// Use lazy evaluation for expensive operations
_logger.LogDebug(() => $"Computed value: {ExpensiveCalculation()}");

// Use scopes for contextual logging
using (_logger.BeginScope("HTTP_REQUEST"))
{
    _logger.LogInformation("Processing request");
}

// Set appropriate levels per category
options.LevelOverrides["Microsoft.EntityFrameworkCore"] = LogLevel.Warning;

❌ DON'T:

// Don't use string concatenation
_logger.LogDebug("User " + userId + " did " + action); // ❌

// Don't ignore exceptions
_logger.LogError("Something failed"); // ❌ No exception

// Don't log sensitive information
_logger.LogInformation($"User password: {password}"); // ❌ Security risk

API Reference 📚


ILogger Interface

Method Description
Log(level, message, exception, properties) Core logging method
LogTrace(message, properties) / LogTrace(messageTemplate, params) Trace level logging
LogDebug(message, properties) / LogDebug(messageTemplate, params) Debug level logging
LogInformation(message, properties) / LogInformation(messageTemplate, params) Information level logging
LogWarning(message, properties) / LogWarning(messageTemplate, params) Warning level logging
LogError(message, exception, properties) / LogError(exception, messageTemplate, params) Error level logging
LogCritical(message, exception, properties) / LogCritical(exception, messageTemplate, params) Critical level logging
BeginScope(scopeName) / BeginScope(properties) Create logging scope
IsEnabled(level) Check if level is enabled

LoggingService

Method Description
CreateLogger(categoryName) Create category-specific logger
FlushAsync(timeout?) Flush all pending logs
Dispose() Cleanup resources

Configuration Options

Option Default Description
MinimumLevel Information Minimum log level
ApplicationName "Unknown" Application identifier
Environment "Production" Runtime environment
BatchSize 100 Log batch size
BatchInterval 5 seconds Batch processing interval
IncludeScopes true Include scope information
LevelOverrides Empty Category-specific levels

Examples 🎨


MAUI ViewModel Logging

public class MainViewModel : ObservableObject
{
    private readonly ILogger _logger;

    public MainViewModel(ILogger logger)
    {
        _logger = logger;
        _logger.LogInformation("MainViewModel initialized");
    }

    private async Task LoadDataAsync()
    {
        using (_logger.BeginScope("DATA_LOADING"))
        {
            try
            {
                _logger.LogDebug("Starting data load");
                await LoadFromApiAsync();
                _logger.LogInformation("Data loaded successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to load data");
            }
        }
    }
}

API Controller Logging

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly ILogger _logger;

    public UsersController(ILogger<UsersController> logger)
    {
        _logger = logger;
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<User>> GetUser(int id)
    {
        using (_logger.BeginScope(new Dictionary<string, object>
        {
            ["Action"] = "GetUser",
            ["UserId"] = id,
            ["RequestId"] = HttpContext.TraceIdentifier
        }))
        {
            _logger.LogInformation("Getting user {UserId}", id);
            
            var user = await _userService.GetUserAsync(id);
            if (user == null)
            {
                _logger.LogWarning("User {UserId} not found", id);
                return NotFound();
            }

            _logger.LogDebug("Retrieved user {UserName} ({UserId})", user.Name, user.Id);
            return user;
        }
    }
}

Background Service Logging

public class BackgroundWorkerService : BackgroundService
{
    private readonly ILogger _logger;

    public BackgroundWorkerService(ILogger<BackgroundWorkerService> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Background worker started");

        while (!stoppingToken.IsCancellationRequested)
        {
            using (_logger.BeginScope("BACKGROUND_ITERATION"))
            {
                try
                {
                    _logger.LogDebug("Starting work iteration");
                    await DoWorkAsync(stoppingToken);
                    _logger.LogDebug("Work iteration completed");
                }
                catch (Exception ex) when (ex is not OperationCanceledException)
                {
                    _logger.LogError(ex, "Error in background work iteration");
                }
            }

            await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        }

        _logger.LogInformation("Background worker stopped");
    }
}

Troubleshooting 🔧


Common Issues

Logs not appearing?

  • Check MinimumLevel configuration

  • Verify provider-specific minimum levels

  • Ensure proper dependency injection setup

Performance issues?

  • Reduce batch size for low-memory environments

  • Increase batch interval for battery-sensitive apps

  • Use lazy evaluation for expensive log messages

Missing scoped properties?

  • Ensure IncludeScopes = true

  • Verify proper using statement for scopes

Debugging Configuration

// Enable self-logging for troubleshooting
services.AddShaunebuLogging(options =>
{
    options.MinimumLevel = LogLevel.Trace; // See all internal logs
    options.ApplicationName = "DebugApp";
});

// Check if logging is working
var logger = serviceProvider.GetRequiredService<ILogger>();
logger.LogInformation("Test message - if you see this, logging works!");

Migration Guide 🚚


From Microsoft.Extensions.Logging

// OLD - Microsoft.Extensions.Logging
services.AddLogging(builder =>
{
    builder.AddConsole();
    builder.AddDebug();
});

// NEW - Shaunebu.Common.Logging
services.AddShaunebuLogging(options =>
{
    options.MinimumLevel = LogLevel.Information;
})
.AddConsole()
.AddFile();

From Serilog

// OLD - Serilog
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .WriteTo.File("log.txt")
    .CreateLogger();

// NEW - Shaunebu.Common.Logging  
services.AddShaunebuLogging(options =>
{
    options.MinimumLevel = LogLevel.Debug;
})
.AddConsole()
.AddFile(options => options.FilePath = "log.txt");
Product Compatible and additional computed target framework versions.
.NET 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.0 367 11/21/2025