Advanced Features
Enhance your logging with PII masking, correlation IDs, enrichers, and sampling.
PII Masking
Automatically mask sensitive data in your logs:
{
"PrimusLogging": {
"ApplicationId": "MyService",
"Targets": [
{ "Type": "console", "Pretty": true }
],
"Pii": {
"MaskEmails": true,
"MaskCreditCards": true,
"MaskSSN": true,
"MaskPasswords": true,
"MaskTokens": true,
"MaskSecrets": true
}
}
}
Result:
| Original | Masked |
|---|---|
user@example.com | u***@***.com |
4111111111111111 | ************1111 |
123-45-6789 | ***-**-**** |
Custom PII Patterns
Mask custom sensitive data:
{
"Pii": {
"MaskEmails": true,
"CustomSensitiveKeys": ["apiKey", "secret"],
"CustomRegexPatterns": ["ORD-\\d{8}"]
}
}
Correlation IDs
The UsePrimusLogging() middleware automatically:
- Generates a unique
X-Correlation-IDfor each request - Adds the correlation ID to all log entries
- Returns the header in responses for tracing
var app = builder.Build();
app.UsePrimusLogging(); // Enables correlation IDs
Custom Enrichers
Add context to every log entry. Built-in enrichers: PropertyEnricher, MachineNameEnricher, ThreadIdEnricher.
// At the top of Program.cs — you need BOTH usings
using PrimusSaaS.Logging.Core; // for enricher classes
using PrimusSaaS.Logging.Extensions; // for AddPrimus()
builder.Logging.AddPrimus(opts =>
{
builder.Configuration.GetSection("PrimusLogging").Bind(opts);
// Static properties
opts.Enrichers.Add(new PropertyEnricher("Application", "OrderService"));
opts.Enrichers.Add(new PropertyEnricher("Environment", builder.Environment.EnvironmentName));
// Machine/thread info
opts.Enrichers.Add(new MachineNameEnricher());
opts.Enrichers.Add(new ThreadIdEnricher());
});
All three enricher classes live in the
PrimusSaaS.Logging.Corenamespace. Without thisusing, the compiler will not find them.
Sampling
Reduce log volume in high-traffic scenarios.
Option A — via appsettings.json (recommended):
{
"PrimusLogging": {
"Sampling": {
"Enabled": true,
"SampleRate": 0.10,
"AlwaysLogOnError": true
}
}
}
Option B — via code:
builder.Logging.AddPrimus(opts =>
{
builder.Configuration.GetSection("PrimusLogging").Bind(opts);
opts.SamplingRate = 0.10; // Keep 10% of low-importance logs
opts.AlwaysLogOnError = true; // Never sample out errors
});
is a convenience shortcut — setting it to automatically enables sampling with a 10% rate. ensures errors are never dropped.
Multiple Targets
Send logs to multiple destinations:
{
"PrimusLogging": {
"ApplicationId": "MyService",
"Environment": "Production",
"MinLevel": 1,
"Targets": [
{ "Type": "console", "Pretty": true },
{ "Type": "file", "Path": "logs/app.log" },
{ "Type": "applicationInsights", "ConnectionString": "..." }
],
"Pii": {
"MaskEmails": true,
"MaskCreditCards": true
}
}
}
Category Truncation
Shorten long category names:
builder.Logging.AddPrimus(opts =>
{
builder.Configuration.GetSection("PrimusLogging").Bind(opts);
opts.TruncateCategoryNames = true;
opts.MaxCategoryLength = 40; // Default: 120
});
Structured Logging Tips
-
Use message templates with named properties:
_logger.LogInformation("Order {OrderId} placed by {UserId}", orderId, userId); -
Use scopes for request-specific context:
using (_logger.BeginScope(new Dictionary<string, object> { { "OrderId", order.Id } }))
{
_logger.LogInformation("Processing order");
} -
Pass exceptions as the first parameter:
_logger.LogError(ex, "Payment failed for {OrderId}", order.Id);