Troubleshooting
Practical problem/solution guide for Pragmatic.Logging. Each section covers a common issue, the likely causes, and the fix.
Log Output Missing Entirely
Section titled “Log Output Missing Entirely”Your application runs, but no log output appears in any provider.
Checklist
Section titled “Checklist”-
Did you call
AddPragmaticLogging()? The builder must be created before any providers are added.builder.Services.AddLogging(logging =>{var pragmatic = logging.AddPragmaticLogging(); // Requiredpragmatic.AddConsole();}); -
Is
Enabledset tofalse? Checkappsettings.jsonfor"PragmaticLogging": { "Enabled": false }. -
Is the MinimumLevel too high? If MinimumLevel is
Warning, allInformationandDebugcalls are silently dropped. Check both the preset and any overrides. -
Did you add at least one provider? Calling
AddPragmaticLogging()alone registers the pipeline but no output. You need at least one provider (.AddConsole(),.AddFile(...), etc.). -
Are category-level overrides filtering your logger? Check
appsettings.jsonfor"LogLevel"overrides in the"Logging"section that might set your namespace toNone.
Duplicate Log Entries
Section titled “Duplicate Log Entries”Every log message appears twice in the console.
You have both the default .NET console provider and PragmaticConsoleProvider registered.
Call ClearProviders() before adding Pragmatic:
builder.Services.AddLogging(logging =>{ logging.ClearProviders(); var pragmatic = logging.AddPragmaticLogging(); pragmatic.AddConsole();});Context Properties Not Appearing in Log Output
Section titled “Context Properties Not Appearing in Log Output”You enabled enrichment but log entries do not contain CorrelationId, UserId, or other context properties.
Checklist
Section titled “Checklist”-
Is the enrichment middleware registered? Add it early in the pipeline:
app.UseMiddleware<LoggingEnrichmentMiddleware>(); -
Is the middleware ordered correctly? It must run before your handlers. Place it before
UseAuthentication()andMapControllers(). -
Is context enrichment enabled in options?
pragmatic.Configure(opts =>{opts.Context.IncludeCorrelationId = true;opts.Context.IncludeUserContext = true;opts.Context.IncludeMachineContext = true;}); -
Is the provider filtering context? Check if a
ContextFilterConfigurationwithMode = ContextFilterMode.Noneis set on the specific provider. -
For UserId: is the user authenticated? The
HttpContextProviderextracts UserId from theNameIdentifierclaim. If the request is unauthenticated,UserIdwill not appear.
Redaction Not Working
Section titled “Redaction Not Working”Sensitive data appears in log output despite enabling redaction.
Checklist
Section titled “Checklist”-
Is global redaction enabled? The global flag is the master switch:
pragmatic.Configure(opts => opts.Privacy.EnableRedaction = true); -
Is the property name in the sensitive list? Check that your property name matches (case-insensitive) or matches a regex pattern:
pragmatic.EnableDataRedaction(r =>{r.SensitivePropertyNames = ["password", "apiKey", "email"];r.PropertyNamePatterns = [@".*password.*", @".*secret.*"];}); -
For secret detection: is it enabled separately? Secret detection and data redaction are independent features:
pragmatic.Configure(opts =>{opts.Privacy.EnableRedaction = true; // Data redactionopts.Privacy.EnableSecretDetection = true; // Secret detection}); -
Is the confidence threshold too high? The default is 0.7. If your secrets are not being detected, lower the threshold or use
CreateForDevelopment()preset (0.5). -
Are you using a compliance preset? Compliance presets automatically configure both redaction and detection:
pragmatic.UseCompliancePreset(ComplianceStandard.Gdpr);
File Provider Not Writing
Section titled “File Provider Not Writing”The file provider is configured but no log files appear on disk.
Checklist
Section titled “Checklist”-
Does the directory exist? The file provider creates the file but not the parent directory. Ensure the
logs/directory (or your configured path) exists. -
Does the process have write permissions? Check file system permissions for the application’s service account.
-
Is the file path template valid? Placeholders are case-sensitive:
{Date},{Year},{Month},{Day},{Hour},{DateTime}. -
Is background processing blocking? If
UseBackgroundProcessingis enabled and the application shuts down before the queue is flushed, entries may be lost. Check thatIHostApplicationLifetimeis properly wired for graceful shutdown. -
Is the file locked by another process? Another instance of the application or a log viewer may have the file locked. Check with your file system.
Rate Limiting Dropping Important Messages
Section titled “Rate Limiting Dropping Important Messages”Critical error messages are being dropped by the rate limiter.
Rate limiting applies to all log levels equally by default.
Configure rate limiting with appropriate thresholds, or apply it only to specific levels:
pragmatic.EnableRateLimiting(rl =>{ rl.MaxMessagesPerSecond = 1000; rl.BurstSize = 100; rl.Strategy = "TokenBucket";});
// Or use built-in presets that only limit lower-priority levels// Error and Critical are typically exempt from rate limitingFor compliance scenarios, disable rate limiting entirely and rely on the bounded queue with Block overflow strategy instead.
High Memory Usage from Logging
Section titled “High Memory Usage from Logging”The application’s memory footprint grows over time due to logging.
Checklist
Section titled “Checklist”-
Is the Memory provider accumulating entries?
PragmaticMemoryProviderstores entries in-memory. CheckMaxEntriesand ensureAutoTruncateis enabled. -
Is the background queue growing unbounded? If using
QueueOverflowStrategy.Expand, the queue grows without limit. Switch toDropOldestor set a reasonableMaxQueueSize. -
Are
StringBuilderinstances leaking? This should not happen withStringBuilderPool, but if you are usingStringBuilderPool.Rent()directly, ensure everyRent()has a matchingReturn()in afinallyblock. -
Is zero-allocation mode enabled? Enable it to reduce GC pressure:
pragmatic.Configure(opts => opts.Performance.EnableZeroAllocation = true);
Slow Application Startup with PrecompilePatterns
Section titled “Slow Application Startup with PrecompilePatterns”Application startup takes several seconds when secret detection is enabled.
PrecompilePatterns = true compiles all regex patterns at startup. With the full pattern library, this can take 1-2 seconds.
For development, disable precompilation:
pragmatic.Configure(opts =>{ opts.Privacy.SecretDetection.PrecompilePatterns = false;});For production, accept the startup cost (patterns are compiled once) or limit the number of patterns:
pragmatic.Configure(opts =>{ opts.Privacy.SecretDetection.PrecompilePatterns = true; opts.Privacy.SecretDetection.MaxPatternsPerScan = 20; // Fewer patterns, faster startup});Can I use Pragmatic.Logging with Serilog or NLog?
Section titled “Can I use Pragmatic.Logging with Serilog or NLog?”Yes, but there is no benefit. Pragmatic.Logging replaces these libraries entirely. It registers as an ILoggerProvider in the standard .NET logging infrastructure. If you add both Pragmatic and Serilog providers, log entries will be processed by both pipelines independently.
Does Pragmatic.Logging support OpenTelemetry?
Section titled “Does Pragmatic.Logging support OpenTelemetry?”The CorrelationIdProvider integrates with Activity.Current and propagates W3C traceparent headers. The BaggagePropagationMiddleware forwards context values to downstream services. OpenTelemetry exporters can consume these traces.
Can I use different redaction settings per provider?
Section titled “Can I use different redaction settings per provider?”Yes. Each provider has its own PrivacyConfiguration. Enable global redaction, then configure per-provider RedactionMode:
// Aggressive redaction for file logspragmatic.AddFile("logs/app.log", c => c.Privacy.RedactionMode = RedactionMode.Aggressive);
// No redaction for memory provider (testing)pragmatic.AddMemory(); // Uses default privacy settingsHow do I test that redaction is working?
Section titled “How do I test that redaction is working?”Use the PragmaticMemoryProvider with redaction enabled and assert on the stored entries:
var memoryProvider = serviceProvider.GetRequiredService<PragmaticMemoryProvider>();var entries = memoryProvider.GetLogEntriesContaining("[REDACTED]");entries.Should().NotBeEmpty();What is the BootstrapLogger for?
Section titled “What is the BootstrapLogger for?”The BootstrapLogger provides logging before the DI container is built. Use it for startup diagnostics:
using var bootstrap = BootstrapLogger.Create();bootstrap.LogInformation("Loading configuration...");It writes to the console and is disposed when the full logging pipeline takes over.
Getting Help
Section titled “Getting Help”- Check the concepts guide for architecture overview
- Check the getting started guide for setup instructions
- Review Benchmark Results for performance comparisons
- Open an issue on the Pragmatic.Design repository with:
- Your
PragmaticLoggingBuilderconfiguration code - The
PragmaticLoggingsection fromappsettings.json - The expected vs actual behavior
- .NET version and OS
- Your