Skip to content

Pragmatic.Logging -- Getting Started

This guide covers installation, basic setup, privacy configuration, and common usage patterns.

Terminal window
dotnet add package Pragmatic.Logging

Pragmatic.Logging plugs into the standard ILoggingBuilder pipeline. Call AddPragmaticLogging() to get a PragmaticLoggingBuilder:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLogging(logging =>
{
logging.ClearProviders(); // Remove default console provider
var pragmatic = logging.AddPragmaticLogging();
pragmatic
.UseDevelopmentPreset()
.AddConsole();
});

Or use the callback overload:

builder.Services.AddLogging(logging =>
{
logging.AddPragmaticLogging(pragmatic =>
{
pragmatic
.UseProductionPreset()
.AddConsole()
.AddFile("logs/app-{Date}.log");
});
});

Presets configure sensible defaults for common scenarios. You can override individual settings after applying a preset.

PresetMethodBest For
DevelopmentUseDevelopmentPreset()Local development. Verbose, no redaction.
ProductionUseProductionPreset()Production deployments. Rate limiting, correlation IDs.
High PerformanceUseHighPerformancePreset()High-throughput services. Zero-allocation, batched writes.
ComplianceUseCompliancePreset(standard)Regulated environments. Redaction, audit trail.
// Override specific settings after a preset
pragmatic
.UseProductionPreset()
.Configure(opts => opts.MinimumLevel = LogLevel.Debug); // Override minimum level

Providers determine where log output goes. Add as many as needed:

pragmatic
.AddConsole(opts =>
{
opts.UseColors = true;
opts.IncludeStructuredData = true;
opts.OutputFormat = "Structured";
})
.AddFile("logs/app-{Date}.log", opts =>
{
opts.MaxFileSizeMB = 100;
opts.CompressOldFiles = true;
opts.RetentionDays = 30;
})
.AddJson(Console.OpenStandardOutput(), opts =>
{
opts.WriteIndented = false;
opts.NamingPolicy = "CamelCase";
})
.AddMemory(); // For testing

The file provider supports template-based naming with automatic rolling:

"logs/app-{Date}.log" -> app-2026-03-21.log
"logs/{Year}/{Month}/app-{Day}.log" -> logs/2026/03/app-21.log
"logs/app-{DateTime}.log" -> app-2026-03-21-14-30-25.log
"logs/app-{Hour}.log" -> app-14.log

Rolling intervals: Hour, Day, Week, Month, Year, None.

After registration, inject and use ILogger<T> as usual. Pragmatic.Logging handles enrichment, redaction, and routing to providers behind the scenes.

public class OrderService(ILogger<OrderService> logger)
{
public void ProcessOrder(int orderId)
{
logger.LogInformation("Processing order {OrderId}", orderId);
}
}

Secret detection scans log content for API keys, tokens, connection strings, and other sensitive data:

pragmatic.Configure(opts =>
{
opts.Privacy.EnableSecretDetection = true;
opts.Privacy.SecretDetection.PrecompilePatterns = true;
opts.Privacy.SecretDetection.MinimumConfidenceForRedaction = 0.7;
});

Data redaction replaces sensitive values in log output:

pragmatic.EnableDataRedaction(redaction =>
{
redaction.RedactionPlaceholder = "[REDACTED]";
redaction.SensitivePropertyNames = ["password", "apiKey", "connectionString"];
redaction.PropertyNamePatterns = [@".*secret.*", @".*token.*"];
redaction.MessageRedactionPatterns = [@"[\w.+-]+@[\w-]+\.[\w.]+"]; // Email
});

For regulated environments, use a compliance preset that configures both detection and redaction:

// GDPR: complete redaction, high confidence, audit trail
pragmatic.UseCompliancePreset(ComplianceStandard.Gdpr);
// HIPAA: very high confidence threshold
pragmatic.UseCompliancePreset(ComplianceStandard.Hipaa);
// PCI-DSS: maximum confidence threshold
pragmatic.UseCompliancePreset(ComplianceStandard.PciDss);

Add the enrichment middleware to automatically attach context properties to every log entry:

var app = builder.Build();
app.UseMiddleware<LoggingEnrichmentMiddleware>();

This adds: CorrelationId, RequestPath, RequestMethod, UserId (from claims), MachineName, ProcessId.

For logging before the DI container is built (e.g., during startup configuration):

using var bootstrap = BootstrapLogger.Create();
bootstrap.LogInformation("Starting application...");
var builder = WebApplication.CreateBuilder(args);
// ... configure services ...

Prevent log spam in noisy scenarios:

pragmatic.EnableRateLimiting(rl =>
{
rl.MaxMessagesPerSecond = 1000;
rl.BurstSize = 100;
rl.Strategy = "TokenBucket"; // Also: FixedWindow, SlidingWindow
});

Enable audit trail for compliance requirements:

pragmatic.EnableAuditTrail(audit =>
{
audit.StorageType = "FileSystem"; // FileSystem, Database, Memory
audit.PolicyType = "GDPR";
audit.BatchSize = 100;
audit.FlushIntervalSeconds = 30;
});

All options bind to the PragmaticLogging configuration section:

{
"PragmaticLogging": {
"Enabled": true,
"MinimumLevel": "Information",
"Privacy": {
"EnableRedaction": true,
"EnableSecretDetection": true
},
"Providers": {
"Console": { "Enabled": true, "UseColors": true },
"File": { "Enabled": true, "BasePath": "./logs" }
}
}
}

Implement IPragmaticLoggerProvider and register via the builder:

pragmatic.AddProvider<MyCustomProvider>(sp =>
{
var config = PragmaticProviderConfiguration.CreateDefault();
return new MyCustomProvider("custom", config);
});