Invex.Extensions.Logging.FancyConsole 0.4.0

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

Invex Logging Extensions

Useful utilities for Microsoft.Extensions.Logging.

Packages

Package What it does
Invex.Extensions.Logging.FancyConsole A colorful, readable console logger built on Spectre.Console, with multiple layouts, per-level styles, scopes, pretty exceptions, and standard-error routing.
Invex.Extensions.Logging.File A dependency-light file logger with size- and time-based rollover, retention limits, routing by scoped group and log level, and buffered or synchronous writing.

Both packages are standard logging providers: they plug into any ASP.NET Core, Generic Host, or manually created ILoggerFactory, bind options from the Logging configuration section, pick up configuration changes at runtime, and leave level filtering to the standard logging rules. They target net10.0, net9.0, net8.0, and netstandard2.0, and can be used independently or together.

Quick start

Install one or both packages:

dotnet add package Invex.Extensions.Logging.FancyConsole
dotnet add package Invex.Extensions.Logging.File

Register them with your host. A common setup is readable console output while you watch the app, plus rolling files for later inspection:

using Invex.Extensions.Logging.FancyConsole;
using Invex.Extensions.Logging.File;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.ClearProviders();
builder.Logging.AddFancyConsole();
builder.Logging.AddFile();

var app = builder.Build();

They also work with a manually created logger factory:

using Invex.Extensions.Logging.FancyConsole;
using Invex.Extensions.Logging.File;
using Microsoft.Extensions.Logging;

using var loggerFactory = LoggerFactory.Create(logging => logging
    .AddFancyConsole()
    .AddFile());

var logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Hello, world!");

See getting started for defaults and level filtering.

Fancy console logger

AddFancyConsole writes styled, human-friendly output to the console. Pick from four layouts:

Layout Output
Standard (default) A date and category header, then time, level, and message, with a blank line between entries.
SingleLine One line per entry: time, level, category, and message.
Minimal Only the level and message.
Detailed Every available field (category, event, thread, scopes, and message), labeled on separate lines.

Standard:

2026-06-11 +10:00 MyApp.Services.OrderService
09:41:23.123  INF Order 42 submitted

SingleLine:

09:41:23.123 INF MyApp.Services.OrderService: Order 42 submitted

Exceptions can be rendered in Full, Spectre.Console Pretty, one-line Summary, or Hidden form, and entries at or above a chosen level can be routed to standard error. Configure in code:

using Invex.Extensions.Logging.FancyConsole;
using Invex.Extensions.Logging.FancyConsole.Configuration;
using Microsoft.Extensions.Logging;

builder.Logging.AddFancyConsole(options =>
{
    options.Layout = FancyConsoleLayout.SingleLine;
    options.IncludeScopes = true;
    options.UseShortCategoryName = true;
    options.LevelStyles[LogLevel.Error] = "bold red";
    options.ExceptionFormat = FancyConsoleExceptionFormat.Pretty;
    options.LogToStandardErrorThreshold = LogLevel.Error;
});

Or under Logging:FancyConsole (provider alias FancyConsole). Values configured by the delegate are applied after values bound from configuration:

{
  "Logging": {
    "FancyConsole": {
      "Layout": "SingleLine",
      "IncludeScopes": true,
      "LevelStyles": {
        "Error": "bold red"
      },
      "ExceptionFormat": "Pretty",
      "LogToStandardErrorThreshold": "Error"
    }
  }
}
Option Default Description
Layout Standard Standard, SingleLine, Minimal, or Detailed.
TimestampFormat null .NET date/time format string; null or empty uses the layout default.
UseUtcTimestamp false Show timestamps in UTC instead of local time.
IncludeScopes false Append active scopes after the category (Standard and SingleLine; Detailed always shows them).
UseShortCategoryName false Shorten categories to the text after their last ..
UseColors true Apply styles when the console supports them; NO_COLOR is honored.
LevelStyles empty Per-level Spectre.Console styles, such as "bold red" or "black on yellow".
ExceptionFormat Full Full, Pretty, Summary, or Hidden.
ExceptionTextStyle "red1" Style for Full and Summary exception text.
LogToStandardErrorThreshold None Entries at or above this level go to standard error; None writes everything to standard output.

Each entry is written as a single unit, so concurrent entries do not interleave, and rendering failures are never thrown into the application. See the fancy console guide for every layout, style, and exception option.

File logger

AddFile writes plain, parseable log lines to rolling files:

[2026-06-11 09:41:23.123 +10:00 INF MyApp.Services.OrderService] Order 42 submitted

By default it writes to a Logs directory relative to the current working directory. The active file is named after AppDomain.CurrentDomain.FriendlyName, rolls over daily or at 100 MiB (whichever happens first), and retains up to 10 GiB of rolled-over files.

Buffered writing is the default. Dispose the host or ILoggerFactory during graceful shutdown so queued entries are flushed, even when disposal immediately follows the last log call; no delay is needed. Entries still in memory can be lost if the process crashes or is killed.

Configure in code:

using Invex.Extensions.Logging.File;
using Invex.Extensions.Logging.File.Configuration;
using Microsoft.Extensions.Logging;

builder.Logging.AddFile(options =>
{
    options.LogDirectory = "Logs";
    options.LogName = "my-app";
    options.FileSizeLimitBytes = 50L * 1024 * 1024;
    options.RolloverInterval = FileRolloverInterval.Hour;
    options.MaxTotalSizeBytes = 1L * 1024 * 1024 * 1024;
    options.PerGroupLogName["Orders"] = "orders";
    options.PerLevelLogName[LogLevel.Error] = "errors";
});

Or under Logging:File (provider alias File). Values configured by the delegate are applied after values bound from configuration:

{
  "Logging": {
    "File": {
      "LogDirectory": "Logs",
      "LogName": "my-app",
      "FileSizeLimitBytes": 104857600,
      "RolloverInterval": "Day",
      "MaxTotalSizeBytes": 10737418240,
      "PerGroupLogName": {
        "Orders": "orders"
      },
      "PerLevelLogName": {
        "Error": "errors",
        "Critical": "errors"
      }
    }
  }
}
Option Default Description
LogDirectory "Logs" Absolute directory, or a directory relative to the current working directory. Created when needed.
LogName null Active base name without .log; null uses the application domain friendly name.
PerGroupLogName empty Suffixes for selected scoped groups, appended to the base name before any level suffix. A mapped null or empty string adds nothing.
PerLevelLogName empty Suffixes for selected levels, appended after the base name and any group suffix. A mapped null or empty string adds nothing.
FileSizeLimitBytes 100 MiB Rolls over before a write that would make the active file reach this size.
RolloverInterval Day Elapsed interval from file creation: Infinite, Year (365 days), Month (30 days), Day, Hour, or Minute.
MaxTotalSizeBytes 10 GiB Maximum total size of rolled-over files for each base name. The oldest rolled-over file is removed when the limit is reached.

PerLevelLogName values now append to LogName as suffixes instead of replacing it. Update existing full-name mappings to suffixes; for example, use "errors" with LogName = "my-app" to write my-app_errors.log. See migration guidance.

Routing by group

Use BeginGroupScope to set a group for log calls within a scope:

using Invex.Extensions.Logging.File;

using (logger.BeginGroupScope("Orders"))
{
    logger.LogInformation("Order submitted"); // my-app_orders.log
    logger.LogError("Payment failed");       // my-app_orders_errors.log
}

File names start with LogName, followed by the mapped group suffix and then the mapped level suffix, each separated by an underscore. Missing mappings and null or empty mapped suffixes add no separator or text. Nested groups override outer groups until disposed, and scopes flow across await and logger categories. Dictionary and formatted scopes such as logger.BeginScope("{Group}", "Orders") also work. Scope values affect routing without appearing in the file's log lines. See group routing for the complete rules.

Rollover, retention, and write modes

When rollover occurs, the active {name}.log is renamed to {name}_{yyMMdd-HHmmss}.log; collisions receive _1, _2, and later suffixes. Time rollover uses elapsed durations, not calendar boundaries, and checks occur only when an entry is written. Retention is evaluated independently for each base name and never deletes the active file. Case-only path aliases follow the destination filesystem's behavior for buffered routing, archive naming, and retention. See file rollover and retention.

Buffered mode queues entries for a dedicated background thread that writes batches of up to 10 entries. Use direct mode when an entry must be written before the log call returns:

builder.Logging.AddFile(buffered: false);

Both modes retry failed writes up to five times, report failures to console/debug output, and drop entries that still cannot be written. See buffered versus direct writing and the log format guide.

Filtering

Neither provider filters levels itself. Use the standard log filtering rules, scoped to a provider alias when needed:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    },
    "FancyConsole": {
      "LogLevel": {
        "Microsoft": "Warning"
      }
    },
    "File": {
      "LogLevel": {
        "Default": "Warning",
        "MyApp.Services": "Information"
      }
    }
  }
}

Documentation

License

Licensed under the terms of LICENSE.txt.

Product 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 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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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
0.4.0 41 10/1/2026
0.4.0-rc.15 36 10/1/2026
0.4.0-beta.feature-groups-a... 36 10/1/2026
0.4.0-beta.feature-groups-a... 37 10/1/2026
0.4.0-beta.feature-groups-a... 38 10/1/2026