Fancy Console Logger
Invex.Extensions.Logging.FancyConsole is a colorful console logger provider built on
Spectre.Console. It offers several layouts, per-level styles, optional
scopes, styled or "pretty" exceptions, and standard-error routing, all configurable through the standard
options pipeline with runtime reload.
The library targets net10.0, net9.0, net8.0, and netstandard2.0.
Registration
using Invex.Extensions.Logging.FancyConsole;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddFancyConsole();
AddFancyConsole() binds options from Logging:FancyConsole. The delegate overload applies code
configuration on top of bound configuration:
using Invex.Extensions.Logging.FancyConsole;
using Invex.Extensions.Logging.FancyConsole.Configuration;
builder.Logging.AddFancyConsole(options =>
{
options.Layout = FancyConsoleLayout.SingleLine;
options.IncludeScopes = true;
options.UseShortCategoryName = true;
options.ExceptionFormat = FancyConsoleExceptionFormat.Pretty;
options.LogToStandardErrorThreshold = LogLevel.Error;
});
Calling AddFancyConsole more than once registers the provider only once.
Layouts
Choose a layout with Layout. Level codes are TRC, DBG, INF, WRN, ERR, and CRT. In Standard,
Minimal, and Detailed, multi-line messages are indented to the message column; SingleLine replaces line breaks with spaces.
Standard (default)
A header line with the date, UTC offset, and category, followed by the time, level, and message, and a blank line between entries:
2026-06-11 +10:00 MyApp.Services.OrderService
09:41:23.123 INF Order 42 submitted
for customer 7
SingleLine
One line per entry, suited to dense output and grep:
09:41:23.123 INF MyApp.Services.OrderService: Order 42 submitted
Minimal
Only the level and message:
INF Order 42 submitted
Detailed
Every available field, labeled, with a blank line between entries. Event is shown only for a non-default
event ID, and Scopes only when scopes are active. Detailed always includes scopes, regardless of
IncludeScopes.
2026-06-11 09:41:23.123 +10:00 Information
Category: MyApp.Services.OrderService
Event: 1001 (OrderSubmitted)
Thread: 16
Scopes: Request 0HN4 => Order 42
Message: Order 42 submitted
Options
| Option | Default | Description |
|---|---|---|
Layout |
Standard |
Standard, SingleLine, Minimal, or Detailed. |
TimestampFormat |
null |
.NET date/time format string (invariant culture). null/empty uses the layout default: HH:mm:ss.fff (Standard, SingleLine) or yyyy-MM-dd HH:mm:ss.fff zzz (Detailed). An invalid format falls back to the layout default. Ignored by Minimal; the Standard header always shows the date and offset. |
UseUtcTimestamp |
false |
Show timestamps in UTC instead of local time. |
IncludeScopes |
false |
Append active scopes after the category as => scope1 => scope2 (Standard and SingleLine). |
UseShortCategoryName |
false |
Shorten categories to the text after their last .. |
UseColors |
true |
Apply level and exception styles. When false, all output is unstyled. |
LevelStyles |
empty | Per-level Spectre.Console style strings, e.g. "bold red", "#ff8800", "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. |
The same configuration in appsettings.json:
{
"Logging": {
"FancyConsole": {
"Layout": "SingleLine",
"TimestampFormat": "HH:mm:ss",
"UseUtcTimestamp": false,
"IncludeScopes": true,
"UseShortCategoryName": true,
"UseColors": true,
"LevelStyles": {
"Information": "white",
"Error": "bold red"
},
"ExceptionFormat": "Pretty",
"ExceptionTextStyle": "red1",
"LogToStandardErrorThreshold": "Error"
}
}
}
Configuration changes are picked up at runtime and apply to subsequent entries.
Level styles
Missing levels use the built-in defaults: grey (Trace), seagreen3 (Debug), skyblue1 (Information),
gold1 (Warning), darkorange (Error), and fuchsia (Critical). A mapped null or whitespace value
disables styling for that level, and a value that is not a valid style falls back to the default.
Colors are emitted only when the console supports them. Spectre.Console detects terminal capabilities and
honors the NO_COLOR environment variable; set UseColors to false to disable styling unconditionally.
Scopes
Message-template scopes (logger.BeginScope("Order {OrderId}", 42)) are shown as their formatted text,
other key/value scopes as comma-separated Key=Value pairs, and any other object via ToString(). Null
and empty scopes are skipped. Minimal never shows scopes.
09:41:23.123 INF OrderService => Request 0HN4 => Order 42: Order 42 submitted
Exceptions
| Format | Output |
|---|---|
Full |
Exception.ToString(), indented to the message column and styled with ExceptionTextStyle. |
Pretty |
Spectre.Console's formatted exception with highlighted types, methods, and paths. |
Summary |
Type and message of the exception and each inner exception, e.g. InvalidOperationException: Boom ---> ArgumentException: Inner. |
Hidden |
Nothing; only the log message is written. |
In Standard layout exceptions follow the message on their own lines, and in Detailed they appear under an
Exception: label. In SingleLine and Minimal, Summary is appended to the line as | {summary} so each
entry stays on one line; other formats are written on the following lines.
Pretty falls back to Full when Spectre.Console cannot render the exception, for example an exception
that was never thrown on .NET Framework.
Output, filtering, and wrapping
The provider does no level filtering of its own. Use standard logging rules, scoped to the FancyConsole
provider alias when needed:
{
"Logging": {
"FancyConsole": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
}
}
}
Each entry is rendered and written as a single unit, so concurrent entries are not interleaved. Empty
messages and LogLevel.None entries are skipped. Rendering failures are reported to debug output and
standard error and never thrown into the application.
Spectre.Console wraps long lines at the console width, which is 80 columns when output is redirected. Use the Microsoft console logger or the file logger when you need unwrapped, machine-parseable output.