CerbiStream.GovernanceAnalyzer 1.2.1

There is a newer version of this package available.
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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CerbiStream.GovernanceAnalyzer" Version="1.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CerbiStream.GovernanceAnalyzer" Version="1.2.1" />
                    
Directory.Packages.props
<PackageReference Include="CerbiStream.GovernanceAnalyzer" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CerbiStream.GovernanceAnalyzer --version 1.2.1
                    
#r "nuget: CerbiStream.GovernanceAnalyzer, 1.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CerbiStream.GovernanceAnalyzer@1.2.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CerbiStream.GovernanceAnalyzer&version=1.2.1
                    
Install as a Cake Addin
#tool nuget:?package=CerbiStream.GovernanceAnalyzer&version=1.2.1
                    
Install as a Cake Tool

Cerbi.NLog.GovernanceAnalyzer

License: MIT Build

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:

  • userId as Required
  • ssn as 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 event
  • GovernanceViolations (list/string) – optional list of violation messages
  • GovernanceRelaxed (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:

  1. Every log passes through RuntimeGovernanceEnricher
  2. Validates against PIILog profile
  3. If violations exist, computes impact score
  4. Attaches GovernanceScoreImpact, GovernanceViolations, GovernanceRelaxed
  5. 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:

  1. scoreShippingEnabled = true
  2. licenseAllowsScoring = true
  3. GovernanceScoreImpact exists & 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.Channels with BoundedChannelFullMode.DropWrite
  • Non-blocking enqueue: O(1) lock-free write; drops when full (no hot-path contention)
  • Async HTTP: HttpClient.PostAsync with fire-and-forget batching
  • Background flushing: continuous Task.Run loop 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 of Contains()
  • 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:

  1. Feature flag: scoreShippingEnabled (on/off switch)
  2. 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):


🧠 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed