Enigma.Logging.Serilog 1.0.0

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

Enigma.Logging.Serilog

NuGet License: MIT

Enigma.Logging.Serilog builds Serilog-backed Microsoft.Extensions.Logging loggers through a small fluent builder. You add one or more Serilog sinks, then build a disposable handle that owns the underlying Serilog logger and hands you a ready-to-use ILogger.

Built on Serilog 4.x. The handle implements the shared Enigma.Logging.Abstractions contract (ILoggerHandle), so consuming code can stay provider-neutral.

What's new in 1.0 — first release of the Enigma.Logging umbrella: Serilog-backed MEL loggers via a fluent sink builder + DI helper. See the release notes.

Install

dotnet add package Enigma.Logging.Serilog

Quick start

Add sinks, then build a logger. The Build* methods return a LoggerHandledispose it at application shutdown so buffered sinks are flushed and closed (see Dispose).

using Enigma.Logging.Serilog;

using var handle = new LoggerProviderBuilder()
    .AddConsole()
    .AddFile("Logs/app.log")
    .BuildLogger("myLogger");

ILogger logger = handle.Logger;
logger.LogInformation("Hello from Enigma.Logging.Serilog");

Each typed sink applies LoggerProviderBuilder.DefaultOutputTemplate by default — a ready-made output template including timestamp, level, source context, message, and exception details. Pass your own outputTemplate to override it.

Getting loggers from the handle

LoggerHandle gives you three ways to obtain loggers, all routed through the same owned SerilogLoggerProvider:

// The logger built with the name passed to BuildLogger(...)
ILogger logger = handle.Logger;

// A categorized logger by type — category is typeof(T).FullName
ILogger<MyService> typed = handle.CreateLogger<MyService>();

// The underlying ILoggerFactory, e.g. for a category name
ILogger byName = handle.Factory.CreateLogger("Custom.Category");

The logger category name becomes Serilog's SourceContext, which drives logger name scoping. Factory and CreateLogger<T> throw ObjectDisposedException once the handle has been disposed.

Available sink extensions

Each extension takes an optional outputTemplate and the optional minLevel / maxLevel / loggerNamePattern parameters described below:

Method Serilog sink Package
AddConsole themed console Serilog.Sinks.Console
AddFile file (takes a path) Serilog.Sinks.File
AddDebug debug output Serilog.Sinks.Debug

For any other Serilog sink, use the generic AddSink methods directly — the analog of Serilog's own WriteTo:

using Serilog.Core;               // ILogEventSink
using Serilog.Configuration;      // LoggerSinkConfiguration

// Configure any sink through a LoggerSinkConfiguration delegate:
builder.AddSink(writeTo => writeTo.File("Logs/buffered.log", buffered: true),
    minLevel, maxLevel, loggerNamePattern);

// Or register a sink instance you already have:
builder.AddSink(myLogEventSink, minLevel, maxLevel, loggerNamePattern);

Building from configuration

To build from an IConfiguration instead of adding sinks in code, use BuildLoggerFromConfiguration. It configures the logger entirely from the Serilog section via Serilog.Settings.Configuration (sinks added in code are ignored on this path):

using var handle = new LoggerProviderBuilder()
    .BuildLoggerFromConfiguration("myLogger", configuration);

handle.Logger.LogInformation("Configured from IConfiguration");

Log level semantics

minLevel (default Trace) and maxLevel (default Critical) bound the Microsoft.Extensions.Logging.LogLevel range a sink receives — they map to a Serilog LogEventLevel range enforced by the sink's inclusion filter. So minLevel: LogLevel.Warning, maxLevel: LogLevel.Error sends a sink only Warning and Error entries. The mapping is:

LogLevel LogEventLevel
Trace Verbose
Debug Debug
Information Information
Warning Warning
Error Error
Critical Fatal
None (disabled)

Serilog has no "Off" level, so LogLevel.None (or an out-of-range value) used as a bound disables the sink — its filter rejects every event.

Logger name scoping

By default a sink matches every logger name ("*"). Pass loggerNamePattern to scope a sink to specific logger names. The pattern uses NLog-style wildcards (* = any run of characters, ? = one character) and is matched case-insensitively against the event's SourceContext (the logger category name):

using var handle = new LoggerProviderBuilder()
    // Only loggers whose name starts with "MyApp.Payments" write to this sink
    .AddFile("Logs/payments.log", loggerNamePattern: "MyApp.Payments.*")
    .BuildLogger("MyApp.Payments.Processor");

Dispose

LoggerHandle owns the underlying Serilog logger. Buffered sinks (file/async) may hold entries in memory, so you must dispose the handle to avoid losing logs:

  • Dispose() — flushes and closes the Serilog sinks, then tears the logger factory down. Idempotent (safe to call more than once). Prefer a using statement, or dispose it explicitly at application shutdown.

Serilog has no flush-without-close operation, so — unlike a buffering target you might checkpoint mid-run — the handle exposes Dispose only; there is no separate Flush. That is why it implements ILoggerHandle but not IFlushableLoggerHandle (which the NLog adapter's handle does).

using var handle = new LoggerProviderBuilder()
    .AddFile("Logs/app.log")
    .BuildLogger("myLogger");

handle.Logger.LogInformation("buffered entry");
// handle disposed here → flush + close sinks

Single-use builder

A builder is single-use: add every sink first, then call one Build* method exactly once. After a logger is built the builder is sealed — any further AddSink call, or a second Build* call, throws InvalidOperationException. Calling BuildLogger with no sinks added also throws InvalidOperationException. To build another logger, create a new LoggerProviderBuilder.

All public methods throw ArgumentNullException for null arguments (name, configuration, sink, configureSink, path, loggerNamePattern).

Thread safety

The built ILogger and the Serilog logger behind the handle are thread-safe for logging — share the handle's loggers freely across threads. The LoggerProviderBuilder itself is not designed for concurrent use: it is a single-use, add-then-build object, so configure and build it on one thread before sharing the resulting loggers.

Using with Microsoft.Extensions.DependencyInjection

AddSerilogLoggerBuilder(name, configure) builds the logger and wires it into the container in one call:

using Enigma.Logging.Serilog;

services.AddSerilogLoggerBuilder("MyApp", builder => builder
    .AddConsole()
    .AddFile("Logs/app.log"));

What you get:

  • ILogger<T> injection routes through Serilog — the built provider is registered in the Microsoft.Extensions.Logging pipeline, so ordinary constructor injection just works:

    public sealed class OrderService(ILogger<OrderService> logger) { /* … */ }
    
  • The handle is resolvable as ILoggerHandle, for direct access to Logger, Factory, and CreateLogger<T>(). (It is not registered as IFlushableLoggerHandle — see Dispose.)

  • The container owns the handle's lifetime — disposing the service provider (application shutdown) disposes the handle, which flushes and closes the Serilog sinks. No manual using needed.

Prefer the standalone builder when the logger must outlive, or exist without, a DI container.

Supported frameworks

netstandard2.0 · net8.0 · net10.0

The effective Microsoft.Extensions.Logging floor is 9.0.0 on every target framework, resolved transitively from Serilog.Extensions.Logging — the integration package that targets Serilog 4.x. (The NLog adapter keeps a lower MEL baseline; this one is deliberately Serilog-4-aligned.)

License

Licensed under the MIT License.

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 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 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
1.0.0 76 7/31/2026

Enigma.Logging.Serilog 1.0.0 — initial release. Build Serilog-backed Microsoft.Extensions.Logging loggers with a fluent sink builder and a disposable LoggerHandle (console/file/debug sinks, configuration-driven build, level-range + logger-name-pattern gating, IServiceCollection DI helper). Supersedes the retired SerilogLoggerBuilder package (new identity, no upgrade path). See RELEASENOTES.md for the full details.