MiniLogger 1.0.0

dotnet add package MiniLogger --version 1.0.0
                    
NuGet\Install-Package MiniLogger -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="MiniLogger" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MiniLogger" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="MiniLogger" />
                    
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 MiniLogger --version 1.0.0
                    
#r "nuget: MiniLogger, 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 MiniLogger@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=MiniLogger&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=MiniLogger&version=1.0.0
                    
Install as a Cake Tool

MiniLogger

A lightweight, plug-and-play console logger for .NET applications with color-coded output, structured logging, and scope support. MiniLogger makes logging simple, readable, and developer-friendly with minimal configuration.

Features

  • Color-coded console output for different log levels
  • Structured logging with key-value pairs and objects
  • Scope support for contextual logging
  • Minimal configuration - works out of the box
  • Thread-safe logging operations
  • Extensible sinks for custom output destinations
  • High performance with low overhead
  • Plug-and-play integration

Installation

dotnet add package MiniLogger

Quick Start

Basic Usage

using MiniLogger;

// Create a logger with console sink
var logger = new MiniLogger()
    .AddSink(new ConsoleLogSink());

// Simple logging
logger.Info("Application started");
logger.Warn("This is a warning message");
logger.Error("An error occurred");

Structured Logging

// Log with structured data
logger.Info("User login successful", new Dictionary<string, object>
{
    ["UserId"] = 12345,
    ["Username"] = "john.doe",
    ["IP"] = "192.168.1.100"
});

// Log with scope
using (logger.BeginScope("UserService"))
{
    logger.Debug("Processing user request", new Dictionary<string, object>
    {
        ["RequestId"] = Guid.NewGuid(),
        ["Method"] = "GetUserProfile"
    });
}

Advanced Usage

// Create logger with multiple sinks
var logger = new MiniLogger()
    .AddSink(new ConsoleLogSink())
    .AddSink(new FileLogSink("app.log"));

// Nested scopes
using (logger.BeginScope("Database"))
{
    logger.Info("Starting database operation");
    
    using (logger.BeginScope("Query"))
    {
        logger.Debug("Executing SELECT query", new Dictionary<string, object>
        {
            ["Table"] = "Users",
            ["Where"] = "Id = 123"
        });
    }
}

Log Levels

MiniLogger supports six log levels with color-coded output:

Level Color Description
Trace Gray Detailed diagnostic information
Debug Cyan Debugging information
Info Green General information messages
Warn Yellow Warning messages
Error Red Error messages
Critical Magenta Critical error messages

Custom Sinks

File Log Sink

public class FileLogSink : ILogSink
{
    private readonly string _filePath;
    private readonly object _lock = new object();

    public FileLogSink(string filePath)
    {
        _filePath = filePath;
    }

    public void Log(LogLevel level, string message, IDictionary<string, object>? data = null, string? scope = null)
    {
        var logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] ";
        
        if (!string.IsNullOrEmpty(scope))
            logEntry += $"[{scope}] ";
            
        logEntry += message;
        
        if (data != null)
        {
            logEntry += " | " + string.Join(" ", data.Select(kv => $"{kv.Key}={kv.Value}"));
        }

        lock (_lock)
        {
            File.AppendAllText(_filePath, logEntry + Environment.NewLine);
        }
    }
}

Remote Log Sink

public class RemoteLogSink : ILogSink
{
    private readonly HttpClient _httpClient;
    private readonly string _endpoint;

    public RemoteLogSink(string endpoint)
    {
        _httpClient = new HttpClient();
        _endpoint = endpoint;
    }

    public async void Log(LogLevel level, string message, IDictionary<string, object>? data = null, string? scope = null)
    {
        var logData = new
        {
            Level = level.ToString(),
            Message = message,
            Data = data,
            Scope = scope,
            Timestamp = DateTime.UtcNow
        };

        var json = System.Text.Json.JsonSerializer.Serialize(logData);
        var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
        
        await _httpClient.PostAsync(_endpoint, content);
    }
}

Integration Examples

ASP.NET Core Integration

public class MiniLoggerService
{
    private readonly MiniLogger _logger;

    public MiniLoggerService()
    {
        _logger = new MiniLogger()
            .AddSink(new ConsoleLogSink())
            .AddSink(new FileLogSink("app.log"));
    }

    public void LogRequest(HttpContext context)
    {
        using (_logger.BeginScope($"HTTP_{context.Request.Method}"))
        {
            _logger.Info($"Request to {context.Request.Path}", new Dictionary<string, object>
            {
                ["Method"] = context.Request.Method,
                ["Path"] = context.Request.Path,
                ["UserAgent"] = context.Request.Headers["User-Agent"].ToString(),
                ["IP"] = context.Connection.RemoteIpAddress?.ToString()
            });
        }
    }
}

Entity Framework Integration

public class LoggingDbContext : DbContext
{
    private readonly MiniLogger _logger;

    public LoggingDbContext(DbContextOptions<LoggingDbContext> options) : base(options)
    {
        _logger = new MiniLogger().AddSink(new ConsoleLogSink());
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        using (_logger.BeginScope("EF_SaveChanges"))
        {
            var count = ChangeTracker.Entries().Count();
            _logger.Debug($"Saving {count} entities");

            var result = await base.SaveChangesAsync(cancellationToken);
            
            _logger.Info($"Saved {result} entities successfully");
            return result;
        }
    }
}

Performance Monitoring

public class PerformanceLogger
{
    private readonly MiniLogger _logger;

    public PerformanceLogger()
    {
        _logger = new MiniLogger().AddSink(new ConsoleLogSink());
    }

    public IDisposable TimeOperation(string operationName)
    {
        var stopwatch = Stopwatch.StartNew();
        
        return new DisposableAction(() =>
        {
            stopwatch.Stop();
            _logger.Info($"Operation completed", new Dictionary<string, object>
            {
                ["Operation"] = operationName,
                ["DurationMs"] = stopwatch.ElapsedMilliseconds
            });
        });
    }

    private class DisposableAction : IDisposable
    {
        private readonly Action _action;
        public DisposableAction(Action action) => _action = action;
        public void Dispose() => _action();
    }
}

Configuration Options

Log Level Filtering

public class FilteredLogSink : ILogSink
{
    private readonly ILogSink _innerSink;
    private readonly LogLevel _minimumLevel;

    public FilteredLogSink(ILogSink innerSink, LogLevel minimumLevel)
    {
        _innerSink = innerSink;
        _minimumLevel = minimumLevel;
    }

    public void Log(LogLevel level, string message, IDictionary<string, object>? data = null, string? scope = null)
    {
        if (level >= _minimumLevel)
        {
            _innerSink.Log(level, message, data, scope);
        }
    }
}

// Usage
var logger = new MiniLogger()
    .AddSink(new FilteredLogSink(new ConsoleLogSink(), LogLevel.Info));

Custom Formatting

public class CustomConsoleSink : ILogSink
{
    public void Log(LogLevel level, string message, IDictionary<string, object>? data = null, string? scope = null)
    {
        var timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
        var formattedMessage = $"[{timestamp}] [{level}] {message}";
        
        if (!string.IsNullOrEmpty(scope))
            formattedMessage = $"[{timestamp}] [{level}] [{scope}] {message}";
            
        if (data != null)
        {
            var dataString = string.Join(", ", data.Select(kv => $"{kv.Key}={kv.Value}"));
            formattedMessage += $" | {dataString}";
        }

        Console.WriteLine(formattedMessage);
    }
}

Best Practices

  1. Use meaningful scopes to organize your logs
  2. Include relevant context in structured data
  3. Choose appropriate log levels for different types of information
  4. Keep log messages concise but informative
  5. Use structured data for machine-readable logs
  6. Consider performance when logging in hot paths

Performance Considerations

  • Minimal overhead: MiniLogger is designed for high performance
  • Thread-safe: All operations are thread-safe
  • Memory efficient: No excessive allocations
  • Async-friendly: Can be used in async contexts

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

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

Support

For support, please open an issue on GitHub or contact us at support@agicoders.com.


Made with ❤️ by Agicoders

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

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 486 7/23/2025