PrimusSaaS.Logging
1.7.2
dotnet add package PrimusSaaS.Logging --version 1.7.2
NuGet\Install-Package PrimusSaaS.Logging -Version 1.7.2
<PackageReference Include="PrimusSaaS.Logging" Version="1.7.2" />
<PackageVersion Include="PrimusSaaS.Logging" Version="1.7.2" />
<PackageReference Include="PrimusSaaS.Logging" />
paket add PrimusSaaS.Logging --version 1.7.2
#r "nuget: PrimusSaaS.Logging, 1.7.2"
#:package PrimusSaaS.Logging@1.7.2
#addin nuget:?package=PrimusSaaS.Logging&version=1.7.2
#tool nuget:?package=PrimusSaaS.Logging&version=1.7.2
PrimusSaaS.Logging - Enterprise Logging for .NET
Package version: 1.5.0
Target Frameworks: net8.0 | net9.0 | net10.0
Enterprise-grade structured logging library for .NET applications with automatic context enrichment, PII masking, audit logging, environment-aware defaults, AWS X-Ray tracing, CloudWatch metrics, and multiple output targets.
Recommendation: For vendor-neutral metrics and distributed tracing (OpenTelemetry), use the new PrimusSaaS.Observability module. Use this package (PrimusSaaS.Logging) if you specifically require local PII masking or custom file rotation sinks.
Features
- Structured Logging - JSON-formatted logs with rich context
- Log Levels - DEBUG, INFO, WARNING, ERROR, CRITICAL
- Multiple Targets - Console, File, Azure Application Insights, CloudWatch
- PII Masking - Automatic redaction of sensitive data (regex + key-name + attribute-based)
[SensitiveData]Attribute - Decorate properties for automatic redaction when logged- File Rotation - Size-based rotation with gzip compression
- Async Buffering - High-performance non-blocking logging
- Custom Enrichers - Add dynamic context to every log
- Standard ILogger - Full compatibility with Microsoft.Extensions.Logging
- Serilog/NLog Bridge - Forward enriched logs into existing sink ecosystems
- ASP.NET Core Integration - Middleware for automatic HTTP context enrichment
- Audit Logging - Dedicated tamper-evident audit pipeline with typed schemas and schema versioning
- BackgroundService Lifecycle - Structured start/stop/iteration logging for workers
- Test Helpers -
FakeAuditLogger,TestLogCapture,LogAssertionsfor consumer tests - Log Level Hot-Reload - Runtime
MinLevelchanges viaIOptionsMonitor<LoggerOptions>(v1.4.0+) - PHI/Financial Masking - HIPAA (ICD-10/ICD-11) and ERISA compliance masking (v1.4.0+)
- Environment-Aware Defaults - Auto-configures Development/Staging/Production settings (v1.5.0+)
- AWS X-Ray Integration - Segment helpers, fault recording, X-Ray/W3C trace ID conversion (v1.5.0+)
- CloudWatch Metrics - Embedded Metric Format (EMF) bridge for System.Diagnostics.Metrics (v1.5.0+)
- Routing Telemetry - Typed models for orchestrator routing and dispatch decisions (v1.5.0+)
- SourceLink + Deterministic Builds - Step into SDK source during debugging (v1.5.0+)
Installation
dotnet add package PrimusSaaS.Logging --version 1.5.0
For CloudWatch integration:
dotnet add package PrimusSaaS.Logging.CloudWatch --version 1.5.0
Quick Start
Register Services
using PrimusSaaS.Logging.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddPrimus(builder.Configuration.GetSection("PrimusLogging"));
var app = builder.Build();
app.UsePrimusLogging();
app.Run();
[SensitiveData] Attribute
Decorate model properties with [SensitiveData] to automatically redact them when logged in context dictionaries. No need to register key names manually.
using PrimusSaaS.Logging.Core;
public class UserProfile
{
public string Name { get; set; }
[SensitiveData]
public string Email { get; set; }
[SensitiveData("Financial")]
public string TaxId { get; set; }
}
// When logged:
logger.Info("Profile loaded", new Dictionary<string, object?>
{
["user"] = profile // Email and TaxId are automatically redacted
});
Attribute-based redaction is enabled by default. Disable via PiiOptions.EnableAttributeBasedRedaction = false.
Typed Audit Entries
Use the AuditEntries factory for structured, category-specific audit events:
using PrimusSaaS.Logging.Audit;
// Data access audit
auditLogger.Log(AuditEntries.DataAccess("user-1", "Read", "Orders:123", durationMs: 45.2));
// Security audit
auditLogger.Log(AuditEntries.Security("user-1", "Login", AuditOutcome.Failure,
ipAddress: "10.0.0.1", reason: "Invalid password"));
// Governance audit (AI/compliance decisions)
auditLogger.Log(AuditEntries.Governance("system", "PolicyEvaluation", "GDPR-Consent",
confidenceScore: 0.95, reasoning: "User consent verified"));
// Configuration change audit
auditLogger.Log(AuditEntries.ConfigurationChange("admin-1", "MaxRetries",
oldValue: "3", newValue: "5"));
// Lifecycle audit
auditLogger.Log(AuditEntries.Lifecycle("user-1", "Deleted", "Order", "ORD-123"));
Available categories: DataAccess, Security, Governance, ConfigurationChange, Lifecycle.
CloudWatch Audit Routing
Route audit entries to a separate CloudWatch log group:
using PrimusSaaS.Logging.CloudWatch;
builder.Logging.AddPrimus(options =>
{
options.ApplicationId = "my-app";
// Operational logs go to one log group
options.AddCloudWatchTarget(cw =>
{
cw.LogGroupName = "/app/my-app/logs";
cw.Region = "us-east-1";
});
// Audit entries go to a separate log group
options.AddCloudWatchAuditTarget(cw =>
{
cw.LogGroupName = "/app/my-app/audit";
cw.Region = "us-east-1";
});
});
BackgroundService Lifecycle Logging
Extend PrimusBackgroundService to get automatic structured logging for worker services:
using PrimusSaaS.Logging.Extensions;
using PrimusSaaS.Logging.Core;
public class OrderSyncWorker : PrimusBackgroundService
{
public OrderSyncWorker(Logger logger) : base(logger, "OrderSyncWorker") { }
protected override TimeSpan IterationDelay => TimeSpan.FromMinutes(5);
protected override async Task ExecuteIterationAsync(CancellationToken ct)
{
// Your worker logic here - lifecycle is logged automatically:
// Starting, IterationCompleted (with duration), IterationFailed, Stopped
await SyncOrdersAsync(ct);
}
protected override Task<bool> OnIterationErrorAsync(
Exception ex, long iterationCount, CancellationToken ct)
{
// Return false to stop the service on error, true to continue (default: true)
return Task.FromResult(iterationCount < 10);
}
}
Test Helpers
Ship with the NuGet package for consumer test convenience:
using PrimusSaaS.Logging.Testing;
using PrimusSaaS.Logging.Audit;
// FakeAuditLogger - captures audit entries in-memory
var fakeAudit = new FakeAuditLogger();
// ... inject into code under test ...
Assert.True(fakeAudit.HasEvent("UserLogin"));
Assert.Equal(2, fakeAudit.GetEvents("UserLogin").Count);
// TestLogCapture - captures log entries
var capture = new TestLogCapture();
var logger = new Logger(new LoggerOptions
{
ApplicationId = "test-app",
CustomTargets = new List<ITarget> { capture }
});
logger.Info("Hello");
Assert.True(capture.HasMessage("Hello"));
// LogAssertions - fluent assertion helpers
LogAssertions.AssertLogContains(capture, "Hello");
LogAssertions.AssertLogDoesNotContain(capture, "secret");
LogAssertions.AssertNoPii(capture); // Smoke test for unmasked emails/SSNs
LogAssertions.AssertAuditRecorded(fakeAudit, "UserLogin");
LogAssertions.AssertAuditRecorded(fakeAudit, "UserLogin", AuditOutcome.Success);
LogAssertions.AssertAuditCount(fakeAudit, 3);
Environment-Aware Defaults (v1.5.0+)
Pass IHostEnvironment to automatically apply environment-specific defaults:
using PrimusSaaS.Logging.Extensions;
builder.Services.AddPrimusLogging(builder.Environment);
| Setting | Development | Staging | Production |
|---|---|---|---|
| MinLevel | Debug | Info | Warning |
| Console Pretty | true | - | false (JSON) |
| PII Masking | Opt-in | Strict (all on) | Strict + MaskIPs |
| Sampling | Disabled | Enabled | Enabled |
AWS X-Ray Integration (v1.5.0+)
Start properly annotated Activities that appear as segments in AWS X-Ray:
using PrimusSaaS.Logging.Tracing;
// Start an X-Ray segment with tenant context
using var activity = XRayIntegration.StartXRaySegment("ProcessOrder", tenantId: "tenant-42");
try
{
await ProcessOrderAsync();
}
catch (Exception ex)
{
XRayIntegration.RecordFault(activity, ex);
throw;
}
Convert between X-Ray and W3C trace ID formats:
// X-Ray → W3C
var w3cId = XRayIntegration.ConvertXRayToW3CTraceId("1-5759e988-bd862e3fe1be46a994272793");
// W3C → X-Ray
var xrayId = XRayIntegration.ConvertW3CToXRayTraceId("5759e988bd862e3fe1be46a994272793");
CloudWatch Metrics (v1.5.0+)
Bridge System.Diagnostics.Metrics to CloudWatch via Embedded Metric Format (EMF):
using PrimusSaaS.Logging.CloudWatch;
var publisher = CloudWatchExtensions.CreateMetricsPublisher(options =>
{
options.MetricsLogGroupName = "/app/my-app/metrics";
options.MetricsNamespace = "MyApp/Primus";
options.FlushIntervalMs = 60_000; // 1 minute
});
// Metrics are automatically collected from PrimusActivitySource:
// - primus.requests_processed (Counter)
// - primus.errors_logged (Counter)
// - primus.request_duration (Histogram)
Routing Telemetry (v1.5.0+)
Typed models for orchestrator routing and dispatch telemetry:
using PrimusSaaS.Logging.Telemetry;
// Routing decision telemetry
var routing = new RoutingTelemetryRecord("trace-123", "tenant-42", "evt-001", "Routed")
{
Reason = "Matched claims domain",
CompletedAt = DateTime.UtcNow
};
auditLogger.LogRoutingTelemetry(routing);
// Dispatch telemetry with confidence scores
var dispatch = new RoutingDispatchTelemetry(
"trace-123", "agent-benefits", "tenant-42",
new[] { "Claims", "Benefits" },
new Dictionary<string, double> { ["Claims"] = 0.95, ["Benefits"] = 0.87 })
{
Status = "Completed",
DurationMs = 142.5
};
auditLogger.LogDispatchTelemetry(dispatch);
Performance
- Async Buffering: Non-blocking writes with configurable buffer size.
- Thread-Safe: Lock-free reads, minimal contention.
- Attribute Cache:
[SensitiveData]reflection results are cached per-type for zero-allocation lookups after first use. - Compression: Gzip reduces storage by ~70%.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.ApplicationInsights.AspNetCore (>= 2.21.0)
- NLog (>= 5.2.8)
- Serilog (>= 2.12.0)
- StackExchange.Redis (>= 2.8.24)
- System.Drawing.Common (>= 8.0.0)
-
net8.0
- Microsoft.ApplicationInsights.AspNetCore (>= 2.21.0)
- NLog (>= 5.2.8)
- Serilog (>= 2.12.0)
- StackExchange.Redis (>= 2.8.24)
- System.Drawing.Common (>= 8.0.0)
-
net9.0
- Microsoft.ApplicationInsights.AspNetCore (>= 2.21.0)
- NLog (>= 5.2.8)
- Serilog (>= 2.12.0)
- StackExchange.Redis (>= 2.8.24)
- System.Drawing.Common (>= 8.0.0)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on PrimusSaaS.Logging:
| Package | Downloads |
|---|---|
|
PrimusSaaS.Logging.CloudWatch
AWS CloudWatch Logs target for PrimusSaaS.Logging. Enables structured log delivery to CloudWatch with automatic log group/stream management and batched writes. |
|
|
PrimusSaaS.Logging.GrafanaLoki
Grafana Loki push target for PrimusSaaS.Logging. Delivers structured, PII-masked log entries to Loki via the HTTP push API with label-based streaming, batching and retry support. |
|
|
PrimusSaaS.Logging.Splunk
Splunk HTTP Event Collector (HEC) target for PrimusSaaS.Logging. Delivers structured, PII-masked log entries to Splunk via HEC with batching and retry support. |
|
|
PrimusSaaS.Logging.Datadog
Datadog Logs Intake target for PrimusSaaS.Logging. Delivers structured, PII-masked log entries to Datadog via the HTTP Logs Intake API with batching and retry support. |
|
|
PrimusSaaS.Logging.GcpCloudLogging
Google Cloud Logging target for PrimusSaaS.Logging. Delivers structured, PII-masked log entries to GCP Cloud Logging via the REST API v2 with batching and retry support. Supports service-account JSON credentials or Application Default Credentials. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.7.2 — NEW: AwsXRayTraceHeader helper in PrimusSaaS.Logging.Tracing for producing/parsing the AWS X-Ray "AWSTraceHeader" wire format (Root=...;Parent=...;Sampled=...). Lets SQS/SNS/Lambda publishers stitch traces into the X-Ray service map without taking an AWSSDK or OpenTelemetry dependency in the core package. Includes Format(traceId), FromActivity(Activity), and TryParse(header, ...) with full round-trip tests.
v1.7.1 — Maintenance: documentation and packaging updates.
v1.7.0 — W3C traceparent propagation in LoggingMiddleware: inbound traceparent/tracestate headers are now parsed and restored into .NET Activity infrastructure, enabling full distributed trace stitching across services in CloudWatch, X-Ray, and Jaeger.
v1.6.0 — Pluggable PII strategy interface (IPiiStrategy) for custom masking/tokenization;
v1.5.0:
- NEW: Environment-aware defaults — AddPrimusLogging(IHostEnvironment) auto-configures for Development/Staging/Production.
- NEW: RoutingTelemetryRecord and RoutingDispatchTelemetry typed schema models matching orchestrator contract schemas.
- NEW: TelemetryLoggerExtensions — LogRoutingTelemetry() and LogDispatchTelemetry() for audit-logged telemetry.
- NEW: XRayIntegration helper — StartXRaySegment(), RecordFault(), X-Ray↔W3C trace ID conversion, ADOT bridge documentation.
- NEW: CloudWatchMetricsPublisher — bridges System.Diagnostics.Metrics to CloudWatch via Embedded Metric Format (EMF).
- NEW: Additional PrimusActivitySource metrics — requests_processed, errors_logged, request_duration counters/histograms.
- NEW: SourceLink + deterministic builds for both PrimusSaaS.Logging and PrimusSaaS.Logging.CloudWatch.
- NEW: XML documentation file generation enabled in NuGet packages.
- INFRA: CloudWatch package version aligned to 1.5.0.
- TESTS: 45 new production completion tests — 186/186 passing.
v1.4.0:
- NEW: Log level hot-reload via IOptionsMonitor — change MinLevel at runtime without restart.
- NEW: WardenAuditRecord typed model + LogWardenValidation() extension for AI governance compliance.
- NEW: AcpEnvelopeAuditRecord typed model + LogAcpEnvelope() extension for agent communication traceability.
- NEW: AuditEntry.SchemaVersion field ("1.0") for compliance audit schema evolution.
- NEW: PHI diagnosis code masking (MaskDiagnosisCodes, default: true) — ICD-10/ICD-11 patterns.
- NEW: Financial account masking (MaskFinancialAccounts, default: false) — ERISA compliance.
- NEW: CloudWatch 256KB entry size guard with automatic truncation.
- NEW: ILogger<T> extensions for LogQueryPerformance() and BeginEventScope().
- TESTS: 21 new production compliance tests — 141/141 passing.
v1.3.0:
- NEW: [SensitiveData] attribute for automatic property-level PII redaction on logged objects.
- NEW: Typed audit entries via AuditEntries factory (DataAccess, Security, Governance, ConfigurationChange, Lifecycle).
- NEW: CloudWatch audit routing — AddCloudWatchAuditTarget() for separate audit log groups.
- NEW: PrimusBackgroundService base class for structured worker lifecycle logging.
- NEW: Consumer test helpers — FakeAuditLogger, TestLogCapture, LogAssertions shipped in NuGet.
- NEW: AuditTargetOptions.CustomTargets for injecting custom audit targets (e.g., CloudWatch).
- NEW: PiiOptions.EnableAttributeBasedRedaction toggle (default: true).
- TESTS: 25 new tests covering all gap closure features — 120/120 passing.
v1.2.6:
- SECURITY: Added phone number masking (MaskPhones, default: true).
- SECURITY: Added IP address masking (MaskIPs, default: false — opt in for GDPR).
- SECURITY: Pinned System.Drawing.Common 8.0.0+ to eliminate NU1904 CVE warning.
- FIX: LogAuditAsync() extension now works on ILogger<T> and ILogger (not just internal Logger type).
- FIX: LogAuditExtensions namespace changed to PrimusSaaS.Logging.Extensions — matches the using statement in all docs.
- DOCS: Console guide updated — documented dual-output format for Pretty:true.
- DOCS: All version references updated to 1.2.6 across all doc pages.
- DOCS: Fixed TargetOptions → TargetConfig in troubleshooting.md code sample.
- TESTS: 6 new unit tests for phone/IP masking — 45/45 passing.
v1.2.5:
- DOCS: Fixed missing DI registration example in console guide (OrderService not wired).
- DOCS: Fixed sampling config — added appsettings.json approach alongside code approach.
- DOCS: Fixed enrichers section — clarified both using statements required.
- DOCS: Removed duplicate Next Steps section in overview.
v1.2.4:
- E2E tested: All endpoint tests passing with structured logging, correlation IDs, and PII masking.
- Verified API accuracy: UsePrimusLogging, LogLevel integration, async buffering.
- Production-ready with comprehensive copy-paste code samples.
v1.2.3:
- DOCS: Comprehensive documentation update with accurate implementation examples and best practices.
- Improved developer experience with clear migration guides and copy-paste ready samples.
v1.2.2: Resolved duplicate UsePrimusLogging extension ambiguity; safe serialization; scopes + correlation IDs; async buffering with metrics.