CerbiStream.GovernanceAnalyzer
1.2.1
See the version list below for details.
dotnet add package CerbiStream.GovernanceAnalyzer --version 1.2.1
NuGet\Install-Package CerbiStream.GovernanceAnalyzer -Version 1.2.1
<PackageReference Include="CerbiStream.GovernanceAnalyzer" Version="1.2.1" />
<PackageVersion Include="CerbiStream.GovernanceAnalyzer" Version="1.2.1" />
<PackageReference Include="CerbiStream.GovernanceAnalyzer" />
paket add CerbiStream.GovernanceAnalyzer --version 1.2.1
#r "nuget: CerbiStream.GovernanceAnalyzer, 1.2.1"
#:package CerbiStream.GovernanceAnalyzer@1.2.1
#addin nuget:?package=CerbiStream.GovernanceAnalyzer&version=1.2.1
#tool nuget:?package=CerbiStream.GovernanceAnalyzer&version=1.2.1
Cerbi.NLog.GovernanceAnalyzer
Cerbi Governance Analyzer for NLog β compile-time log validation using Roslyn analyzers and JSON-based governance profiles + realtime runtime governance validation with high-throughput async score shipping.
This package lets you enforce logging governance rules for NLog at build time and runtime, so bad log patterns never make it to production, and governance violations are automatically scored and shipped to centralized observability platforms.
Part of the Cerbi Suite for governed logging, observability, and compliance.
π What It Does
Cerbi.NLog.GovernanceAnalyzer provides dual-layer governance:
Compile-Time (Roslyn Analyzer)
- β
Enforce required fields (e.g.,
userId,operationId) - β Block or warn on forbidden fields (e.g.,
ssn,creditCardNumber) - π§ Validate field types, enums, and encryption settings
- π Violations surfaced as compiler diagnostics in Visual Studio, Rider, CI/CD
Runtime (GovernanceScore Target)
- π Realtime validation: automatically validates every log against governance profiles
- π Impact scoring: computes violation severity (MissingField=5pts, Forbidden=10pts, etc.)
- π‘ Async shipping: batched HTTP POST with retry, backoff, and license gating
- β‘ High throughput: 100k+ events/sec, non-blocking enqueue, Channel-based queue
- π― Auto-enrichment: opt-in feature attaches scores automatically
π§ Example β NLog Usage & Diagnostics
_logger.Info("userId={0}, ssn={1}", "abc-123", "123-45-6789");
If your cerbi_governance.json declares:
userIdas Requiredssnas Forbidden
Compile-Time
[CERBI001] Missing Required Field: 'userId'
[CERBI002] Forbidden Field: 'ssn'
Runtime
{
"App": "MyApp",
"Environment": "Production",
"Impact": 15.0,
"Violations": ["MissingField:userId", "ForbiddenField:ssn"],
"Relaxed": false
}
π Governance Configuration
Governance rules are defined in a JSON profile shared with the rest of the Cerbi ecosystem (via Cerbi.Governance.Core).
Example cerbi_governance.json:
{
"EnforcementMode": "Strict",
"LoggingProfiles": {
"PIILog": {
"AllowedLevels": [ "Info", "Warn", "Error" ],
"FieldSeverities": {
"userId": "Required",
"ssn": "Forbidden",
"sessionId": "Warning"
},
"FieldTypes": {
"userId": "Guid"
},
"FieldEnums": {
"Region": ["US", "EU", "APAC"]
}
}
}
}
In your .csproj, make sure the config is copied alongside your build output:
<ItemGroup>
<None Include="cerbi_governance.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Tip: You can keep multiple profiles (e.g.
default,PIILog,AuditLog) and select them via Cerbi configuration. The NLog analyzer consumes whatever profile you point it at.
π Runtime Governance Score Shipping (Optional)
Enable automatic validation and scoring by adding the custom NLog target GovernanceScore.
It inspects LogEventInfo.Properties for these keys:
GovernanceScoreImpact(numeric) β REQUIRED to emit an eventGovernanceViolations(list/string) β optional list of violation messagesGovernanceRelaxed(bool) β optional flag indicating relaxed enforcement mode
If present, and shipping is enabled & licensed, a GovernanceScoreEvent is queued and batch-shipped asynchronously.
NLog Config Example
<nlog>
<extensions>
<add assembly="CerbiStream.GovernanceAnalyzer" />
</extensions>
<targets>
<target xsi:type="GovernanceScore"
name="governanceScore"
appName="MyApp"
environment="Production"
enableAutoEnrichment="true"
governanceProfile="PIILog"
scoreShippingEnabled="true"
licenseAllowsScoring="true"
scoreEndpoint="https://score.cerbi.systems/ingest"
scoreMaxBatchSize="50"
scoreMaxQueueSize="1000"
scoreFlushIntervalSeconds="5" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="governanceScore" />
</rules>
</nlog>
How it works:
- Every log passes through
RuntimeGovernanceEnricher - Validates against
PIILogprofile - If violations exist, computes impact score
- Attaches
GovernanceScoreImpact,GovernanceViolations,GovernanceRelaxed - Ships to endpoint via async batch
Manual Mode
Attach properties manually:
var logEvent = new LogEventInfo(LogLevel.Info, "", "Example governance event");
logEvent.Properties["GovernanceScoreImpact"] = 12.5;
logEvent.Properties["GovernanceViolations"] = new[]{"MissingField:userId"};
logEvent.Properties["GovernanceRelaxed"] = false;
Logger.Log(logEvent);
Gating Rules
Event shipped only if:
scoreShippingEnabled = truelicenseAllowsScoring = trueGovernanceScoreImpactexists & parses as numeric
Non-blocking: dropped if queue full; no hot-path locks.
βοΈ Configuration Reference (Target Attributes)
| Attribute | Default | Description |
|---|---|---|
appName |
(required) | Application identifier in shipped events. |
environment |
(required) | Deployment environment (Prod/Stage/Dev). |
enableAutoEnrichment |
false |
Auto-validate and score every log. |
governanceProfile |
"default" |
Profile name for auto-enrichment validation. |
scoreShippingEnabled |
false |
Master switch for score emission. |
licenseAllowsScoring |
false |
License gate (entitlement check). |
scoreMaxBatchSize |
50 |
Max events per HTTP POST batch. |
scoreMaxQueueSize |
1000 |
Queue capacity; drops when full. |
scoreFlushIntervalSeconds |
5 |
Background flush interval. |
scoreMaxRetries |
3 |
HTTP retry attempts per batch. |
scoreRetryBackoffMilliseconds |
250 |
Base backoff; scales linearly (250ms, 500ms, 750ms). |
scoreEndpoint |
https://cerbi.systems/score |
POST destination URL. |
You can also programmatically configure the target after LogManager.Configuration loads if needed.
π GovernanceScoreEvent Schema (JSON Batch Payload)
A flush sends a JSON array of events:
{
"App": "MyApp",
"Environment": "Production",
"UtcTimestamp": "2025-01-15T12:34:56Z",
"Impact": 15.0,
"Relaxed": false,
"Violations": [
"MissingField: userId (User identifier)",
"ForbiddenField: ssn (Social Security Number)"
],
"Properties": {
"CorrelationId": "abc-123",
"RequestPath": "/api/users"
}
}
Reserved property keys are not duplicated inside Properties: GovernanceScoreImpact, GovernanceViolations, GovernanceRelaxed.
β‘ Performance & Reliability
High-Throughput Design
- Channel-based queue:
System.Threading.ChannelswithBoundedChannelFullMode.DropWrite - Non-blocking enqueue: O(1) lock-free write; drops when full (no hot-path contention)
- Async HTTP:
HttpClient.PostAsyncwith fire-and-forget batching - Background flushing: continuous
Task.Runloop eliminates timer overhead - Profile caching: loaded once on
InitializeTarget(), reused per event - Inline validation: avoids external helper call overhead
- Fast impact scoring: char prefix matching (
err[0] == 'M') instead ofContains() - Zero-allocation enqueue: no intermediate buffers, direct channel write
Benchmark
| Metric | Performance |
|---|---|
| Enqueue throughput | 100,000+ events/sec |
| Hot-path overhead | <1 Β΅s (cached profile + fast ContainsKey) |
| Queue capacity | 1,000 events (configurable) |
| Batch size | 50 events/POST (configurable) |
| Concurrent flushing | Supported (fire-and-forget async) |
| Backpressure | Drops events when queue full (no blocking) |
Failure Modes
- HTTP failure: retries with exponential backoff; drops batch after
MaxRetries - Malformed impact: suppresses event emission (no exception)
- Queue overflow: silently drops new events (non-blocking)
- Shutdown: drains remaining events on
Dispose()(5s timeout)
π License Gating
Two independent gates:
- Feature flag:
scoreShippingEnabled(on/off switch) - Entitlement check:
licenseAllowsScoring(license validation)
Use licenseAllowsScoring=false to disable dynamically (e.g., expired contract, regional restriction, missing entitlement).
π§ͺ Testing Guidance
Unit Tests
// Test auto-enrichment
var target = CreateTarget(fakeShipper, t => {
t.EnableAutoEnrichment = true;
t.GovernanceProfile = "PIILog";
});
var logEvent = new LogEventInfo(LogLevel.Info, "", "test");
logEvent.Properties["password"] = "secret"; // forbidden field
target.Emit(logEvent);
Assert.Equal(1, fakeShipper.EnqueueCount);
Assert.True(fakeShipper.LastEvent.Impact > 0);
Assert.Contains("ForbiddenField: password", fakeShipper.LastEvent.Violations);
High-Throughput Test
[Fact]
public async Task HighThroughput_ThousandsOfEvents_NoBlocking()
{
var shipper = new ScoreShipper(httpClient, options);
var start = DateTime.UtcNow;
for (int i = 0; i < 1000; i++)
shipper.Enqueue(new GovernanceScoreEvent { Impact = i });
var elapsed = DateTime.UtcNow - start;
Assert.True(elapsed.TotalMilliseconds < 100); // <100ms for 1000 events
}
π Extensibility
Custom Shipper
Replace internal ScoreShipper with custom implementation:
public class MyCustomTarget : GovernanceScoreTarget
{
protected override void InitializeTarget()
{
// Inject custom shipper with metrics, circuit breaker, etc.
_scoreShipper = new MyCustomShipper(_httpClient, ScoreShipping);
}
}
Custom Validation
Wrap additional metadata:
logEvent.Properties["TeamId"] = "team-42";
logEvent.Properties["ServiceVersion"] = "1.2.3";
// Automatically copied to GovernanceScoreEvent.Properties
π¦ Installation
dotnet add package Cerbi.NLog.GovernanceAnalyzer
- Analyzer: runs automatically at build
- Target: activates via
<extensions>in NLog config
π Encryption & NLog
This package does not implement log payload encryption. NLog lacks first-class encryption support for structured data.
For end-to-end encrypted logging with governance-aware encryption modes (AES/Base64/None):
CerbiStreamβ governed logging libraryCerbi.Governance.Runtimeβ runtime validation engine
π§ IDE & CI Integration
Local Development
- Underlines / squiggles in Visual Studio and Rider
- Diagnostics in Error List
- Treat as warnings for dev productivity
CI/CD
dotnet build /warnaserror:CERBI001,CERBI002
- Escalate to errors for critical profiles (PII/PHI)
- Block deployment on governance violations
π§Ή Plugin Architecture
Layer custom rules via ICustomGovernancePlugin:
public class TeamIdPlugin : ICustomGovernancePlugin
{
public bool Validate(
string profile,
Dictionary<string, object> logData,
out List<string> failures,
out int impactScore)
{
failures = new();
impactScore = 0;
var isProd = logData.TryGetValue("Environment", out var env) &&
env?.ToString() == "Production";
if (isProd && !logData.ContainsKey("TeamId"))
{
failures.Add("MissingField: TeamId is required in Production.");
impactScore = 5;
return false;
}
return true;
}
}
Use plugins for:
- Environment-specific rules (stricter in Production)
- Team/domain-specific checks
- Custom impact scoring for dashboards (CerbiShield / CerbIQ)
π How It Fits with Other Loggers & Stacks
This package targets NLog specifically, but itβs part of a bigger story:
- Serilog / MEL / NLog / Log4Net
- Other Cerbi analyzers and runtime components cover these stacks.
- OpenTelemetry Logging / OTLP / Collector
- Cerbi ensures logs are governed before theyβre exported and shipped downstream.
- Seq, Grafana Loki / Promtail / Alloy, Fluentd / FluentBit, ELK / OpenSearch, Graylog, VictoriaLogs / VictoriaMetrics, Journald / syslog
- Keep using your existing sinks; this analyzer + target just keeps the input sane and compliant.
Cerbi.NLog.GovernanceAnalyzer doesnβt replace NLog or your observability platform. It makes sure your NLog usage is safe, structured, and policy-compliant.
π License
MIT Β© Cerbi LLC β https://cerbi.io
See LICENSE.txt for details.
| 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 was computed. 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. |
-
net8.0
- Microsoft.CodeAnalysis.CSharp (>= 4.13.0)
- Newtonsoft.Json (>= 13.0.3)
- NLog (>= 5.3.0)
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.49 | 135 | 12/29/2025 |
| 1.5.48 | 200 | 12/22/2025 |
| 1.5.47 | 193 | 12/22/2025 |
| 1.4.46 | 442 | 12/11/2025 |
| 1.4.44 | 435 | 12/11/2025 |
| 1.3.0 | 434 | 12/10/2025 |
| 1.2.1 | 207 | 11/25/2025 |
| 1.1.43 | 439 | 12/11/2025 |
| 1.1.41 | 444 | 12/11/2025 |
| 1.1.36 | 219 | 10/29/2025 |
| 1.1.35 | 203 | 10/29/2025 |
| 1.1.34 | 241 | 5/18/2025 |
| 1.1.33 | 187 | 5/18/2025 |
| 1.1.32 | 177 | 5/17/2025 |
| 1.1.31 | 210 | 5/17/2025 |
| 1.1.30 | 305 | 5/15/2025 |
| 1.1.29 | 312 | 5/15/2025 |
| 1.1.28 | 298 | 5/15/2025 |
| 1.1.27 | 316 | 5/15/2025 |
| 1.1.25 | 316 | 5/15/2025 |