CSharpEssentials.LoggerHelper 5.3.2

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

<a name="top"></a>

CSharpEssentials — LoggerHelper

A thin, opinionated layer over Serilog: exact level sets per sink, masking on every sink and queryable sink health — from one JSON file.

Already happy with restrictedToMinimumLevel in Serilog.Settings.Configuration? Then plain Serilog is enough. See when LoggerHelper helps.

NuGet Version NuGet Downloads .NET Versions License

Build and Test (src v5) CodeQL Dependabot Updates

GitHub stars GitHub issues

⭐ If you find this project useful, please consider giving it a star on GitHub!
💡 Explore the source code, check open issues, or contribute.


LoggerHelper is a modular logging infrastructure for .NET. Install the core + only the sink packages you need, drop in a JSON config, and your entire app's ILogger<T> routes to Console, File, Email, Telegram, SQL Server, PostgreSQL, MySQL/MariaDB, Elasticsearch, Seq, and Hangfire Console — each receiving only the log levels you configure.

Zero code changes required if you already use ILogger<T>. LoggerHelper registers as a standard ILoggerProvider.

dotnet add package CSharpEssentials.LoggerHelper
dotnet add package CSharpEssentials.LoggerHelper.Sink.Console
dotnet add package CSharpEssentials.LoggerHelper.Sink.File

Table of Contents


🎮 Try it live before you install! See the exact "Config vs Result" output for every sink directly in your browser on the Interactive Playground at loggerhelper.it.

<a name="demo-playground"></a>

🧪 See It Live: One Event, Every Sink, Zero Secrets Leaked

docker compose up -d + dotnet run, then one click. The Demo Playground sends a single log event to Console, File, Seq, Elasticsearch, SQL Server, PostgreSQL and Telegram at the same time, built on the fluent API from the options you pick on the page. And it puts HttpHelper to work against a real API.

  • 🎯 Per-sink level routing: set PostgreSQL to Error and watch it filter a Warning while the others receive it.
  • 🎭 Real masking: Sup3rSecret!, emails and card numbers become ***MASKED*** in every sink, rendered message included.
  • 💥 Resilient by design: stop a container and send again; your app keeps logging and the failure is reported, not thrown.
  • 🔁 HttpHelper, live: real calls to httpbin.org with Polly retries, timeouts, rate limiting and Bearer auth; every attempt lands in your sinks, token masked.
  • 🔍 Nothing hidden: the page shows the event exactly as the sinks receive it and the C# code that produced it.

LoggerHelper Playground

👉 Open the step-by-step guide: DEMO.md: Docker setup, a tour of the page, HttpHelper scenarios and seven experiments to try.

<a name="quick-start"></a>

🚀 Quick Start

1. Install packages

dotnet add package CSharpEssentials.LoggerHelper
dotnet add package CSharpEssentials.LoggerHelper.Sink.Console
dotnet add package CSharpEssentials.LoggerHelper.Sink.File

2. Wire up in Program.cs

builder.Services.AddLoggerHelper(builder.Configuration);
app.UseLoggerHelper();

3. Create appsettings.LoggerHelper.json in your project root

{
  "LoggerHelper": {
    "ApplicationName": "MyApp",
    "Routes": [
      { "Sink": "Console", "Levels": ["Information", "Warning"] },
      { "Sink": "File", "Levels": ["Information", "Warning", "Error", "Fatal"] }
    ],
    "Sinks": {
      "File": {
        "Path": "Logs",
        "RollingInterval": "Day",
        "RetainedFileCountLimit": 7
      }
    },
    "General": { "EnableRequestResponseLogging": true }
  }
}

🔌 Adding more sinks is effortless: Want to route logs to SQL Server, PostgreSQL, MySQL/MariaDB, Email, Seq, or Telegram? Just install the specific sink NuGet package (e.g. CSharpEssentials.LoggerHelper.Sink.Email) and add its configuration block and route to the JSON. No C# code changes required.

Done. Every ILogger<T> in your app now routes through LoggerHelper.

💡 PRO TIP: Environment-Specific Configs
LoggerHelper automatically detects your environment! Create an appsettings.LoggerHelper.debug.json file alongside the main config, and LoggerHelper will automatically load it when running in Development mode. This is perfect for enabling verbose Console logging locally while keeping appsettings.LoggerHelper.json strictly for Production settings (like Databases and Email).

⚠️ File in the working directory wins. If an appsettings.LoggerHelper*.json exists in the current directory, AddLoggerHelper(...) reads it and it fully replaces the IConfiguration you passed (no merge). With AddLoggerHelper(config, fluent), routes may come from the fluent API alone: the "no routes" check runs after the fluent merge.

⚠️ Misconfigured sinks are reported, not hidden. A sink with missing required settings (e.g. empty ConnectionString, Host, BotToken, ServerUrl, NodeUris) fails to configure; the other sinks keep working and the Dashboard / MCP loggerhelper_get_sinks show it as FAILED.


Option B — Fluent API

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 = "Logs"; f.RollingInterval = "Day"; })
    .ConfigureEmail(e => { e.To = "ops@example.com"; e.Host = "smtp.example.com"; })
    .EnableRequestResponseLogging()
);

Option C — JSON + Fluent merge

// 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)
);

Fluent General flags and SensitiveDataMasking are merged over the JSON: EnableSelfLogging, EnableRequestResponseLogging and EnableRenderedMessage are OR-ed; EnableOpenTelemetry is AND-ed (fluent DisableOpenTelemetry can only turn it off); masking presets/properties are unioned and rules appended, de-duplicated by Pattern (JSON wins).

↑ Back to Top


<a name="run-the-demo-in-60-seconds"></a>

⚡ Run the Demo in 60 Seconds

Clone the repo and start the interactive demo app. The demo comes pre-configured with Console, File, MSSqlServer, and PostgreSQL sinks.

git clone https://github.com/alexbypa/CSharp.Essentials.git
cd CSharp.Essentials/src/CSharpEssentials.LoggerHelper.Demo
dotnet run

Open the URL shown in your terminal (usually http://localhost:5123): the root opens the Playground, and /swagger or /scalar list all demo scenarios. Each endpoint produces structured logs visible immediately in the terminal and in the Logs/ folder.

Try GET /api/httphelper/retry, then open /loggerhelper to watch HttpHelper retries live.

🧪 Playground with every sink: start SQL Server, PostgreSQL, Seq and Elasticsearch with docker compose up -d in src/CSharpEssentials.LoggerHelper.Demo/docker, then open the Demo root (/playground.html). Step-by-step guide: DEMO.md.

💡 No database required to run it: Even if you don't have SQL Server or PostgreSQL running locally, LoggerHelper gracefully ignores the connection errors. Your app won't crash, and logs will still appear perfectly in the Console and File sinks!

↑ Back to Top


<a name="why-choose-loggerhelper"></a>

🎯 Why choose LoggerHelper?

  • 🔌 Native ILogger<T>: Zero vendor lock-in. Uses standard Microsoft abstractions.
  • 🧩 Zero Unnecessary Dependencies: Highly modular. Install the core package and only the specific sinks you need.
  • 🛠️ JSON-First Configuration: Send an exact set of levels to each sink (e.g. Information + Warning but not Error) without sub-loggers or filter expressions.
  • 🛡️ PII Data Masking: Automatically redact passwords, JWTs, and sensitive fields across all sinks globally.
  • 🤖 AI-Ready: Includes a native MCP Server to let AI assistants query log health and configuration out-of-the-box.

↑ Back to Top


<a name="packages"></a>

📦 Packages

Package Description Version Downloads
CSharpEssentials.LoggerHelper Core routing engine, ILogger<T> bridge, JSON/fluent config NuGet NuGet
CSharpEssentials.HttpHelper HttpClient + Polly resilience, rate limiting, opt-in per-attempt structured logging and correlation ID (HttpHelperLogging) — guide → NuGet NuGet
...Sink.Console Colored console output, per-level themes — guide → NuGet NuGet
...Sink.MSSqlServer SQL Server structured logs, auto table creation — guide → NuGet NuGet
...Sink.Postgresql PostgreSQL, JSONB columns, custom schema — guide → NuGet NuGet
...Sink.MySql MySQL & MariaDB, real typed columns + native JSON, auto table creation — guide → NuGet NuGet
...Sink.Elasticsearch Elasticsearch/OpenSearch indexing, Kibana-ready — guide → NuGet NuGet
...Sink.File Rolling JSON files, per-property subdirectories, configurable retention — guide → NuGet NuGet
...Sink.Telegram Bot notifications, MarkdownV2, throttling — guide → NuGet NuGet
...Sink.Email SMTP alerts, HTML templates, throttling — guide → NuGet NuGet
...Sink.Dashboard Dashboard LoggerHelper — guide → NuGet NuGet
...Sink.HangfireConsole Structured logs in Hangfire Dashboard with color output — guide → NuGet NuGet
...Sink.Seq Seq centralized log server — guide → NuGet NuGet
CSharpEssentials.LoggerHelper.MCP MCP server: AI assistants can query sink health, errors & config — guide → NuGet NuGet

↑ Back to Top


<a name="feature-highlights"></a>

✨ Feature Highlights

Per-Level Sink Routing — Declarative

Send different log levels to different destinations without writing conditional predicates:

"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"] }
]

Native ILogger<T> — Zero Code Changes

If your app already uses ILogger<T>, you change nothing. LoggerHelper registers as a standard ILoggerProvider:

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.

BeginScope — Context That Travels

using (_logger.BeginScope(new Dictionary<string, object?> {
    ["OrderId"] = orderId,
    ["UserId"]  = userId
}))
{
    _logger.LogInformation("Validation started");   // OrderId + UserId attached
    await ValidateStock();                           // inner logs also carry them
    _logger.LogInformation("Order confirmed");       // OrderId + UserId attached
}

<a name="enrichment"></a>

Enrichment — Extra Properties on Every Log

Enrichment adds properties to a log event besides its message. They become searchable fields in Seq and Elasticsearch, and dedicated columns in database sinks when you map them (see From property to column).

Automatic, nothing to write:

Property Source
ApplicationName Config / WithApplicationName()
MachineName Environment.MachineName
SourceContext Class name from ILogger<T>
TraceId / SpanId System.Diagnostics.Activity (OpenTelemetry)

Per operation: BeginTrace adds Action and IdTransaction (plus SpanName inside an Activity) to every log in the block:

using (logger.BeginTrace("Checkout", idTransaction)) {
    logger.LogInformation("Payment authorized");     // + Action, IdTransaction
    logger.LogInformation("Order {OrderId} shipped", orderId);
}

// One-off log, no scope:
logger.Trace("Checkout", idTransaction, "Order {OrderId} shipped", orderId);

Any property you like: BeginScope, as shown above (OrderId, UserId, TenantId...).

On every event, with your own logic: WithEnrichers plugs standard Serilog enrichers into the pipeline:

builder.Services.AddLoggerHelper(builder.Configuration, b => b
    .WithEnrichers(c => c
        .Enrich.WithProperty("Environment", builder.Environment.EnvironmentName)
        .Enrich.With(new TenantEnricher())));   // your Serilog ILogEventEnricher

Enrichers added with WithEnrichers run after sensitive data masking: don't put secrets in them.

<a name="from-property-to-column"></a> From property to column

Sink Where the properties go
PostgreSQL Default columns already include ApplicationName, MachineName, Action, IdTransaction; add more with Columns
SQL Server In the Properties column; promote any of them to its own column with AdditionalColumns
Seq, Elasticsearch Every property is a searchable field, nothing to configure

Internal Diagnostics

If a sink fails (wrong connection string, unreachable SMTP), your app keeps running. Errors are captured (not thrown) and inspectable at runtime:

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}")))
);

Request/Response Logging Middleware

"General": { "EnableRequestResponseLogging": true }
app.UseLoggerHelper();

One setting, one line — full HTTP request/response logging with correlation IDs and timing.

Dynamic File Routing (Multi-Tenant)

Route logs to subdirectories based on any log property:

"Sinks": {
  "File": { "Path": "Logs", "RollingInterval": "Day", "FileNameProperty": "TenantId" }
}

Logs with TenantId = "acme" → Logs/acme/log-20250101.txt.
Logs without the property → Logs/log-20250101.txt.

Sensitive Data Masking — One JSON Block Protects Every Sink

Stop writing Regex.Replace calls before every logger.LogInformation. Declare what's sensitive once, and LoggerHelper redacts it everywhere — Console, File, SQL, Elasticsearch, Seq, Telegram — before any sink ever sees it:

"SensitiveDataMasking": {
  "Enabled": true,
  "MaskText": "***MASKED***",
  "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!");
// → every sink receives: Login for ***MASKED*** with ***MASKED***
  • Built-in presets for the secrets that leak most often: emails, credit card numbers, JWTs, Bearer ... tokens, and Password=... / Pwd=... in connection strings.
  • SensitiveProperties redacts named structured fields outright (e.g. Password, ApiKey), regardless of content.
  • Custom regex rules with an optional secret capture group mask only part of a match — Bearer ***MASKED*** keeps the scheme visible while hiding the token.
  • Zero overhead when disabled (the default) — the enricher isn't added to the pipeline at all.

Serilog has no first-class equivalent: redaction usually means a hand-rolled IDestructuringPolicy or a third-party enricher wired up per project. Here it's one JSON block, applied globally.

↑ Back to Top


<a name="built-in-ui-dashboard"></a>

📊 Built-in UI — Dashboard

dotnet add package CSharpEssentials.LoggerHelper.Dashboard

LoggerHelper Dashboard Preview

Embedded real-time diagnostics dashboard for ASP.NET Core — no Seq, no Kibana, no extra infrastructure required. Navigate to /loggerhelper to see the health of your logging pipeline at a glance:

  • 📡 Live Log Stream: Browser-based tail -f via Server-Sent Events. Filter by level or text in real time.
  • 🩺 Sink Health Cards: At-a-glance status for every configured sink (ACTIVE / FAILED) and their assigned log levels.
  • ⚠️ Error History: Click-to-expand table of recent sink errors (SMTP failures, DB write errors) with full stack traces.
  • ⏪ Context Before Error: The killer feature. A zero-allocation ring buffer automatically flushes all preceding Debug/Info/Warning entries only when an Error or Fatal event fires. You see exactly what happened before the crash without keeping verbose logging on permanently!
// Program.cs
builder.Services.AddLoggerHelperDashboard(o => o.UseBasicAuthentication("admin", builder.Configuration["Dashboard:Password"]));
// ...
app.MapLoggerHelperDashboard(); // Exposes the UI at /loggerhelper

Authentication is mandatory on every Dashboard route (page, /api/status, /api/logs, /api/stream). Use the built-in Basic auth shown above (HTTPS only), your app's authentication, or a named AuthorizationPolicy. Without any of them MapLoggerHelperDashboard() throws InvalidOperationException at startup. See the Dashboard guide.

↑ Back to Top


<a name="ai-integration-mcp-server"></a>

🤖 AI Integration — MCP Server

dotnet add package CSharpEssentials.LoggerHelper.MCP

🤖 AI Diagnostics in Action: Here is an example of an AI assistant querying the running application's logging state in real-time, instantly identifying offline sinks (like Elasticsearch and Seq), and proposing actionable fixes directly in the chat:

LoggerHelper MCP Preview

Give your AI assistant live visibility into your running app's logging state. Two lines of setup expose a Model Context Protocol (MCP) server that Claude, Cursor, GitHub Copilot, and any MCP-compatible client can query.

// Program.cs — add after AddLoggerHelper()
builder.Services.AddLoggerHelperMcp();
// ...
app.MapLoggerHelperMcp("/mcp");        // Streamable HTTP  — Claude Code, Cursor, Copilot
app.MapLoggerHelperMcpSse();           // HTTP+SSE         — Claude Desktop, MCP Inspector

AI can now ask your app:

  • "Are all sinks healthy?" → loggerhelper_get_health (OK / WARNING / CRITICAL)
  • "Show me the last 10 logging errors" → loggerhelper_get_errors
  • "What levels does the Email sink receive?" → loggerhelper_get_sinks
  • "Is PII masking enabled?" → loggerhelper_get_config

Predefined prompt — run a full diagnostic with one command:

curl -X POST http://localhost:5000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"prompts/get","params":{"name":"diagnose-logging","arguments":{"focus":"all"}}}'

The diagnose-logging prompt instructs the AI to call all four tools and return a structured report with Overall Status, Failed Sinks, Configuration Issues, and Recommended Actions.

Why this matters: Every other .NET logging library requires a separate dashboard (Seq, Kibana, Grafana) before an AI assistant can see log state. LoggerHelper MCP ships that built in — zero extra infrastructure, zero extra dependencies, one NuGet package.

↑ Back to Top


<a name="sink-overview"></a>

📋 Sink Overview

Each sink is a separate NuGet package — install only what you need. Click guide → for the full configuration reference, sample output, and troubleshooting for each sink.

Sink What it does Install Full guide
Console Colored terminal output, per-level themes dotnet add package CSharpEssentials.LoggerHelper.Sink.Console guide →
File Rolling JSON files, per-property subdirectories, configurable retention dotnet add package CSharpEssentials.LoggerHelper.Sink.File guide →
Email SMTP alerts, HTML templates, throttling dotnet add package CSharpEssentials.LoggerHelper.Sink.Email guide →
Telegram Bot notifications, MarkdownV2, throttling dotnet add package CSharpEssentials.LoggerHelper.Sink.Telegram guide →
Elasticsearch Elasticsearch / OpenSearch indexing, auto template, Kibana-ready dotnet add package CSharpEssentials.LoggerHelper.Sink.Elasticsearch guide →
SQL Server Structured log table, auto creation, custom columns dotnet add package CSharpEssentials.LoggerHelper.Sink.MSSqlServer guide →
PostgreSQL JSONB properties column, custom schema dotnet add package CSharpEssentials.LoggerHelper.Sink.Postgresql guide →
MySQL / MariaDB Typed columns, native JSON column, auto table creation, batched writes dotnet add package CSharpEssentials.LoggerHelper.Sink.MySql guide →
Seq Centralized log server with search, alerts, and dashboards dotnet add package CSharpEssentials.LoggerHelper.Sink.Seq guide →
Hangfire Console Structured logs inside the Hangfire Dashboard dotnet add package CSharpEssentials.LoggerHelper.Sink.HangfireConsole guide →

Every sink uses the same routing pattern — just add the sink name to Routes:

"Routes": [
  { "Sink": "Console",       "Levels": ["Debug", "Information", "Warning"] },
  { "Sink": "File",          "Levels": ["Information", "Warning", "Error", "Fatal"] },
  { "Sink": "Elasticsearch", "Levels": ["Warning", "Error", "Fatal"] }
]

For per-sink configuration options (connection strings, paths, retention, custom columns), see the guide → linked in the table above.

↑ Back to Top


<a name="comparison"></a>

📊 Comparison

LoggerHelper sits on top of Serilog: everything below that plain Serilog or NLog already do is marked as such. Pick plain Serilog when you need maximum throughput or full programmatic control of the pipeline; LoggerHelper adds per-message overhead (see benchmarks).

Feature Serilog (plain) NLog LoggerHelper v5
Per-sink minimum level from JSON ✅ restrictedToMinimumLevel ✅ minlevel in rules ✅
Exact level set per sink (e.g. Information + Warning, not Error) Sub-logger + Serilog.Expressions filter per sink ✅ levels="Info,Warn" in rules ✅ Routes[].Levels
ILogger<T> support Via Serilog.Extensions.Logging / Serilog.AspNetCore Via NLog.Extensions.Logging Built in (registers an ILoggerProvider)
Sinks as separate NuGet packages ✅ ✅ ✅ auto-discovered via [ModuleInitializer]
Structured named params, BeginScope ✅ ✅ ✅ (propagated to Serilog)
JSON and code config combined ✅ ReadFrom.Configuration + WriteTo ✅ ✅ JSON, fluent or merged
Trace correlation ✅ TraceId/SpanId captured (Serilog 3+) Via NLog.DiagnosticSource ✅ plus log events added to the current Activity
Sink startup failures SelfLog (text output) InternalLogger (text output) Queryable ILogErrorStore, sink listed as Configured=false
Request/response logging UseSerilogRequestLogging (summary, no bodies) Manual Middleware with bodies (64 KB cap), 1 line
Email / Telegram alerts Serilog.Sinks.Email; Telegram via 3rd-party sinks NLog.MailKit; Telegram via 3rd-party Sink packages with built-in throttling
File path by log property (multi-tenant) Serilog.Sinks.Map ${event-properties} in fileName FileNameProperty in the File sink
Sensitive data masking 3rd-party (Destructurama, masking enrichers) 3rd-party / custom JSON-driven, applied to every sink
Minimal setup 2–3 lines + JSON (ReadFrom.Configuration) 1–2 lines + XML/JSON 2 lines + JSON
Overhead per message (no-op sink) baseline lower than Serilog ~3× plain Serilog
Maturity and ecosystem Standard, huge Established Young, small

↑ Back to Top


<a name="architecture"></a>

🏗️ Architecture

LoggerHelper uses a zero-dependency plugin architecture. The core package has no knowledge of any specific sink — they self-register at startup via [ModuleInitializer].

Your App
  └── CSharpEssentials.LoggerHelper (core)
        ├── Bridges ILogger<T> → Serilog (zero allocations on hot path)
        ├── Routes events by level via pre-computed HashSet<LogEventLevel>
        ├── Exposes ILogErrorStore for sink failure diagnostics
        └── Discovers sink plugins automatically at startup
              ├── Sink.Console    (auto-registers via [ModuleInitializer])
              ├── Sink.File       (auto-registers)
              ├── Sink.Email      (auto-registers)
              └── ... any ISinkPlugin

Performance Focus

Every version ships a targeted performance audit. Key hot-path optimizations to date:

Version Component Optimization Impact
v5.0.6 Middleware ReadBodySafe ArrayPool<char> replaces new char[64K] −256 KB LOH per request
v5.0.5 SinkRouting.Matches() HashSet<LogEventLevel> replaces string O(n) scan Zero alloc per log event
v5.0.5 Telegram Emit() Fire-and-forget Task.Run vs blocking GetResult() No pipeline stall
v5.0.5 Email template Cached at ctor vs File.ReadAllText per emit No disk I/O on hot path

Building a Custom Sink

[LoggerHelperSink]
public 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");

        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());
}

If required options are missing or empty, throw InvalidOperationException from Configure: the engine catches it, skips your sink and records it as not configured (FAILED in Dashboard/MCP). Do not silently return.

Reference CSharpEssentials.LoggerHelper as a NuGet package. The sink auto-registers with no changes to the core.

↑ Back to Top


<a name="view-source-contribute"></a>

🤝 View Source & Contribute

If you're reading this on NuGet, we highly recommend visiting our GitHub Repository!

By visiting the repository you can:

  • 👀 Explore the source code and evaluate the code quality.
  • 🐛 Check open issues or report new ones.
  • 🛠️ Contribute to the project via Pull Requests.
  • ⭐ Drop a star to support the project's growth!

↑ Back to Top


<a name="documentation-links"></a>

↑ Back to Top


License

MIT — Alessandro Chiodo

GitHub · NuGet · loggerhelper.it

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

NuGet packages (13)

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.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
5.3.2 0 10/11/2026
5.3.1 39 10/10/2026
5.3.0 42 10/10/2026
5.2.11 74 10/9/2026
5.2.10 171 10/7/2026
5.2.9 218 10/6/2026
5.2.8 218 10/6/2026
5.2.7 211 10/6/2026
5.2.6 288 8/31/2026
5.2.4.1 280 8/27/2026
5.2.4 312 8/25/2026
5.2.3 291 8/25/2026
5.2.2.9 495 7/11/2026
5.2.2.8 324 7/11/2026
5.2.2.7 318 7/10/2026
5.2.2.6 301 7/6/2026
5.2.2.5 309 7/5/2026
5.2.2.4 316 7/5/2026
5.2.2.3 305 7/5/2026
5.2.2.2 325 7/5/2026
Loading failed