Pragmatic.Logging
High-performance, structured logging framework for the Pragmatic.Design ecosystem. Extends .NET ILogger with zero-allocation hot paths, privacy-aware redaction, audit trail support, and multiple output providers.
The Problem
Section titled “The Problem”Production logging needs structured output, PII redaction, correlation IDs, rate limiting, and multiple output targets — all without adding latency. The standard .NET logging infrastructure provides the ILogger foundation but leaves these concerns to the developer. String interpolation allocates on every call. Secrets leak into logs when developers forget to sanitize. Context properties require manual passing at every call site. And configuring all of these concerns together requires cobbling together multiple libraries.
// Without Pragmatic: allocates on every call, no redaction, no contextlogger.LogInformation($"Order {orderId} placed by {email} via {connectionString}");// Leaks PII (email) and secrets (connection string), allocates a string even when level is disabledThe Solution
Section titled “The Solution”Pragmatic.Logging wraps the standard Microsoft.Extensions.Logging infrastructure with a fluent PragmaticLoggingBuilder API. One builder configures all concerns: providers, presets, privacy, performance, and context enrichment. All providers integrate with the standard ILogger<T> interface — no proprietary abstractions.
// With Pragmatic: one builder, all concerns, zero-allocation hot pathsbuilder.Services.AddLogging(logging =>{ logging.ClearProviders(); var pragmatic = logging.AddPragmaticLogging(); pragmatic .UseProductionPreset() // Background processing, rate limiting, correlation IDs .AddConsole() // Colored terminal output .AddFile("logs/app-{Date}.log") // Rolling file with retention .EnableDataRedaction(r => // Automatic PII redaction r.SensitivePropertyNames = ["password", "email", "apiKey"]);});Performance
Section titled “Performance”Benchmarked against Serilog and NLog on .NET 10 (BenchmarkDotNet 0.14.0):
| Scenario | Pragmatic | NLog | Serilog |
|---|---|---|---|
| Simple logging | 21.87 ns / 64 B | 138.52 ns / 488 B | 155.06 ns / 440 B |
| Structured logging | 46.98 ns / 216 B | 279.84 ns / 696 B | 557.59 ns / 2016 B |
| Exception logging | 21.48 ns / 64 B | 134.99 ns / 504 B | 163.39 ns / 440 B |
| High volume (1000/iter) | 18.88 us / 64 KB | 134.75 us / 476 KB | 154.71 us / 430 KB |
Full benchmark results are in BENCHMARK-RESULTS.md.
Installation
Section titled “Installation”dotnet add package Pragmatic.LoggingQuick Start
Section titled “Quick Start”Basic Registration
Section titled “Basic Registration”builder.Services.AddLogging(logging =>{ var pragmatic = logging.AddPragmaticLogging(); pragmatic .UseDevelopmentPreset() .AddConsole() .AddFile("logs/app-{Date}.log");});Preset-Based Configuration
Section titled “Preset-Based Configuration”// Production with rate limiting and correlation IDsvar pragmatic = logging.AddPragmaticLogging();pragmatic .UseProductionPreset() .AddFile("logs/app-{Date}.log") .AddJson(Console.OpenStandardOutput());Compliance Configuration
Section titled “Compliance Configuration”// GDPR-compliant logging with audit trailvar pragmatic = logging.AddPragmaticLogging();pragmatic .UseCompliancePreset(ComplianceStandard.Gdpr) .EnableDataRedaction(r => { r.RedactionPlaceholder = "[REDACTED]"; r.PreserveLengths = false; }) .EnableAuditTrail(a => { a.StorageType = "Database"; a.FlushIntervalSeconds = 30; });Providers
Section titled “Providers”All providers implement IPragmaticLoggerProvider and register as ILoggerProvider with the DI container.
| Provider | Class | Output |
|---|---|---|
| Console | PragmaticConsoleProvider | Colored terminal output with structured data |
| File | PragmaticFileProvider | File-based with rolling, retention, async I/O |
| JSON | PragmaticJsonProvider | Structured JSON / NDJSON output |
| Enhanced JSON | PragmaticEnhancedJsonProvider | NDJSON with async buffering |
| Memory | PragmaticMemoryProvider | In-memory buffer for testing |
| Debug | PragmaticDebugProvider | Debug output window |
| Null | PragmaticNullProvider | No-op for benchmarking |
| Windows Event Log | PragmaticWindowsEventLogProvider | Windows Event Log |
Adding Providers via Builder
Section titled “Adding Providers via Builder”pragmatic .AddConsole(opts => { opts.UseColors = true; opts.IncludeStructuredData = true; }) .AddFile("logs/app-{Date}.log", opts => { opts.MaxFileSizeMB = 100; opts.RetentionDays = 30; }) .AddJson(Console.OpenStandardOutput(), opts => { opts.WriteIndented = false; }) .AddMemory() .AddDebug() .AddNdjsonAsync("logs/structured-{Date}.ndjson");File Provider Features
Section titled “File Provider Features”PragmaticFileProvider is a high-performance file logger with:
- Channel-based async processing — lock-free queuing with
System.Threading.Channels - Automatic file rolling — by size (configurable
MaxFileSize) or time interval (Hour, Day, Week, Month, Year) - Retention policies — automatic cleanup of old files (
MaxRetainedFiles) - Template-based file naming —
{Date},{DateTime},{Year},{Month},{Day},{Hour}placeholders - Back-pressure handling — configurable Drop or Block policy when queue is full
- Exponential backoff retry — on write failures with configurable delays
- Health monitoring —
PerformCustomHealthCheck()reports Healthy/Degraded/Unhealthy
// Template-based file paths"logs/app-{Date}.log" // app-2026-03-21.log"logs/{Year}/{Month}/app-{Day}.log" // logs/2026/03/app-21.log"logs/app-{Hour}.log" // app-14.log (hourly rolling)Configuration Presets
Section titled “Configuration Presets”PragmaticLoggingBuilder provides 4 built-in presets:
Development
Section titled “Development”pragmatic.UseDevelopmentPreset();- MinimumLevel:
Trace - HighPerformanceMode: disabled
- Telemetry: disabled
- Machine context: enabled, user context: disabled
Production
Section titled “Production”pragmatic.UseProductionPreset();- MinimumLevel:
Information - Background processing: enabled, buffer size 5000
- Rate limiting: enabled (1000 msg/sec)
- Correlation IDs and user context: enabled
High Performance
Section titled “High Performance”pragmatic.UseHighPerformancePreset();- MinimumLevel:
Information(skips Debug/Trace) - HighPerformanceMode: enabled
- Zero-allocation optimizations: enabled
- Buffer size: 10000, flush threshold: 1000
Compliance
Section titled “Compliance”pragmatic.UseCompliancePreset(ComplianceStandard.Gdpr);- Redaction: enabled
- Secret detection: enabled
- Audit trail: enabled with database storage
- GDPR: confidence threshold 0.8, complete redaction
- HIPAA: confidence threshold 0.9
- PCI-DSS: confidence threshold 0.95
Privacy and Redaction
Section titled “Privacy and Redaction”Secret Detection
Section titled “Secret Detection”The SecretDetector engine scans log content for sensitive information using pattern matching:
Detection categories:
- Crypto (private keys) — severity Critical, confidence 0.95
- API keys (AWS, GitHub, generic) — severity High, confidence 0.75—0.90
- Tokens (JWT, OAuth) — severity Medium—High, confidence 0.70—0.90
- Database (connection strings, passwords) — severity High, confidence 0.80
- Cloud (Azure, GCP keys) — severity High, confidence 0.80
Detection features:
- Pre-compiled regex patterns for performance
- Property name hinting (confidence boost for
password,token,keyproperties) - False positive filtering (placeholders, common GUIDs, sequential hex)
- Overlap resolution (keeps highest-confidence match)
- Audit trail integration
Redaction styles:
Placeholder—[APIKEYS_REDACTED](category-based)PreserveLength—************PreserveStructure—[JWT_HEADER].[JWT_PAYLOAD].[JWT_SIGNATURE]Minimal—[REDACTED]
Data Redaction Configuration
Section titled “Data Redaction Configuration”pragmatic.EnableDataRedaction(redaction =>{ redaction.RedactionPlaceholder = "[REDACTED]"; redaction.PreserveLengths = false; redaction.PreserveJsonStructure = true; redaction.SensitivePropertyNames = ["password", "secret", "apiKey"]; redaction.PropertyNamePatterns = [@".*password.*", @".*secret.*"]; redaction.MessageRedactionPatterns = [@"[\w.+-]+@[\w-]+\.[\w.]+"];});Audit Trail
Section titled “Audit Trail”The audit subsystem provides compliance-grade logging for regulatory requirements.
Components
Section titled “Components”| Type | Purpose |
|---|---|
PragmaticAuditService | Core audit service, records compliance violations |
IAuditPolicy | Policy interface for audit behavior (Default, GDPR, HighPerformance, Development) |
IAuditStorage | Storage interface for audit entries |
MemoryAuditStorage | In-memory storage (testing) |
FileSystemAuditStorage | File-based audit storage |
Configuration
Section titled “Configuration”pragmatic.EnableAuditTrail(audit =>{ audit.StorageType = "FileSystem"; // FileSystem, Database, Memory audit.PolicyType = "GDPR"; // Default, GDPR, HighPerformance, Development audit.BatchSize = 100; audit.FlushIntervalSeconds = 30;});Rate Limiting
Section titled “Rate Limiting”Lock-free, per-message rate limiting via HighPerformanceRateLimiter:
pragmatic.EnableRateLimiting(rl =>{ rl.MaxMessagesPerSecond = 1000; rl.BurstSize = 100; rl.Strategy = "TokenBucket"; // TokenBucket, FixedWindow, SlidingWindow});Context Enrichment
Section titled “Context Enrichment”Built-in Context Providers
Section titled “Built-in Context Providers”| Provider | Properties Added |
|---|---|
HttpContextProvider | RequestPath, RequestMethod, UserId (from claims) |
CorrelationIdProvider | CorrelationId |
MachineContextProvider | MachineName |
ProcessContextProvider | ProcessId |
ThreadContextProvider | ThreadId |
ASP.NET Core Integration
Section titled “ASP.NET Core Integration”// Middleware for automatic enrichmentapp.UseMiddleware<LoggingEnrichmentMiddleware>();Bootstrap Logger
Section titled “Bootstrap Logger”For logging before DI is ready:
using var bootstrap = BootstrapLogger.Create();bootstrap.LogInformation("Starting application...");Configuration via appsettings.json
Section titled “Configuration via appsettings.json”All options can be bound from IConfiguration:
{ "PragmaticLogging": { "Enabled": true, "MinimumLevel": "Information", "HighPerformanceMode": false, "Privacy": { "EnableRedaction": true, "EnableSecretDetection": true, "ComplianceStandard": "General", "SecretDetection": { "MinimumSecretLength": 8, "PrecompilePatterns": true, "MinimumConfidenceForRedaction": 0.7 }, "DataRedaction": { "RedactionPlaceholder": "[REDACTED]", "SensitivePropertyNames": ["password", "secret"] } }, "Performance": { "BufferSize": 1000, "FlushThreshold": 100, "EnableZeroAllocation": true, "UseBackgroundProcessing": true }, "RateLimiting": { "Enabled": false, "MaxMessagesPerSecond": 1000, "Strategy": "TokenBucket" }, "Providers": { "Console": { "Enabled": true, "UseColors": true }, "File": { "Enabled": true, "BasePath": "./logs", "MaxFileSizeMB": 100 } } }}Zero-Allocation Infrastructure
Section titled “Zero-Allocation Infrastructure”For hot paths, the module provides:
| Type | Purpose |
|---|---|
StackAllocatedBuffer | Stack-allocated buffer for formatting |
ZeroAllocMessageFormatter | Message formatting without allocations |
StringBuilderPool | Object pool for StringBuilder reuse |
DefaultObjectPool<T> | Generic object pool implementation |
PropertyPool | Pool for log property objects |
Key Types
Section titled “Key Types”| Type | Namespace | Purpose |
|---|---|---|
PragmaticLoggingBuilder | Pragmatic.Logging | Fluent configuration API |
PragmaticLoggingOptions | Pragmatic.Logging.Configuration | Main options class |
SecretDetector | Pragmatic.Logging.Privacy | Secret detection engine |
PragmaticDataRedactor | Pragmatic.Logging.Privacy | Data redaction service |
PragmaticAuditService | Pragmatic.Logging.Privacy.Audit | Audit trail service |
PragmaticFileProvider | Pragmatic.Logging.Providers | High-performance file provider |
PragmaticConsoleProvider | Pragmatic.Logging.Providers | Console provider |
PragmaticJsonProvider | Pragmatic.Logging.Providers | JSON/NDJSON provider |
LoggingEnrichmentMiddleware | Pragmatic.Logging.AspNetCore | ASP.NET Core enrichment middleware |
BootstrapLogger | Pragmatic.Logging.AspNetCore | Pre-DI logger |
| Benchmark Results | BENCHMARK-RESULTS.md |
Dependencies
Section titled “Dependencies”Microsoft.Extensions.Logging.Abstractions10.0.0OpenTelemetry.Api(optional, for trace correlation)
License
Section titled “License”Part of the Pragmatic.Design ecosystem.