Cerbi.Serilog.GovernanceAnalyzer
1.5.0
dotnet add package Cerbi.Serilog.GovernanceAnalyzer --version 1.5.0
NuGet\Install-Package Cerbi.Serilog.GovernanceAnalyzer -Version 1.5.0
<PackageReference Include="Cerbi.Serilog.GovernanceAnalyzer" Version="1.5.0" />
<PackageVersion Include="Cerbi.Serilog.GovernanceAnalyzer" Version="1.5.0" />
<PackageReference Include="Cerbi.Serilog.GovernanceAnalyzer" />
paket add Cerbi.Serilog.GovernanceAnalyzer --version 1.5.0
#r "nuget: Cerbi.Serilog.GovernanceAnalyzer, 1.5.0"
#:package Cerbi.Serilog.GovernanceAnalyzer@1.5.0
#addin nuget:?package=Cerbi.Serilog.GovernanceAnalyzer&version=1.5.0
#tool nuget:?package=Cerbi.Serilog.GovernanceAnalyzer&version=1.5.0
Cerbi.Serilog.Governance
Real-time governance enforcement for Serilog using Cerbi — the structured logging validator for .NET.
Requirements
- .NET 9.0 or higher (also compatible with .NET 8.0+)
- Serilog 4.x
Features
- Block non-compliant log events (required / forbidden fields, enum validation)
- Optional enrichment with governance metadata (profile, violations, relaxed flag)
- TagOnlyMode for non-blocking observability
- Works with any Serilog sinks + other enrichers/filters
- Relax() bypass tagging (still observable)
- Queue-first score shipping with Azure Service Bus + HTTP fallback
- High-throughput score shipping with batching, retry logic, and ArrayPool optimizations
Performance Characteristics
Throughput Modes
Standard Mode (Default)
- Validates + enriches: ~50K-100K events/sec
- Score shipping: 100-1K events/sec
- Suitable for: Most production workloads
High-Throughput Mode
- Validates + enriches: ~100K-200K events/sec
- Score shipping: 10K-50K events/sec
- Optimizations: ArrayPool, reduced allocations, aggressive batching
- Suitable for: High-volume APIs, streaming services
Optimization Techniques
The library uses several performance optimizations:
- Lock-free enqueuing via ConcurrentQueue
- ArrayPool<T> for batch collection (zero allocations)
- Batch serialization - serialize once, retry with same payload
- Background worker - non-blocking score shipping
- ConfigureAwait(false) throughout async paths
- AggressiveInlining on hot path methods
Install
dotnet add package Cerbi.Serilog.Governance
Requires runtime packages (pulled transitively): Cerbi.Governance.Core, Cerbi.Governance.Runtime.
Config File (cerbi_governance.json)
{
"EnforcementMode": "Strict",
"LoggingProfiles": {
"Orders": {
"RequireTopic": false,
"AllowedTopics": ["Orders", "Users"],
"FieldSeverities": {
"userId": "Required",
"email": "Required",
"password": "Forbidden"
},
"FieldEnums": { "Status": ["Pending", "Approved", "Rejected"] },
"AllowRelax": true
}
}
}
One-Line Setup
using Cerbi.Serilog.Governance;
Log.Logger = new LoggerConfiguration()
.CerbiGovernance(o =>
{
o.Profile = "Orders"; // profile key
o.ConfigPath = "cerbi_governance.json"; // path
// o.TagOnlyMode = true; // uncomment for no blocking
})
.WriteTo.Console()
.CreateLogger();
High-Throughput Configuration
For applications handling 10K+ events/second, configure aggressive batching and tuning:
Log.Logger = new LoggerConfiguration()
.CerbiGovernance(o =>
{
o.Profile = "Orders";
o.TagOnlyMode = true; // Recommended for high throughput
o.AppName = "HighThroughputAPI";
o.Environment = "Production";
// High-throughput score shipping settings
o.ScoreShipping = new ScoreShippingOptions
{
Enabled = true,
LicenseAllowsScoring = true,
Endpoint = "https://governance.cerbi.io/v1/scores",
ApiKey = "your-api-key",
// Optimized for high throughput
BatchSize = 250,
FlushInterval = TimeSpan.FromSeconds(1),
MaxQueueSize = 50_000,
MaxRetryAttempts = 2,
// Queue-first ingestion (Service Bus)
ServiceBusConnectionString = Environment.GetEnvironmentVariable("ScoringIngestion:AzureServiceBus:ConnectionString"),
ServiceBusQueueName = Environment.GetEnvironmentVariable("ScoringIngestion:AzureServiceBus:QueueName"),
DeliveryMode = ScoringDeliveryMode.QueueFirst
};
})
.WriteTo.Console()
.CreateLogger();
Queue-First Score Shipping
| Configuration Key | Description |
|---|---|
ScoringIngestion:AzureServiceBus:ConnectionString |
Full Service Bus connection string (Endpoint, SharedAccessKeyName, SharedAccessKey). |
ScoringIngestion:AzureServiceBus:QueueName |
Queue name if not provided via EntityPath. |
ScoringIngestion:Mode |
QueueFirst (default), QueueOnly, or HttpOnly. |
Behavior
- If Service Bus config is present → events are enqueued as
Cerbi.Contracts.Contracts.ScoringQueueEnvelopeDtowithScoringEventDtopayload. - If Service Bus is missing but HTTP Endpoint is configured → HTTP batching is used.
- If neither are configured → shipping is skipped with a
Serilog.Debugging.SelfLogwarning (the application keeps running).
Each Service Bus message includes:
MessageId=IdempotencyKeyif present, otherwise SHA-256 hash ofTenantId|AppName|LogId|Timestamp.CorrelationIdif available on the log event (CorrelationId,TraceId, or custom).ContentType=application/json(matchesScoringQueueEnvelopeDto).
Throughput Tuning Guide
| Scenario | BatchSize | FlushInterval | MaxQueueSize | MaxRetryAttempts |
|---|---|---|---|---|
| Low (< 1K/sec) | 50 | 5s | 10,000 | 3 |
| Medium (1K-10K/sec) | 100 | 2s | 25,000 | 2 |
| High (10K-50K/sec) | 250 | 1s | 50,000 | 2 |
| Extreme (> 50K/sec) | 500 | 500ms | 100,000 | 1 |
Memory Impact: Each queued event ≈ 200-500 bytes. MaxQueueSize=100K ≈ 20-50 MB.
Filtering Only
.Filter.WithCerbiGovernanceFiltering(o => { o.Profile = "Orders"; })
Enrichment Only
.Enrich.WithCerbiGovernanceTagging(o => { o.Profile = "Orders"; })
Relaxed Logging
Log.ForContext("userId", "abc123")
.Relax() // bypass enforcement, tagged GovernanceRelaxed=true
.Information("Non-compliant log allowed in relax mode");
TagOnlyMode
Use when you want visibility but no blocking (e.g. staging or high-throughput production):
o.TagOnlyMode = true;
Performance Note: TagOnlyMode is recommended for high-throughput scenarios to avoid blocking on the validation path.
Benchmarks
Run benchmarks to measure performance on your hardware:
dotnet run -c Release -p BenchmarkSuite1/BenchmarkSuite1.csproj
Typical results (AMD Ryzen 9 / Intel i9):
- Enricher (valid event): 500-800 ns/op
- Filter (valid event): 400-600 ns/op
- Filter (blocked event): 600-900 ns/op
Monitoring & Diagnostics
Queue Metrics
Monitor queue depth for health:
var healthCheck = new CerbiGovernanceHealth(scoreShipper);
var queueDepth = healthCheck.GetQueueDepth(); // Monitor this metric
Dropped Events
Events are dropped silently when MaxQueueSize is exceeded. Enable diagnostics to track:
using Serilog.Debugging;
SelfLog.Enable(msg => Console.WriteLine($"[Cerbi] {msg}"));
CI Version Override
Set VERSION env (Directory.Build.props maps it):
dotnet pack ClassLibrary1/Cerbi-Serilog-Governance.csproj -c Release -p:Version=1.2.15
Roadmap
- Caller type / [CerbiTopic] support when runtime exposes evaluation API
- Structured violation detail enrichment toggle
- Adaptive batching based on queue depth
Contributing
Open issues / PRs. Keep changes minimal & benchmark if performance related.
License
MIT
See Also
- CerbiStream (integrated governance API)
- Cerbi.Governance.Runtime (core validator)
| 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 was computed. 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
- Cerbi.Governance.Core (>= 2.2.29)
- Cerbi.Governance.Runtime (>= 2.0.23)
- Serilog (>= 4.3.1)
-
net8.0
- Cerbi.Governance.Core (>= 2.2.29)
- Cerbi.Governance.Runtime (>= 2.0.23)
- Serilog (>= 4.3.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.5.0 | 38 | 5/4/2026 |
| 1.4.59 | 53 | 5/3/2026 |
| 1.4.0 | 37 | 5/4/2026 |
| 1.3.58 | 86 | 4/29/2026 |
| 1.3.57 | 85 | 4/29/2026 |
| 1.3.56 | 80 | 4/29/2026 |
| 1.3.55 | 94 | 4/12/2026 |
| 1.3.54 | 88 | 4/12/2026 |
| 1.3.53 | 107 | 3/17/2026 |
| 1.3.52 | 96 | 3/17/2026 |
| 1.3.50 | 115 | 2/26/2026 |
| 1.3.49 | 110 | 2/23/2026 |
| 1.3.48 | 105 | 2/4/2026 |
| 1.3.47 | 207 | 12/22/2025 |
| 1.3.4 | 210 | 11/25/2025 |
| 1.2.46 | 192 | 12/22/2025 |
| 1.2.45 | 185 | 12/22/2025 |
| 1.2.44 | 152 | 12/21/2025 |
| 1.2.43 | 229 | 12/19/2025 |
| 1.2.42 | 289 | 12/17/2025 |
v1.4.0: Migrated to CerbiShield.Contracts v1.2.1 canonical contracts via Cerbi.Governance.Core v2.2.29 and Cerbi.GovernanceRuntime v2.0.23. Breaking: old Cerbi.CerbiShield.Contracts namespace removed.