Architecture and Core Concepts
This guide explains why Pragmatic.Logging exists, how its pieces fit together, and how to choose the right configuration for each situation. Read this before diving into the individual feature guides.
The Problem
Section titled “The Problem”Logging sits on the hot path of every request. A production application needs structured log output, correlation IDs for distributed tracing, PII redaction for compliance, rate limiting to prevent log spam, and multiple output targets – all without adding measurable latency. The standard .NET logging infrastructure provides the foundation, but leaves these concerns to the developer.
Manual formatting wastes allocations
Section titled “Manual formatting wastes allocations”// Every call allocates a new string, even when the level is disabledlogger.LogInformation($"Order {orderId} placed by {customerId} for {total:C}");
// Even the recommended structured approach allocates parameter arrayslogger.LogInformation("Order {OrderId} placed by {CustomerId} for {Total}", orderId, customerId, total);Under high throughput, string allocations from logging alone can create GC pressure that causes visible latency spikes. The standard LoggerMessage.Define pattern helps, but requires boilerplate for every message.
No built-in privacy protection
Section titled “No built-in privacy protection”// This logs the full connection string, including the passwordlogger.LogError("Failed to connect: {ConnectionString}", connectionString);
// This leaks the JWT token into your log aggregatorlogger.LogDebug("Auth header: {AuthHeader}", request.Headers.Authorization);
// This writes PII to disk in a GDPR-regulated environmentlogger.LogInformation("User {Email} placed order {OrderId}", user.Email, orderId);There is no standard mechanism to detect and redact secrets, API keys, or personally identifiable information before they reach the log output. Developers must remember to sanitize every call site – and they will forget.
No structured context enrichment
Section titled “No structured context enrichment”// Without enrichment, you pass context manually at every call sitelogger.LogInformation("Order placed. CorrelationId={CorrelationId}, UserId={UserId}, " + "Machine={Machine}, RequestPath={Path}", correlationId, userId, Environment.MachineName, httpContext.Request.Path);When debugging a production incident across dozens of service replicas, you need every log entry to carry ambient context – correlation IDs, user identifiers, request paths, machine names. Passing these values explicitly at every call site is error-prone and clutters the business code.
No unified configuration
Section titled “No unified configuration”Each concern – output targets, formatting, filtering, rate limiting, compliance – requires its own configuration surface. Developers cobble together Serilog enrichers, NLog targets, custom middleware, and manual redaction code. There is no single place to configure “production-ready logging” with one call.
The Solution
Section titled “The Solution”Pragmatic.Logging wraps the standard Microsoft.Extensions.Logging infrastructure with a fluent PragmaticLoggingBuilder API. It provides:
- Zero-allocation formatter –
ZeroAllocMessageFormatter.TryFormatuses stack-allocated buffers and pooledStringBuilderinstances to format with no heap allocation (the formatter itself; end-to-end pipeline costs are in the performance guide) - Automatic secret detection and PII redaction – pre-compiled regex patterns scan log content before it reaches any output provider
- Context enrichment – ambient properties (correlation IDs, user identity, machine name) are attached to every log entry without changes to business code
- Multiple providers – console, file, JSON, NDJSON, memory, debug, Windows Event Log, and custom providers
- Configuration presets – one-call setup for Development, Production, High Performance, and Compliance scenarios
- Rate limiting – lock-free token bucket, sliding window, and fixed window strategies prevent log spam
- Audit trail – compliance-grade recording of every redaction event and sensitive data access
- Standard interface – everything works through
ILogger<T>. No proprietary abstractions.
// With Pragmatic: one builder, all concerns configuredbuilder.Services.AddPragmaticLogging(pragmatic => pragmatic .UseProductionPreset() // Sensible defaults for production .AddConsole() // Colored terminal output .AddFile("logs/app-{Date}.log") // Rolling file with retention .AddJson("logs/app.json")); // Structured JSON for log aggregatorsOr integrated with the Pragmatic.Composition host:
await PragmaticApp.RunAsync(args, app =>{ app.UseLogging(log => { log.AddConsole(PragmaticConsoleConfiguration.ForDevelopment()); log.AddFile("logs/app-{Date}.log"); });});Performance
Section titled “Performance”Benchmarked on .NET 10 against Serilog, NLog and ZLogger, each writing into a sink that renders the message and reads every property (per call, 2026-10-09):
| Scenario | Pragmatic | ZLogger | NLog | Serilog |
|---|---|---|---|---|
[LoggerMessage] call site |
132.2 ns / 128 B | 156.9 ns / 192 B | 389.7 ns / 1,416 B | 329.5 ns / 800 B |
| Simple logging | 147.0 ns / 168 B | 170.0 ns / 216 B | 237.7 ns / 760 B | 276.2 ns / 528 B |
| Structured (with scope) | 378.9 ns / 464 B | 432.8 ns / 520 B | 674.2 ns / 1,328 B | 860.5 ns / 1,912 B |
| Exception logging | 208.8 ns / 184 B | 218.9 ns / 232 B | 316.2 ns / 776 B | 367.0 ns / 528 B |
| Production (context + scope) | 695.5 ns / 864 B | 589.9 ns / 832 B | 1,065.9 ns / 2,872 B | 1,299.4 ns / 3,000 B |
Pragmatic is ahead of Serilog and NLog in every scenario, and allocates the least of the four everywhere but Production. Against ZLogger it is faster in every scenario but Production: on exception logging the lead is within this run’s deviation, and beyond it on the CI runner, whose deviation is ten times smaller. Production is ZLogger’s, by 4% on the runner, and the request context is why: see the results page.
A provider writes a call from its state: the properties read where the call put them, the scopes from the
ambient stack, no LogEntry and no dictionary. A call builds an entry only for what needs one — an
advanced filter, the pattern redactor, declared redaction. See
BENCHMARK-RESULTS.md for the run, the machine, the reports, and where the bytes
went.
How It Works
Section titled “How It Works”Pragmatic.Logging is built on three layers: the builder that configures the pipeline, the provider base that enforces the pipeline for every output target, and the providers that write log entries to their destinations.
Layer 1: PragmaticLoggingBuilder
Section titled “Layer 1: PragmaticLoggingBuilder”The PragmaticLoggingBuilder is the entry point for all configuration. services.AddPragmaticLogging(pragmatic => …) (or app.UseLogging(…) in a Pragmatic host) hands it to you, and it provides a fluent API for adding providers, applying presets, enabling privacy features, and configuring performance options. There is one: Pragmatic.Logging.Extensions.PragmaticLoggingBuilder.
// inside services.AddPragmaticLogging(pragmatic => { … })
// Presets configure all knobs at oncepragmatic.UseProductionPreset();
// Then override individual settingspragmatic.Configure(opts => opts.MinimumLevel = LogLevel.Debug);
// Add providerspragmatic.AddConsole();pragmatic.AddFile("logs/app-{Date}.log");
// Enable privacy featurespragmatic.EnableDataRedaction(r => r.RedactionPlaceholder = "[REDACTED]");pragmatic.EnableAuditTrail(a => a.StorageType = "FileSystem");Layer 2: PragmaticLoggerProviderBase
Section titled “Layer 2: PragmaticLoggerProviderBase”Every provider – built-in or custom – extends PragmaticLoggerProviderBase. This base class enforces a consistent pipeline for every log entry:
Log Entry | v[IsEnabled check] --no--> (dropped, zero work) | yes v[Advanced filter chain] --filtered--> (dropped, counter incremented) | pass v[Context enrichment] -- adds CorrelationId, UserId, MachineName, etc. | v[Structured property filter] -- applies ContextFilterMode | v[Data redaction] |-- SecretDetector scans message + property values |-- PragmaticDataRedactor checks property names + patterns |-- Audit trail records each redaction event | v[WriteLogCore] -- provider-specific output (console, file, JSON, etc.)This means every provider automatically benefits from the full privacy stack, context enrichment, and filtering. You never need to implement redaction in a custom provider.
Layer 3: Providers
Section titled “Layer 3: Providers”Each provider implements WriteLogCore and handles the specific output format and destination. Pragmatic.Logging ships with eight built-in providers:
| 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 for log aggregators |
| Enhanced JSON | PragmaticEnhancedJsonProvider |
NDJSON with async buffering |
| Memory | PragmaticMemoryProvider |
In-memory buffer for testing |
| Debug | PragmaticDebugProvider |
Debug output window (Visual Studio, Rider) |
| Null | PragmaticNullProvider |
No-op for benchmarking |
| Windows Event Log | PragmaticWindowsEventLogProvider |
Windows Event Log |
High-Performance Logging: [LoggerMessage]
Section titled “High-Performance Logging: [LoggerMessage]”For hot paths, declare [LoggerMessage] methods. Pragmatic.Logging works entirely through the
standard ILogger abstraction, and the attribute is the one you know: in a project that references
Pragmatic.SourceGenerator it binds to Pragmatic’s, whose generated state writes itself as UTF-8 and
masks a [PersonalData] or [NotLogged] argument at the call site. Without the generator it is
Microsoft’s. See Log call sites.
using Microsoft.Extensions.Logging;
public partial class OrderService(ILogger<OrderService> logger){ public void PlaceOrder(Guid orderId, string customerId) { LogOrderPlaced(orderId, customerId); }
[LoggerMessage(Level = LogLevel.Information, Message = "Order {OrderId} placed by {CustomerId}")] private partial void LogOrderPlaced(Guid orderId, string customerId);}The generated method performs an IsEnabled check before any work and hands the logger a struct
state with no boxing. When the Pragmatic JSON provider writes it from that state — context enrichment,
filters and pattern redaction off, no active scope — a call like this one allocates nothing; the
conditions are listed with the reasons.
When to use which approach
Section titled “When to use which approach”| Approach | Allocation | Use Case |
|---|---|---|
[LoggerMessage] partial method |
Minimal (no boxing) | Hot paths, high-throughput code |
logger.LogInformation("...", args) |
Low (parameter array) | Business logic, moderate throughput |
String interpolation $"..." |
High (string + boxing) | Never in production code |
Privacy and Redaction
Section titled “Privacy and Redaction”Pragmatic.Logging provides a layered defense against accidental exposure of sensitive data.
Secret Detection
Section titled “Secret Detection”The SecretDetector scans log messages and property values against a curated library of pre-compiled regex patterns. Each detection carries a confidence score and severity level.
| Category | Examples | Severity |
|---|---|---|
| Crypto | RSA/EC/PGP private keys | Critical |
| API Keys | AWS (AKIA...), GitHub PAT (ghp_...), Stripe (sk_live_...) |
Critical |
| Tokens | JWT (eyJ...), Bearer tokens, OAuth refresh tokens |
High |
| Database | Connection strings with Password=, MongoDB URIs |
Critical |
| Cloud | Azure Storage Key, GCP Service Account Key | Critical |
| Application | Encryption keys, hash salts | Medium |
The SecretDetectionOptions.MinimumConfidenceForRedaction threshold (default: 0.7) controls which detections trigger automatic redaction. Detections below the threshold are logged for review but not redacted.
Data Redaction
Section titled “Data Redaction”Beyond secret detection, the PragmaticDataRedactor handles PII and business-sensitive data based on property names and message content patterns:
- Explicit flag – Properties marked with
PropertyCharacteristics.Redactedare always redacted - Name matching – Property names checked against a
HashSet<string>of sensitive names (case-insensitive) and compiled regex patterns - Message scanning – Log message text scanned for emails, credit card numbers, SSNs, and custom patterns
pragmatic.EnableDataRedaction(redaction =>{ redaction.RedactionPlaceholder = "[REDACTED]"; redaction.SensitivePropertyNames = ["password", "apiKey", "email", "ssn"]; redaction.PropertyNamePatterns = [@".*password.*", @".*secret.*"]; redaction.MessageRedactionPatterns = [@"[\w.+-]+@[\w-]+\.[\w.]+"]; // Email});Redaction Styles
Section titled “Redaction Styles”| Style | Output | Description |
|---|---|---|
Placeholder |
[API_KEY_REDACTED] |
Descriptive placeholder with secret type |
PreserveLength |
******************************** |
Asterisks matching original length |
PreserveStructure |
eyJ***.***.*** |
Keeps format markers (JWT segments) |
Minimal |
[REDACTED] |
Simple constant replacement |
Compliance Standards
Section titled “Compliance Standards”Pre-built compliance templates configure the correct sensitive property lists, message patterns, redaction placeholders, audit requirements, and data retention periods:
| Standard | Placeholder | Deep Redaction | Audit Trail | Retention |
|---|---|---|---|---|
| GDPR | [GDPR-REDACTED] |
Yes | Yes | 2 years |
| HIPAA | [PHI-REDACTED] |
Yes | Yes | 6 years |
| PCI-DSS | [CARD-DATA-REDACTED] |
Yes | Yes | 1 year |
| CCPA | [REDACTED] |
Yes | Yes | 90 days |
| SOX | [REDACTED] |
Yes | Yes | 7 years |
// GDPR-compliant loggingpragmatic.UseCompliancePreset(ComplianceStandard.Gdpr);
// Multi-compliance (uses most restrictive settings)var config = ComplianceTemplates.CreateMultiCompliance( includeGdpr: true, includeHipaa: true, includePciDss: false);Zero-Allocation Performance
Section titled “Zero-Allocation Performance”For hot paths, Pragmatic.Logging provides infrastructure that eliminates heap allocations.
StackAllocatedBuffer
Section titled “StackAllocatedBuffer”Small messages (up to 1,024 characters) are formatted into a stackalloc buffer. Larger messages fall back to ArrayPool<char>.Shared so the rented array is reused across calls.
ZeroAllocMessageFormatter
Section titled “ZeroAllocMessageFormatter”The core formatting engine uses a ThreadLocal<StringBuilder> pool and ArrayPool<object?> for parameter arrays, minimizing allocations on every call. It has specialized handlers for common types:
| Type | Allocation | Method |
|---|---|---|
int, long, float, double, decimal |
Zero | TryFormat(Span<char>) |
DateTime, DateTimeOffset |
Zero | TryFormat with ISO 8601 |
TimeSpan, Guid |
Zero | TryFormat |
bool |
Zero | Literal copy |
string |
Zero | AsSpan().CopyTo() |
ISpanFormattable |
Zero | Interface TryFormat |
| Other | 1 allocation | ToString() fallback |
Object Pooling
Section titled “Object Pooling”| Pool | Purpose |
|---|
Early-Exit IsEnabled Checks
Section titled “Early-Exit IsEnabled Checks”Every provider performs an IsEnabled check with [MethodImpl(AggressiveInlining)] before any formatting work begins. If the log level is below the configured minimum, the call returns immediately with zero work done.
Context Enrichment
Section titled “Context Enrichment”Context enrichment automatically attaches ambient information to every log entry without requiring the developer to pass values explicitly at every call site.
Built-in Context Providers
Section titled “Built-in Context Providers”| Provider | Priority | Scope | Key Properties |
|---|---|---|---|
HttpContextProvider |
100 | Per-request | RequestPath, RequestMethod, UserId, RemoteIpAddress |
CorrelationIdProvider |
50 | Per-request | CorrelationId, TraceId, SpanId |
ThreadContextProvider |
500 | Per-call | ThreadId, ThreadName, IsBackground |
ProcessContextProvider |
900 | Per-process | ProcessId, ProcessName, AppVersion |
MachineContextProvider |
1000 | Per-machine | MachineName, OSVersion, CLRVersion |
Custom Providers
Section titled “Custom Providers”Extend ContextProviderBase for domain-specific context. The provider lives as long as the context
manager (a singleton), so what belongs to the request, the tenant, it reads on each call, not in its
constructor, and it declares itself not static so that the manager asks it on each call:
public sealed class TenantContextProvider(IHttpContextAccessor httpContextAccessor) : ContextProviderBase("Tenant", priority: 80){ public override bool IsStatic => false;
public override bool IsAvailable() => CurrentTenant() is { IsResolved: true };
public override IReadOnlyDictionary<string, object?> GetContextProperties() { var tenant = CurrentTenant(); return CreatePropertiesDictionary(("TenantId", tenant?.TenantId), ("TenantName", tenant?.TenantName)); }
private ITenantContext? CurrentTenant() => httpContextAccessor.HttpContext?.RequestServices.GetService<ITenantContext>();}See Context Enrichment for its registration.
ASP.NET Core Middleware
Section titled “ASP.NET Core Middleware”Two middleware components wire enrichment into the HTTP pipeline:
-
LoggingEnrichmentMiddleware– Creates a logging scope with correlation ID, request path, request method, and user identity. Optionally logs request start/completion with timing and maps HTTP status codes to log levels (5xx = Error, 4xx = Warning, 2xx/3xx = Information). -
BaggagePropagationMiddleware– Propagates selected context values intoActivity.Baggagefor automatic forwarding to downstream services via W3C Baggage headers.
app.UseMiddleware<BaggagePropagationMiddleware>();app.UseMiddleware<LoggingEnrichmentMiddleware>();Per-Provider Context Filtering
Section titled “Per-Provider Context Filtering”Each provider can independently control which context properties it includes via ContextFilterConfiguration. This lets you add full context to file logs while keeping console output compact.
logging.AddConsole(config =>{ config.ContextFilter = new ContextFilterConfiguration { Mode = ContextFilterMode.Include, PropertyNames = new HashSet<string> { "CorrelationId", "UserId" } };});| Mode | Behavior |
|---|---|
All |
Include all context properties (default) |
Include |
Include only listed properties |
Exclude |
Include all except listed properties |
None |
Include no context properties |
Configuration Presets
Section titled “Configuration Presets”PragmaticLoggingBuilder provides four built-in presets that configure all knobs at once.
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 file-system storage (database storage is not implemented)
- Confidence thresholds vary by standard (GDPR: 0.8, HIPAA: 0.9, PCI-DSS: 0.95)
Override After Preset
Section titled “Override After Preset”Presets set sensible defaults. Override individual settings after applying a preset:
pragmatic .UseProductionPreset() .Configure(opts => opts.MinimumLevel = LogLevel.Debug);Rate Limiting
Section titled “Rate Limiting”Under sustained load, a noisy log category can produce thousands of duplicate messages per second. The HighPerformanceRateLimiter throttles log output using one of three strategies without blocking the caller.
| Strategy | Algorithm | Behavior |
|---|---|---|
TokenBucket |
Token bucket | Allows bursts up to bucket size, then rate-limits. Best for most scenarios. |
SlidingWindow |
Sliding window | Precise rate over a moving window. Best for strict compliance. |
FixedWindow |
Fixed window | Simple counter reset at boundary. Fastest, but allows edge bursts. |
pragmatic.EnableRateLimiting(rl =>{ rl.MaxMessagesPerSecond = 1000; rl.BurstSize = 100; rl.Strategy = "TokenBucket";});Background Processing and Batching
Section titled “Background Processing and Batching”Synchronous writes to disk or network block the calling thread. Pragmatic.Logging decouples log production from log output.
Background Processing
Section titled “Background Processing”When enabled, log entries are enqueued into a bounded channel. A background consumer thread drains the queue and writes entries in batches.
Caller thread Background thread | | |-- Enqueue(entry) --> | | (non-blocking) | | [Wait for batch/timer] | | | [WriteLogCore(batch)]Queue Overflow Strategies
Section titled “Queue Overflow Strategies”| Strategy | Data Loss | Blocking |
|---|---|---|
DropOldest |
Oldest entries | No |
DropNewest |
Newest entries | No |
Block |
None | Yes |
Expand |
None | No |
For production, DropOldest is recommended. Use Block only in compliance-critical scenarios.
Batching
Section titled “Batching”Individual disk writes are expensive. Batching amortizes the cost by collecting entries until either the BatchSize threshold or FlushTimeout is reached.
| Scenario | Recommended Batch Size | Flush Interval |
|---|---|---|
| Web API (moderate traffic) | 50-100 | 1-2 seconds |
| High-throughput service | 200-500 | 5-10 seconds |
| Real-time streaming | 10-20 | 100 ms |
| Compliance (every entry matters) | 25-50 | 500 ms |
Audit Trail
Section titled “Audit Trail”The PragmaticAuditService records every redaction event, sensitive data access, and compliance violation into a durable audit store. It runs as an IHostedService with batch processing and configurable flush intervals.
Storage Options
Section titled “Storage Options”| Storage | Class | Persistence | Best For |
|---|---|---|---|
| Memory | MemoryAuditStorage |
In-process | Testing, development |
| File System | FileSystemAuditStorage |
Disk | Single-server deployments |
Audit Policies
Section titled “Audit Policies”| Policy | Description |
|---|---|
| Default | Records all redaction and access events |
| GDPR | Records everything, forces immediate flush for violations |
| HighPerformance | Only records high-severity events |
| Development | Minimal auditing for fast iteration |
pragmatic.EnableAuditTrail(audit =>{ audit.StorageType = "FileSystem"; audit.PolicyType = "GDPR"; audit.BatchSize = 100; audit.FlushIntervalSeconds = 30;});Bootstrap Logger
Section titled “Bootstrap Logger”For logging before the DI container is built (during startup configuration):
using var bootstrap = BootstrapLogger.Create();bootstrap.LogInformation("Starting application...");
var builder = WebApplication.CreateBuilder(args);// ... configure services ...Configuration via appsettings.json
Section titled “Configuration via appsettings.json”All options bind to the PragmaticLogging configuration section:
{ "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 } } }}Ecosystem Integration
Section titled “Ecosystem Integration”IPragmaticBuilder
Section titled “IPragmaticBuilder”Pragmatic.Logging integrates with the Pragmatic.Composition host via UseLogging():
await PragmaticApp.RunAsync(args, app =>{ app.UseLogging(log => { log.AddConsole(PragmaticConsoleConfiguration.ForDevelopment()); log.AddFile("logs/app-{Date}.log"); });});Standard ILogger
Section titled “Standard ILogger”After registration, inject and use ILogger<T> as usual. Pragmatic.Logging handles enrichment, redaction, and routing behind the scenes:
public class OrderService(ILogger<OrderService> logger){ public void ProcessOrder(int orderId) { logger.LogInformation("Processing order {OrderId}", orderId); }}Custom Providers
Section titled “Custom Providers”Implement IPragmaticLoggerProvider or extend PragmaticLoggerProviderBase for custom output targets. The base class handles configuration, metrics, health checks, enrichment, and redaction – you only implement WriteLogCore.
public sealed class SlackAlertProvider : PragmaticLoggerProviderBase{ protected override void WriteLogCore(LogEvent logEvent) { if (logEvent.LogLevel < LogLevel.Error) return; // Send to Slack webhook }}The LogEvent is reused by the next call on the thread: a provider that keeps it past the call keeps
logEvent.ToEntry(). See Providers.
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 |
PragmaticMemoryProvider |
Pragmatic.Logging.Providers |
In-memory provider for testing |
LoggingEnrichmentMiddleware |
Pragmatic.Logging.AspNetCore |
ASP.NET Core enrichment middleware |
BaggagePropagationMiddleware |
Pragmatic.Logging.AspNetCore |
Distributed tracing baggage propagation |
BootstrapLogger |
Pragmatic.Logging.AspNetCore |
Pre-DI logger |
ContextManager |
Pragmatic.Logging.Context |
Context provider registry |
HighPerformanceRateLimiter |
Pragmatic.Logging |
Lock-free rate limiter |
ZeroAllocMessageFormatter |
Pragmatic.Logging.ZeroAllocation |
Zero-allocation message formatting |
See Also
Section titled “See Also”- Getting Started – Installation, registration, first provider
- Log Providers – Detailed configuration for each provider
- Privacy and Security – Secret detection, data redaction, compliance
- Performance – Zero-allocation, batching, rate limiting, background processing
- Context Enrichment – Built-in and custom context providers
- Common Mistakes – Pitfalls and how to avoid them
- Troubleshooting – Problem/solution guide
