![]() |
VOOZH | about |
dotnet add package CSharpEssentials.LoggerHelper --version 5.1.0
NuGet\Install-Package CSharpEssentials.LoggerHelper -Version 5.1.0
<PackageReference Include="CSharpEssentials.LoggerHelper" Version="5.1.0" />
<PackageVersion Include="CSharpEssentials.LoggerHelper" Version="5.1.0" />Directory.Packages.props
<PackageReference Include="CSharpEssentials.LoggerHelper" />Project file
paket add CSharpEssentials.LoggerHelper --version 5.1.0
#r "nuget: CSharpEssentials.LoggerHelper, 5.1.0"
#:package CSharpEssentials.LoggerHelper@5.1.0
#addin nuget:?package=CSharpEssentials.LoggerHelper&version=5.1.0Install as a Cake Addin
#tool nuget:?package=CSharpEssentials.LoggerHelper&version=5.1.0Install as a Cake Tool
Route Serilog sinks by log level โ zero boilerplate, native
ILogger<T>support.
Install the NuGet, add 5 lines of JSON, and every ILogger<T> in your app automatically routes logs to Console, File, Email, Telegram, PostgreSQL, SQL Server, Elasticsearch, and Seq โ each sink receiving only the levels you want.
dotnet add package CSharpEssentials.LoggerHelper
dotnet add package CSharpEssentials.LoggerHelper.Sink.Console
dotnet add package CSharpEssentials.LoggerHelper.Sink.File
dotnet add package CSharpEssentials.LoggerHelper.Sink.Email # add only what you need
| Serilog alone | NLog | LoggerHelper v5 | |
|---|---|---|---|
| Per-level sink routing | Manual per sink | Via targets | JSON / fluent โ built-in |
ILogger<T> compatible |
Via bridge pkg | Native | Native โ zero code change |
| Install only needed sinks | No | No | Yes โ modular NuGet |
| Named params preserved | Yes | Yes | Yes โ through the bridge |
BeginScope structured |
Yes | Yes | Yes โ propagates to Serilog |
| Scope nesting | Yes | Yes | Yes โ accumulates properties |
| OpenTelemetry trace ID | Manual | Manual | Built-in, auto-correlated |
| Internal error diagnostics | No | No | Yes โ injectable ILogErrorStore |
| Fluent OR JSON OR both | No | No | All three, mergeable |
Program.cs
builder.Services.AddLoggerHelper(builder.Configuration);
app.UseLoggerHelper();
appsettings.LoggerHelper.json
{
"LoggerHelper": {
"ApplicationName": "MyApp",
"Routes": [
{ "Sink": "Console", "Levels": ["Information", "Warning"] },
{ "Sink": "File", "Levels": ["Information", "Warning", "Error", "Fatal"] },
{ "Sink": "Email", "Levels": ["Error", "Fatal"] }
],
"Sinks": {
"File": { "Path": "C:\\Logs\\MyApp", "RollingInterval": "Day" },
"Email": { "To": "ops@example.com", "Host": "smtp.example.com", "Port": 587 }
},
"General": { "EnableRequestResponseLogging": true }
}
}
That's it. Every ILogger<T> in your app now routes through LoggerHelper.
builder.Services.AddLoggerHelper(b => b
.WithApplicationName("MyApp")
.AddRoute("Console", LogEventLevel.Information, LogEventLevel.Warning)
.AddRoute("File", LogEventLevel.Information, LogEventLevel.Warning, LogEventLevel.Error, LogEventLevel.Fatal)
.AddRoute("Email", LogEventLevel.Error, LogEventLevel.Fatal)
.ConfigureFile(f => { f.Path = "C:\\Logs\\MyApp"; f.RollingInterval = "Day"; })
.EnableRequestResponseLogging()
);
// JSON defines shared config across environments.
// Fluent adds Development-only extras without touching JSON.
builder.Services.AddLoggerHelper(builder.Configuration, b => b
.AddRoute("Console", LogEventLevel.Debug) // extra sink only in code
);
ILoggingBuilder (respects Logging:LogLevel filters)builder.Logging.ClearProviders();
builder.Logging.AddLoggerHelper(builder.Configuration);
If your app already uses ILogger<T>, you change nothing. LoggerHelper plugs in as a standard ILoggerProvider:
// Your existing service โ not a single line changes
public class OrderService(ILogger<OrderService> logger) {
public void Process(int orderId) {
logger.LogInformation("Processing order {OrderId}", orderId); // โ Console + File
logger.LogError("Payment failed for {OrderId}", orderId); // โ File + Email
}
}
Named parameters like {OrderId} are preserved as structured Serilog properties โ not flattened into strings.
Add business properties once. Every log in that block carries them automatically, including logs inside methods you call:
using (_logger.BeginScope(new Dictionary<string, object?> {
["OrderId"] = orderId,
["UserId"] = userId
}))
{
_logger.LogInformation("Validation started"); // OrderId + UserId are here
await ValidateStock(); // logs inside also carry them
_logger.LogInformation("Order confirmed"); // OrderId + UserId are here
}
// Outside the using: properties removed automatically
Scope nesting โ properties accumulate layer by layer:
using (_logger.BeginScope(new Dictionary<string, object?> { ["OrderId"] = 123 }))
{
using (_logger.BeginScope(new Dictionary<string, object?> { ["Provider"] = "Stripe" }))
{
_logger.LogInformation("Charging card");
// OrderId=123, Provider="Stripe"
}
_logger.LogInformation("Order complete");
// OrderId=123 (Provider removed)
}
Without any extra code, every log event carries:
| Property | Value |
|---|---|
ApplicationName |
Set via config or WithApplicationName() |
MachineName |
Environment.MachineName |
SourceContext |
Class name from ILogger<T> |
RenderedMessage |
Pre-rendered message string |
TraceId / SpanId |
From System.Diagnostics.Activity (OpenTelemetry) |
RequestPath / RequestId |
Added by ASP.NET Core middleware |
Each sink is a separate NuGet โ install only what you need:
| Package | Target |
|---|---|
CSharpEssentials.LoggerHelper.Sink.Console |
Colored console output |
CSharpEssentials.LoggerHelper.Sink.File |
JSON rolling files |
CSharpEssentials.LoggerHelper.Sink.Email |
SMTP alerts with throttling |
CSharpEssentials.LoggerHelper.Sink.Telegram |
Bot notifications with throttling |
CSharpEssentials.LoggerHelper.Sink.Postgresql |
PostgreSQL structured logs |
CSharpEssentials.LoggerHelper.Sink.MSSqlServer |
SQL Server structured logs |
CSharpEssentials.LoggerHelper.Sink.Elasticsearch |
Elasticsearch + Kibana |
CSharpEssentials.LoggerHelper.Sink.Seq |
Seq centralized log server |
CSharpEssentials.LoggerHelper.Sink.HangfireConsole |
Hangfire Dashboard console logs |
Sinks self-register via a plugin mechanism โ the core package has zero dependency on them.
Redact PII and secrets from every sink at once, declaratively:
"SensitiveDataMasking": {
"Enabled": true,
"Presets": [ "Email", "CreditCard", "JwtToken", "BearerToken", "ConnectionStringSecret" ],
"SensitiveProperties": [ "Password", "ApiKey" ],
"Rules": [ { "Name": "OrderId", "Pattern": "ORD-\\d+" } ]
}
logger.LogInformation("Login for {Email} with {Password}", "alice@example.com", "Sup3rSecret!");
// โ Login for ***MASKED*** with ***MASKED***
Disabled by default โ zero overhead unless enabled. Or via fluent API: .EnableSensitiveDataMasking(o => o.Presets.Add("Email")).
"Routes": [
{ "Sink": "Console", "Levels": ["Debug", "Information", "Warning"] },
{ "Sink": "File", "Levels": ["Information", "Warning", "Error", "Fatal"] },
{ "Sink": "Telegram", "Levels": ["Error", "Fatal"] },
{ "Sink": "Email", "Levels": ["Fatal"] },
{ "Sink": "Elasticsearch", "Levels": ["Information", "Warning", "Error", "Fatal"] }
]
Legacy (Serilog:SerilogConfiguration) |
v5 (LoggerHelper) |
|---|---|
SerilogCondition |
Routes |
Level |
Levels |
SerilogOption |
Sinks |
See for feature parity details.
See for LoggerHelper v5 vs Serilog vs NLog comparisons.
LoggerHelper automatically picks the right file based on the current environment:
| Environment | File loaded |
|---|---|
Development |
appsettings.LoggerHelper.debug.json |
| Everything else | appsettings.LoggerHelper.json |
If a sink fails to configure (wrong connection string, unreachable SMTP server), LoggerHelper captures the error silently and exposes it โ your app keeps running:
app.MapGet("/health/logging", (ILogErrorStore errors) =>
errors.Count == 0
? Results.Ok("All sinks healthy")
: Results.Problem(string.Join("\n", errors.GetAll().Select(e => $"{e.SinkName}: {e.ErrorMessage}")))
);
Enable HTTP request/response logging with a single setting:
"General": { "EnableRequestResponseLogging": true }
Then activate in the pipeline:
app.UseLoggerHelper();
CSharpEssentials.LoggerHelper.Sink.MyTargetISinkPlugin:internal sealed class MyTargetSinkPlugin : ISinkPlugin {
public bool CanHandle(string sinkName) =>
sinkName.Equals("MyTarget", StringComparison.OrdinalIgnoreCase);
public void Configure(LoggerConfiguration loggerConfig, SinkRouting routing, LoggerHelperOptions options) {
var opts = options.GetSinkConfig<MyTargetOptions>("MyTarget")
?? options.BindSinkSection<MyTargetOptions>("MyTarget")
?? new MyTargetOptions();
loggerConfig.WriteTo.Conditional(
evt => routing.Matches(evt.Level),
wt => wt.MySink(opts.ConnectionString)
);
}
}
public static class PluginInitializer {
[ModuleInitializer]
public static void Init() => SinkPluginRegistry.Register(new MyTargetSinkPlugin());
}
CSharpEssentials.LoggerHelper as a NuGet โ not a project reference.LoggerHelper v5 is built on Serilog, adding a thin MEL-compatible routing layer. Overhead vs raw Serilog is kept minimal โ no reflection at log time, level checks short-circuit before routing evaluation.
Full benchmark results (auto-updated on each release) โ
Benchmarks run with BenchmarkDotNet on .NET 9, comparing LoggerHelper v5 against Serilog (baseline) and NLog using no-op sinks to measure framework overhead independently of I/O.
| Package | Targets |
|---|---|
| LoggerHelper core | net8.0 ยท net9.0 ยท net10.0 |
| Sink plugins | net8.0 ยท net9.0 ยท net10.0 |
Planned for upcoming releases โ contributions welcome.
dotnet new template โ dotnet new loggerhelper-api scaffolds a pre-configured project with zero frictionMIT โ ยฉ Alessandro Chiodo
Documentation ยท GitHub ยท NuGet
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 5 NuGet packages that depend on CSharpEssentials.LoggerHelper:
| Package | Downloads |
|---|---|
|
CSharpEssentials.HttpHelper
Make every HTTP call resilient in one line. Built-in retry, rate limiting, and automatic logging โ so your app keeps working when APIs don't. Built on IHttpClientFactory โ register once with AddHttpClients(), inject anywhere. |
|
|
CSharpEssentials.LoggerHelper.Sink.Console
See your logs in color, instantly. Add Console to your LoggerHelper routes and get beautiful, level-filtered colored output โ zero configuration beyond a single JSON entry. Auto-registered via [ModuleInitializer]: no code changes, just add the NuGet. Part of the CSharpEssentials.LoggerHelper ecosystem with 9 pluggable sinks and now a built-in MCP server for AI assistant integration. |
|
|
CSharpEssentials.LoggerHelper.Sink.MSSqlServer
Query your logs with SQL. Auto-creates the table, batches the writes, and lets you JOIN logs with your business data โ because sometimes grep isn't enough. AutoCreateSqlTable means zero migrations to get started. |
|
|
CSharpEssentials.LoggerHelper.Sink.Postgresql
Logs meet PostgreSQL. JSONB fields you can query, auto-created tables, and the full power of SQL โ perfect for teams already running Postgres. NeedAutoCreateTable means zero migrations to get started. |
|
|
CSharpEssentials.LoggerHelper.Sink.Elasticsearch
Search millions of logs in milliseconds. Ship structured logs straight to Elasticsearch and build Kibana dashboards that actually tell you what's happening. Works with self-hosted Elasticsearch, OpenSearch, and Elastic Cloud โ point IndexFormat at your ILM policy and go. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.1.0 | 207 | 6/16/2026 |
| 5.0.8 | 351 | 6/13/2026 |
| 5.0.7 | 332 | 6/11/2026 |
| 5.0.6 | 315 | 6/10/2026 |
| 5.0.5 | 344 | 6/6/2026 |
| 5.0.4 | 333 | 6/5/2026 |
| 5.0.3 | 332 | 6/2/2026 |
| 5.0.2 | 402 | 6/1/2026 |
| 5.0.1 | 388 | 5/31/2026 |
| 5.0.0 | 359 | 5/31/2026 |
| 4.1.0 | 173 | 3/27/2026 |
| 4.0.13 | 176 | 2/28/2026 |
| 4.0.12 | 818 | 11/19/2025 |
| 4.0.11-beta | 176 | 11/15/2025 |
| 4.0.10.1 | 247 | 10/12/2025 |
| 4.0.10 | 570 | 10/12/2025 |
| 4.0.9.1 | 180 | 10/10/2025 |
| 4.0.9 | 148 | 10/10/2025 |
| 4.0.8 | 169 | 10/10/2025 |
| 4.0.7 | 216 | 10/8/2025 |