<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Thomas Nelson</title>
    <description>The latest articles on Forem by Thomas Nelson (@zeroshi).</description>
    <link>https://forem.com/zeroshi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3032318%2F03ed7f84-093b-4721-9ce5-f5164e73d4c2.png</url>
      <title>Forem: Thomas Nelson</title>
      <link>https://forem.com/zeroshi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/zeroshi"/>
    <language>en</language>
    <item>
      <title>Enforce Runtime Logging Governance in .NET 8 with Cerbi.MEL.Governance</title>
      <dc:creator>Thomas Nelson</dc:creator>
      <pubDate>Thu, 05 Jun 2025 04:27:15 +0000</pubDate>
      <link>https://forem.com/zeroshi/enforce-runtime-logging-governance-in-net-8-with-cerbimelgovernance-1jf8</link>
      <guid>https://forem.com/zeroshi/enforce-runtime-logging-governance-in-net-8-with-cerbimelgovernance-1jf8</guid>
      <description>&lt;p&gt;Ever wished you could automatically catch missing PII fields or forbidden values in your &lt;code&gt;.NET 8&lt;/code&gt; logs, without rewriting your entire logging setup? With &lt;strong&gt;Cerbi.MEL.Governance&lt;/strong&gt;, you can now plug governance checks directly into any &lt;a href="https://docs.microsoft.com/dotnet/core/extensions/logging" rel="noopener noreferrer"&gt;&lt;code&gt;Microsoft.Extensions.Logging&lt;/code&gt;&lt;/a&gt; pipeline. It always emits your original log line—and only emits a second JSON payload when a violation occurs.&lt;/p&gt;

&lt;p&gt;In this post, we’ll cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why runtime logging governance matters&lt;/li&gt;
&lt;li&gt;How to install Cerbi.MEL.Governance&lt;/li&gt;
&lt;li&gt;Configuring your governance JSON (&lt;code&gt;cerbi_governance.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A quick‐start code example (3 lines to enable)&lt;/li&gt;
&lt;li&gt;A live demo with console output&lt;/li&gt;
&lt;li&gt;Advanced tips: Relaxed mode, multiple profiles, performance notes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s dive in!&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Why Runtime Logging Governance Matters
&lt;/h2&gt;

&lt;p&gt;When you log structured messages in production—especially with user data or payment information—you want to make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Required fields&lt;/strong&gt; (e.g., &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;) are never missing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forbidden fields&lt;/strong&gt; (e.g., &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;creditCardNumber&lt;/code&gt;) never appear.&lt;/li&gt;
&lt;li&gt;You can enforce these rules &lt;strong&gt;at runtime&lt;/strong&gt;, without having to manually audit logs later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most teams adopt Serilog or other libraries for structured logging. But if you’re already using &lt;code&gt;.NET&lt;/code&gt;’s built‐in &lt;a href="https://docs.microsoft.com/dotnet/core/extensions/logging" rel="noopener noreferrer"&gt;MEL&lt;/a&gt; (Microsoft.Extensions.Logging), there wasn’t a turnkey way to enforce governance rules—until now.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Cerbi.MEL.Governance&lt;/strong&gt;, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validate structured fields at runtime&lt;/strong&gt; against a governance profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always emit the original log line&lt;/strong&gt; (so downstream parsers/alerts work unchanged).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emit a secondary JSON payload only if a violation exists&lt;/strong&gt; (no extra noise when everything is valid).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support “Relaxed mode”&lt;/strong&gt; (if you want to temporarily bypass some rules) by passing &lt;code&gt;{ Relax } = true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plug into any MEL-compatible sink&lt;/strong&gt;: Console, File, Seq, Application Insights, etc.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Installation (NuGet)
&lt;/h2&gt;

&lt;p&gt;Install the latest version via CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Installs the most recent version of Cerbi.MEL.Governance&lt;/span&gt;
dotnet add package Cerbi.MEL.Governance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Cerbi.MEL.Governance targets &lt;strong&gt;.NET 8.0&lt;/strong&gt; or higher.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Governance Configuration (&lt;code&gt;cerbi_governance.json&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Create a file named &lt;code&gt;cerbi_governance.json&lt;/code&gt; in your project root (or anywhere you like, just point &lt;code&gt;ConfigPath&lt;/code&gt; to it). Here’s a sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"EnforcementMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Strict"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"LoggingProfiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"FieldSeverities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Forbidden"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"AllowRelax"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"RequireTopic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"AllowedTopics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Payments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"FieldSeverities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"accountNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Required"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"AllowRelax"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"RequireTopic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"AllowedTopics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Payments"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;EnforcementMode&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"Strict"&lt;/code&gt;: Any missing required field or forbidden field triggers a violation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;LoggingProfiles&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each top‐level key (e.g., &lt;code&gt;"Orders"&lt;/code&gt;, &lt;code&gt;"Payments"&lt;/code&gt;) is a &lt;strong&gt;profile name&lt;/strong&gt; or &lt;strong&gt;topic&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;FieldSeverities&lt;/code&gt;&lt;/strong&gt;: map each field name to &lt;code&gt;"Required"&lt;/code&gt; or &lt;code&gt;"Forbidden"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AllowRelax&lt;/code&gt;&lt;/strong&gt; (boolean): if &lt;code&gt;true&lt;/code&gt;, passing &lt;code&gt;{ Relax } = true&lt;/code&gt; in your log call will suppress violations and mark &lt;code&gt;"GovernanceRelaxed": true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RequireTopic&lt;/code&gt;&lt;/strong&gt;: if &lt;code&gt;true&lt;/code&gt;, logs without a matching &lt;code&gt;[CerbiTopic]&lt;/code&gt; attribute or fallback &lt;code&gt;Profile&lt;/code&gt; key will be skipped/flagged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AllowedTopics&lt;/code&gt;&lt;/strong&gt;: list of topics allowed for this profile (helps prevent cross‐pollination).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Quick‐Start Code Example (3 Lines!)
&lt;/h2&gt;

&lt;p&gt;In most &lt;code&gt;.NET 8&lt;/code&gt; console or worker‐service apps, you have something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Hosting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Logging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Cerbi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Cerbi.MEL.Governance’s namespace&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ClearProviders&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSimpleConsole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncludeScopes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SingleLine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimestampFormat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HH:mm:ss "&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="c1"&gt;// ← 3 lines to enable governance:&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCerbiGovernance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Profile&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                   &lt;span class="c1"&gt;// fallback topic if no [CerbiTopic] found&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cerbi_governance.json"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// path to your JSON profile&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                         &lt;span class="c1"&gt;// toggle enforcement on/off&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTransient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTransient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PaymentService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;using Cerbi;&lt;/code&gt;&lt;/strong&gt; is mandatory because the &lt;code&gt;AddCerbiGovernance(...)&lt;/code&gt; extension lives there.&lt;/li&gt;
&lt;li&gt;You can replace &lt;code&gt;logging.AddSimpleConsole(...)&lt;/code&gt; with any other MEL sink (e.g., &lt;code&gt;logging.AddConsole()&lt;/code&gt;, &lt;code&gt;logging.AddApplicationInsights()&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;options.Profile&lt;/code&gt;&lt;/strong&gt; is the default fallback topic if no &lt;code&gt;[CerbiTopic("…")]&lt;/code&gt; is found on the call stack. You can still override via &lt;code&gt;[CerbiTopic]&lt;/code&gt; on a class or method.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Live Demo &amp;amp; Output
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;OrderService.cs&lt;/code&gt; (example)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Cerbi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// for [CerbiTopic]&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Logging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;CerbiTopic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Example 1: Valid log (both userId and email provided)&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valid order: {userId} {email}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Example 2: Missing userId → violation&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Missing userId, only email: {email}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Example 3: Forbidden field (password) → violation&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Leaking password: {userId} {email} {password}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"supersecret"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Example 4: Relaxed mode (AllowRelax = true in JSON; pass {Relax} = true)&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Email-only (relaxed): {email} {Relax}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming you call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see console output like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[12:34:56 INF] Valid order: abc123 user@example.com
[12:34:56 INF] {"userId":"abc123","email":"user@example.com","CerbiTopic":"Orders","GovernanceProfileUsed":"Orders","GovernanceEnforced":true,"GovernanceMode":"Strict"}

[12:34:56 INF] Missing userId, only email: user@example.com
[12:34:56 INF] {"email":"user@example.com","CerbiTopic":"Orders","GovernanceViolations":["MissingField:userId"],"GovernanceRelaxed":false,"GovernanceProfileUsed":"Orders"}

[12:34:56 INF] Leaking password: abc123 user@example.com supersecret
[12:34:56 INF] {"userId":"abc123","email":"user@example.com","password":"supersecret","CerbiTopic":"Orders","GovernanceViolations":["ForbiddenField:password"],"GovernanceRelaxed":false,"GovernanceProfileUsed":"Orders"}

[12:34:56 INF] Email-only (relaxed): user@example.com True
[12:34:56 INF] {"email":"user@example.com","CerbiTopic":"Orders","GovernanceRelaxed":true,"GovernanceProfileUsed":"Orders"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First log&lt;/strong&gt;: both fields present → governance enforced in “Strict” mode (JSON payload shows &lt;code&gt;"GovernanceEnforced": true&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second log&lt;/strong&gt;: missing &lt;code&gt;userId&lt;/code&gt; → JSON payload includes &lt;code&gt;"GovernanceViolations": ["MissingField:userId"]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third log&lt;/strong&gt;: forbidden &lt;code&gt;password&lt;/code&gt; → JSON payload includes &lt;code&gt;"ForbiddenField:password"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fourth log&lt;/strong&gt;: relaxed (because &lt;code&gt;{ Relax } = true&lt;/code&gt; and &lt;code&gt;AllowRelax:true&lt;/code&gt; in JSON) → JSON payload shows &lt;code&gt;"GovernanceRelaxed": true&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that &lt;strong&gt;your original log line always appears first&lt;/strong&gt;, unchanged. Only when a rule is violated (or relaxed) do you see that second JSON‐only line. Downstream log processors (Seq, Kibana, Splunk) still parse your structured fields from the first line as usual.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Advanced Tips &amp;amp; Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Multiple Profiles / Topics&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;If your solution has multiple domains (e.g., “Orders,” “Payments,” “Users”), define each profile in the JSON.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;[CerbiTopic("Payments")]&lt;/code&gt; on your &lt;code&gt;PaymentService&lt;/code&gt; class. If no attribute is found, &lt;code&gt;options.Profile&lt;/code&gt; kicks in as a fallback.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Turning Enforcement On/Off&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;options.Enabled = false&lt;/code&gt; (or toggle via an environment variable) for development or quick debugging.&lt;/li&gt;
&lt;li&gt;You can programmatically reload the JSON file if it changes at runtime by restarting your host. A future version may support hot‐reloading.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Relaxed Mode&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;In JSON: &lt;code&gt;"AllowRelax": true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In code: &lt;code&gt;_logger.LogInformation("… {Relax}", true)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Violations are suppressed; JSON payload simply shows &lt;code&gt;"GovernanceRelaxed": true, "GovernanceProfileUsed": "Orders"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;EA / Compliance-Driven Use Cases&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;If you’re a Lead Enterprise Architect responsible for compliance, embed your EA roadmap decisions into your governance JSON.&lt;/li&gt;
&lt;li&gt;Use field‐severity rules to detect days when migrations aren’t passing compliance checks (e.g., new microservices missing required context fields).&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Performance Considerations&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;On a warm VM startup, the JSON validator is built once in memory. Per‐log overhead is minimal (milliseconds) unless you have hundreds of structured fields.&lt;/li&gt;
&lt;li&gt;Benchmarks show &amp;lt; 1 ms overhead on typical log calls when no violations occur. Always measure under your app’s load profile if you have extremely high‐frequency logging.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Next Steps &amp;amp; Roadmap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relax() Helper Extension&lt;/strong&gt;&lt;br&gt;
Coming soon: a fluent &lt;code&gt;logger.Relax()&lt;/code&gt; API so you don’t have to manually pass &lt;code&gt;{ Relax } = true&lt;/code&gt; each time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support for Additional EA Tools&lt;/strong&gt;&lt;br&gt;
Future releases will integrate directly with LeanIX, Alfabet, and MEGA’s REST APIs to sync governance profiles automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Violation Formatting&lt;/strong&gt;&lt;br&gt;
Want more context in the JSON payload? We plan to add hooks so you can control the violation‐code format (e.g., prepend environment name or correlation‐ID).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Contributions&lt;/strong&gt;&lt;br&gt;
We welcome issues and pull requests! If you have a scenario we haven’t covered (e.g., Azure Functions scope issues), please open an issue or PR on GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Links &amp;amp; Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;Demo &amp;amp; Examples (GitHub)&lt;/strong&gt;:
&lt;a href="https://github.com/Zeroshi/Cerbi.MEL.Governance.Demo" rel="noopener noreferrer"&gt;Zeroshi/Cerbi.MEL.Governance.Demo: Demonstrating Cerbi MEL governance implementation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;NuGet Package&lt;/strong&gt;:
&lt;code&gt;dotnet add package Cerbi.MEL.Governance&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cerbi.MEL.Governance&lt;/strong&gt; gives you runtime enforcement of required/forbidden fields in any MEL pipeline. Install one NuGet package, configure a simple JSON file, and enforce PII/compliance rules automatically. Visit the repo for a full demo; join the conversation via issues or PRs if you need help or want to contribute!&lt;/p&gt;

&lt;p&gt;Happy logging!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>security</category>
      <category>logging</category>
      <category>compliance</category>
    </item>
    <item>
      <title>CerbiStream: Real-Time Governance-Enforced Logging for .NET</title>
      <dc:creator>Thomas Nelson</dc:creator>
      <pubDate>Tue, 20 May 2025 01:56:45 +0000</pubDate>
      <link>https://forem.com/zeroshi/cerbistream-real-time-governance-enforced-logging-for-net-1kc4</link>
      <guid>https://forem.com/zeroshi/cerbistream-real-time-governance-enforced-logging-for-net-1kc4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;What if your logs could validate themselves &lt;em&gt;while running&lt;/em&gt; — tagging violations without dropping a single event?&lt;br&gt;
CerbiStream brings governance to your logs, adds structure, encrypts them, and routes them securely. All in real-time.&lt;/p&gt;

&lt;p&gt;Enterprise-grade logging with structure, encryption, fallback, and real-time governance — built for cloud-native .NET developers.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧠 Why CerbiStream Exists
&lt;/h2&gt;

&lt;p&gt;As developers, we've all experienced logging mistakes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accidentally logging sensitive data like passwords or emails&lt;/li&gt;
&lt;li&gt;Forgetting to include &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;requestId&lt;/code&gt;, or &lt;code&gt;environment&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Debugging issues with logs that have no structure, context, or traceability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CerbiStream is designed to help development teams avoid these problems — by baking in &lt;strong&gt;runtime validation&lt;/strong&gt;, &lt;strong&gt;fallback safety&lt;/strong&gt;, and &lt;strong&gt;contextual metadata&lt;/strong&gt; into every log line.&lt;/p&gt;

&lt;p&gt;It doesn't just log your data. It &lt;strong&gt;governs it&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ What Is CerbiStream?
&lt;/h2&gt;

&lt;p&gt;CerbiStream is a modular logging framework for .NET that helps developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Enforce runtime log structure via governance profiles&lt;/li&gt;
&lt;li&gt;🔐 Secure logs with AES/Base64 encryption&lt;/li&gt;
&lt;li&gt;🚦 Auto-tag logs with metadata and trace info&lt;/li&gt;
&lt;li&gt;📂 Fallback to encrypted local files if queues fail&lt;/li&gt;
&lt;li&gt;📡 Send to queues, cloud storage, or telemetry in parallel&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Quick Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package CerbiStream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCerbiStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"RabbitMQ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"logs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithFileFallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logs/fallback.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithEncryptionMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EncryptionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithEncryptionKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;myIv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithGovernanceChecks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableProductionMode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔐 Real-Time Governance Enforcement
&lt;/h2&gt;

&lt;p&gt;The real-time governance feature rolled out recently with Cerbi.Governance.Runtime — and it's just the beginning. We’ve built it into CerbiStream to validate logs &lt;em&gt;as they happen&lt;/em&gt;, without slowing development workflows or requiring devs to memorize rules.&lt;/p&gt;

&lt;p&gt;We're actively extending this to other ecosystems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔜 &lt;code&gt;Cerbi.Serilog.GovernanceAnalyzer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🔜 &lt;code&gt;Cerbi.NLog.GovernanceAnalyzer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🔜 &lt;code&gt;Cerbi.Log4Net.GovernanceAnalyzer&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will bring consistent, policy-driven enforcement across the most popular logging stacks in .NET.&lt;/p&gt;

&lt;p&gt;CerbiStream now supports &lt;strong&gt;real-time governance enforcement&lt;/strong&gt; via &lt;code&gt;Cerbi.Governance.Runtime&lt;/code&gt;, ensuring that logs are validated against governance profiles &lt;em&gt;at runtime&lt;/em&gt;. This removes dependency on build-time analyzers and works seamlessly across environments and dynamic deployment scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Profiles define expected fields, severity, and topics.&lt;/li&gt;
&lt;li&gt;When a log is written, it is evaluated against the profile before being routed.&lt;/li&gt;
&lt;li&gt;If the log is non-compliant, governance metadata is injected (e.g., &lt;code&gt;GovernanceViolations&lt;/code&gt;, &lt;code&gt;GovernanceProfileUsed&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;Relax()&lt;/code&gt; is applied, governance is bypassed &lt;em&gt;intentionally&lt;/em&gt; but still &lt;strong&gt;tagged&lt;/strong&gt; with &lt;code&gt;"GovernanceRelaxed": true&lt;/code&gt; for audit and scoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ This approach ensures &lt;em&gt;logs aren't dropped&lt;/em&gt; — they are &lt;strong&gt;tagged, not blocked&lt;/strong&gt;, making it easy to score or flag them downstream without causing operational noise or alert spam.&lt;/p&gt;

&lt;p&gt;➡️ Future versions will integrate this tagging into CerbiSense for governance scoring and trend analysis across teams and services.&lt;/p&gt;

&lt;p&gt;CerbiStream uses JSON-based profiles and applies them at runtime, so developers aren’t locked into compile-time analyzers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"EnforcementMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Strict"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"LoggingProfiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"RequireTopic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"AllowedTopics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"FieldSeverities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Forbidden"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"AllowRelax"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tag your class with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;CerbiTopic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛄 Example Logs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Compliant Log
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Order started"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"u123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"demo@site.com"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Order started"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"u123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"demo@site.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"GovernanceProfileUsed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Orders"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"TimestampUtc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-05-19T10:42:01Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ❌ Violation (Missing Required Fields)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"GovernanceViolations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Missing: userId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missing: email"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"GovernanceMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Strict"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🛑 Relaxed Log (Explicit Bypass)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Relax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Emergency override triggered"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Emergency override triggered"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"GovernanceRelaxed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"LogLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📂 File Fallback Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithEncryptedFallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fallback.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"primary.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs are written securely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;ENCRYPTED&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;AES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Payload&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;/ENCRYPTED&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ☁️ Supported Targets
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📨 &lt;strong&gt;Queues&lt;/strong&gt;: RabbitMQ, Azure Service Bus, Kafka, AWS SQS, GCP Pub/Sub&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Telemetry&lt;/strong&gt;: App Insights, OpenTelemetry, Datadog, CloudWatch&lt;/li&gt;
&lt;li&gt;📂 &lt;strong&gt;Storage&lt;/strong&gt;: Azure Blob, AWS S3, Google Cloud Storage&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Preset Modes for Easy Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableDevModeMinimal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;             &lt;span class="c1"&gt;// Console only&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableDeveloperModeWithTelemetry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Local testing&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableProductionMode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;             &lt;span class="c1"&gt;// Full governance&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableBenchmarkMode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;              &lt;span class="c1"&gt;// Silent for perf tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 Benchmarked vs. Serilog
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;CerbiStream ✅&lt;/th&gt;
&lt;th&gt;Serilog ❌&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Real-Time Governance&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full Payload Encryption&lt;/td&gt;
&lt;td&gt;✅ Built-in AES&lt;/td&gt;
&lt;td&gt;❌ Requires plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fallback Logging&lt;/td&gt;
&lt;td&gt;✅ Encrypted&lt;/td&gt;
&lt;td&gt;🔸 Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telemetry + Queues&lt;/td&gt;
&lt;td&gt;✅ Dual support&lt;/td&gt;
&lt;td&gt;🔸 Separate sinks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/Zeroshi/CerbiStream.BenchmarkTests" rel="noopener noreferrer"&gt;View benchmarks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧾 Summary
&lt;/h2&gt;

&lt;p&gt;In this article, we covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why log governance is a human problem&lt;/li&gt;
&lt;li&gt;What CerbiStream does differently&lt;/li&gt;
&lt;li&gt;How runtime enforcement tags non-compliant logs&lt;/li&gt;
&lt;li&gt;What compliant, violating, and relaxed log output looks like&lt;/li&gt;
&lt;li&gt;How fallback, telemetry, and encryption features help build safer systems&lt;/li&gt;
&lt;li&gt;The roadmap for supporting other loggers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CerbiStream was created to help developers log confidently and securely — without losing productivity. Try it out, enforce your standards, and eliminate log regret.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Try It Out
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧪 &lt;a href="https://github.com/Zeroshi/CerbistreamGovernanceDemo" rel="noopener noreferrer"&gt;CerbiStream Demo App&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧠 &lt;a href="https://github.com/Zeroshi/Cerbi-CerbiStream" rel="noopener noreferrer"&gt;CerbiStream Core Repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧪 &lt;a href="https://github.com/Zeroshi/CerbiStream.BenchmarkTests" rel="noopener noreferrer"&gt;Benchmark Suite&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📦 NuGet Packages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nuget.org/packages/CerbiStream" rel="noopener noreferrer"&gt;CerbiStream&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nuget.org/packages/Cerbi.Governance.Runtime" rel="noopener noreferrer"&gt;Cerbi.Governance.Runtime&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nuget.org/packages/CerbiStream.GovernanceAnalyzer" rel="noopener noreferrer"&gt;CerbiStream.GovernanceAnalyzer&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.nuget.org/packages/Cerbi.Serilog.GovernanceAnalyzer" rel="noopener noreferrer"&gt;Cerbi.Serilog.GovernanceAnalyzer&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧪 &lt;a href="https://github.com/Zeroshi/CerbistreamGovernanceDemo" rel="noopener noreferrer"&gt;Sample App&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📚 &lt;a href="https://github.com/Zeroshi/Cerbi-CerbiStream" rel="noopener noreferrer"&gt;Documentation &amp;amp; Profiles&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📦 &lt;a href="https://www.nuget.org/packages/CerbiStream" rel="noopener noreferrer"&gt;NuGet - CerbiStream&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💬 &lt;a href="https://github.com/Zeroshi/Cerbi-CerbiStream/discussions" rel="noopener noreferrer"&gt;GitHub Discussions&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;CerbiStream is open source and evolving fast. Let us know your use case or suggest a feature!&lt;br&gt;
&lt;strong&gt;Happy logging 🙌&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>logging</category>
      <category>security</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Benchmarking Logging Frameworks: How CerbiStream Measures Up</title>
      <dc:creator>Thomas Nelson</dc:creator>
      <pubDate>Wed, 23 Apr 2025 21:43:25 +0000</pubDate>
      <link>https://forem.com/zeroshi/benchmarking-logging-frameworks-how-cerbistream-measures-up-35af</link>
      <guid>https://forem.com/zeroshi/benchmarking-logging-frameworks-how-cerbistream-measures-up-35af</guid>
      <description>&lt;p&gt;Logging shouldn’t be an afterthought. It should be &lt;strong&gt;fast&lt;/strong&gt;, &lt;strong&gt;structured&lt;/strong&gt;, and &lt;strong&gt;governed&lt;/strong&gt;—without slowing your app down.&lt;/p&gt;

&lt;p&gt;Meet &lt;a href="https://www.nuget.org/packages/CerbiStream" rel="noopener noreferrer"&gt;&lt;strong&gt;CerbiStream&lt;/strong&gt;&lt;/a&gt;, a developer-first logging library built with governance and performance at its core. But how does it actually perform compared to industry staples like &lt;strong&gt;Serilog&lt;/strong&gt;, &lt;strong&gt;NLog&lt;/strong&gt;, and &lt;strong&gt;Log4Net&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;That’s what &lt;a href="https://github.com/Zeroshi/CerbiStream.BenchmarkTests" rel="noopener noreferrer"&gt;&lt;strong&gt;CerbiStream.BenchmarkTests&lt;/strong&gt;&lt;/a&gt; was created to answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔬 What’s Inside?
&lt;/h2&gt;

&lt;p&gt;This open-source benchmark suite uses &lt;a href="https://benchmarkdotnet.org/" rel="noopener noreferrer"&gt;BenchmarkDotNet&lt;/a&gt; to give you real, comparable results across popular logging frameworks.&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔁 &lt;strong&gt;Throughput tests&lt;/strong&gt; — logging 10k+ entries per run&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;Memory benchmarks&lt;/strong&gt; — allocations, GC behavior, per-log overhead&lt;/li&gt;
&lt;li&gt;🧱 &lt;strong&gt;Payload scenarios&lt;/strong&gt; — from flat logs to nested structured objects&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Governance enforcement&lt;/strong&gt; — CerbiStream uniquely validates required &amp;amp; forbidden fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All test outputs are saved under the &lt;code&gt;charts/&lt;/code&gt; folder and are easy to extend. Want to add your own logger? Just plug it in.&lt;/p&gt;




&lt;h2&gt;
  
  
  📈 Sample Benchmark: Logs/sec
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Logger&lt;/th&gt;
&lt;th&gt;Logs/sec (Structured)&lt;/th&gt;
&lt;th&gt;Memory/Log&lt;/th&gt;
&lt;th&gt;Governance?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CerbiStream&lt;/td&gt;
&lt;td&gt;🟢 82,000+&lt;/td&gt;
&lt;td&gt;~128 B&lt;/td&gt;
&lt;td&gt;✅ Full support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NLog&lt;/td&gt;
&lt;td&gt;🔵 84,000&lt;/td&gt;
&lt;td&gt;~120 B&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serilog&lt;/td&gt;
&lt;td&gt;🟡 80,000&lt;/td&gt;
&lt;td&gt;~146 B&lt;/td&gt;
&lt;td&gt;⚠️ Plugin only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Log4Net&lt;/td&gt;
&lt;td&gt;🟠 60,000&lt;/td&gt;
&lt;td&gt;~160 B&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ CerbiStream is the only logger with &lt;strong&gt;compile-time analyzers&lt;/strong&gt; and &lt;strong&gt;runtime validation&lt;/strong&gt; for governance rules.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More detailed charts → &lt;a href="https://github.com/Zeroshi/CerbiStream.BenchmarkTests/tree/main/charts" rel="noopener noreferrer"&gt;View Benchmarks&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ What Makes CerbiStream Different?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCerbiStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseGovernanceFromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Configs/governance.json"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>dotnet</category>
      <category>logging</category>
      <category>benchmarking</category>
      <category>programming</category>
    </item>
    <item>
      <title>CerbiStream – Bringing Governance to the Wild West of Logging</title>
      <dc:creator>Thomas Nelson</dc:creator>
      <pubDate>Thu, 10 Apr 2025 16:42:00 +0000</pubDate>
      <link>https://forem.com/zeroshi/cerbistream-bringing-governance-to-the-wild-west-of-logging-4ok6</link>
      <guid>https://forem.com/zeroshi/cerbistream-bringing-governance-to-the-wild-west-of-logging-4ok6</guid>
      <description>&lt;p&gt;Hi everyone,&lt;/p&gt;

&lt;p&gt;I’m excited to share deeper insights into &lt;a href="https://www.nuget.org/packages/CerbiStream" rel="noopener noreferrer"&gt;&lt;strong&gt;CerbiStream&lt;/strong&gt;&lt;/a&gt; — a &lt;strong&gt;free logging framework&lt;/strong&gt; built for &lt;strong&gt;.NET&lt;/strong&gt; that’s designed to solve persistent challenges faced by growing companies, decoupled teams, contracting organizations, and industries under strict regulations like &lt;strong&gt;HIPAA&lt;/strong&gt; and &lt;strong&gt;GDPR&lt;/strong&gt;. While CerbiStream is currently optimized for .NET, plans are already underway to extend support to &lt;strong&gt;other popular frameworks&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Governance in Logging Matters
&lt;/h2&gt;

&lt;p&gt;Logging today is often the wild west of modern systems. Many organizations suffer from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inconsistent Logging&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Developers working across multiple services use varied logging approaches, leading to confusing and unstructured log outputs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unpredictable Data&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Without enforced structure, you never know what data will be captured—making troubleshooting and traceability challenging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compliance and Security Challenges&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For industries dealing with sensitive data, inconsistent logging can lead to major compliance issues and security risks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having held roles across several companies and industries, I saw how these issues resulted in operational headaches and wasted time. That's why I built &lt;strong&gt;CerbiStream&lt;/strong&gt; — to enforce governance in logging from the ground up.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes CerbiStream Different
&lt;/h2&gt;

&lt;p&gt;CerbiStream isn’t just another logging library. It is engineered with a &lt;strong&gt;governance-first mindset&lt;/strong&gt; while ensuring integration with modern observability tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoupled Logging Pipeline
&lt;/h3&gt;

&lt;p&gt;CerbiStream sends logs through queues — supporting &lt;strong&gt;RabbitMQ&lt;/strong&gt;, &lt;strong&gt;Kafka&lt;/strong&gt;, &lt;strong&gt;Azure Service Bus&lt;/strong&gt;, &lt;strong&gt;AWS SQS&lt;/strong&gt;, and &lt;strong&gt;GCP Pub/Sub&lt;/strong&gt; — offloading processing to downstream systems like &lt;strong&gt;Application Insights&lt;/strong&gt; and others. This ensures &lt;strong&gt;minimal latency&lt;/strong&gt; and &lt;strong&gt;maximum durability&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Governance-First Approach
&lt;/h3&gt;

&lt;p&gt;With built-in &lt;strong&gt;compile-time analyzers&lt;/strong&gt; and &lt;strong&gt;runtime validators&lt;/strong&gt;, every log entry must include the required metadata (e.g., &lt;code&gt;UserId&lt;/code&gt;, &lt;code&gt;IPAddress&lt;/code&gt;). This simplifies troubleshooting and helps meet strict &lt;strong&gt;audit and compliance&lt;/strong&gt; standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Optimized
&lt;/h3&gt;

&lt;p&gt;Using &lt;a href="https://benchmarkdotnet.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;BenchmarkDotNet&lt;/strong&gt;&lt;/a&gt;, local benchmarks were run comparing CerbiStream to &lt;strong&gt;Serilog&lt;/strong&gt;, &lt;strong&gt;NLog&lt;/strong&gt;, and &lt;strong&gt;Log4Net&lt;/strong&gt;. CerbiStream consistently matched or exceeded their performance — while offering governance and queue-first routing as a bonus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexible and Developer-Friendly
&lt;/h3&gt;

&lt;p&gt;In development mode, rapid iteration is effortless. Production mode supports telemetry and governance seamlessly. CerbiStream’s intuitive API enables quick integration, even for decentralized or remote teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built for .NET — and Beyond
&lt;/h3&gt;

&lt;p&gt;CerbiStream is currently focused on .NET, but we’re actively working to support &lt;strong&gt;other frameworks&lt;/strong&gt; like &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt;, and &lt;strong&gt;Java&lt;/strong&gt;, making cross-platform structured logging with governance a reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Need for a Unified, Governed Logging Approach
&lt;/h2&gt;

&lt;p&gt;For growing companies — especially those with &lt;strong&gt;distributed teams&lt;/strong&gt; or &lt;strong&gt;contractors&lt;/strong&gt; — consistent logging is critical. CerbiStream guarantees that every log entry follows strict governance rules, helping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce production troubleshooting time
&lt;/li&gt;
&lt;li&gt;Strengthen security and compliance postures
&lt;/li&gt;
&lt;li&gt;Enable consistent audit trails
&lt;/li&gt;
&lt;li&gt;Standardize developer logging practices across teams&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Let’s Drive the Conversation Forward
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your feedback on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Clarity&lt;/strong&gt; — Is the CerbiStream API intuitive enough for your team?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance &amp;amp; Governance&lt;/strong&gt; — Would enforced log structure simplify your audit/security processes?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Enhancements&lt;/strong&gt; — What would make CerbiStream even more powerful for your use case?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Integration&lt;/strong&gt; — Would a governance dashboard like &lt;a href="https://github.com/Zeroshi/CerbiShield" rel="noopener noreferrer"&gt;&lt;strong&gt;CerbiShield&lt;/strong&gt;&lt;/a&gt; (coming soon!) revolutionize how you handle log auditing?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Free
&lt;/h2&gt;

&lt;p&gt;CerbiStream is &lt;a href="https://www.nuget.org/packages/CerbiStream" rel="noopener noreferrer"&gt;&lt;strong&gt;completely free&lt;/strong&gt; on NuGet&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
You can check out the full source code on GitHub: &lt;a href="https://github.com/Zeroshi/Cerbi-CerbiStream" rel="noopener noreferrer"&gt;&lt;strong&gt;CerbiStream GitHub Repo&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, to add governance add: &lt;a href="https://www.nuget.org/packages/CerbiStream.GovernanceAnalyzer" rel="noopener noreferrer"&gt;CerbiStream.GovernanceAnalyzer&lt;/a&gt;   &lt;/p&gt;

&lt;p&gt;Feel free to drop your comments or questions below. Whether you're working on a tightly regulated enterprise app or just want clean, consistent logs across services — your feedback will help shape the future of CerbiStream.&lt;/p&gt;

&lt;p&gt;Let’s redefine logging together.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>logging</category>
      <category>governance</category>
      <category>opensource</category>
    </item>
    <item>
      <title>CerbiStream: .NET Logging with Governance Enforcement, Queue Routing, and Developer-First Config</title>
      <dc:creator>Thomas Nelson</dc:creator>
      <pubDate>Wed, 09 Apr 2025 04:11:11 +0000</pubDate>
      <link>https://forem.com/zeroshi/cerbistream-net-logging-with-governance-enforcement-queue-routing-and-developer-first-config-4108</link>
      <guid>https://forem.com/zeroshi/cerbistream-net-logging-with-governance-enforcement-queue-routing-and-developer-first-config-4108</guid>
      <description>&lt;p&gt;Hey,&lt;/p&gt;

&lt;p&gt;I'm new to the site. I created this account because I wanted to gather some feedback on a product I've been building. &lt;/p&gt;

&lt;p&gt;Over the past few months, I’ve been working on a .NET logging framework that solves a handful of pain points I’ve consistently run into on large-scale enterprise systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logging that's &lt;strong&gt;too open-ended&lt;/strong&gt; or poorly structured&lt;/li&gt;
&lt;li&gt;Inconsistent developer output across microservices&lt;/li&gt;
&lt;li&gt;Centralized routing to multiple observability tools&lt;/li&gt;
&lt;li&gt;Difficulty enforcing governance or auditing policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built &lt;strong&gt;CerbiStream&lt;/strong&gt; — a governance-first, developer-friendly logging solution for .NET 8 and beyond.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is CerbiStream?
&lt;/h2&gt;

&lt;p&gt;CerbiStream is a structured logging library built to help teams &lt;strong&gt;enforce log structure&lt;/strong&gt;, &lt;strong&gt;send logs through queues&lt;/strong&gt;, and &lt;strong&gt;stay secure and consistent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔹 &lt;a href="https://www.nuget.org/packages/CerbiStream" rel="noopener noreferrer"&gt;CerbiStream on NuGet&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔹 &lt;a href="https://www.nuget.org/packages/CerbiStream.GovernanceAnalyzer" rel="noopener noreferrer"&gt;Governance Analyzer Add-on&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔹 &lt;a href="https://github.com/Zeroshi/Cerbi-CerbiStream" rel="noopener noreferrer"&gt;GitHub Repo (MIT)&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔹 &lt;a href="https://cerbi.systems/" rel="noopener noreferrer"&gt;CerbiSuite Website&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;✅ Out-of-the-box support for &lt;code&gt;ILogger&amp;lt;T&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ Works with RabbitMQ, Kafka, Azure Service Bus, AWS SQS, GCP Pub/Sub&lt;br&gt;&lt;br&gt;
✅ Optional encryption (Base64, AES with custom keys or Azure Key Vault)&lt;br&gt;&lt;br&gt;
✅ Governance Analyzer for compile-time structured logging enforcement&lt;br&gt;&lt;br&gt;
✅ External validator support for EF Core/Blazor-safe validation&lt;br&gt;&lt;br&gt;
✅ Presets for development, benchmarking, and telemetry-enabled modes&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCerbiStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AzureServiceBus"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sb://..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"audit-logs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithEncryptionMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EncryptionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Base64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableDeveloperModeWithTelemetry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ To enable governance without using the Roslyn analyzer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithGovernanceValidator&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UserId"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IPAddress"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Cerbi?&lt;/strong&gt;&lt;br&gt;
CerbiStream is part of a bigger ecosystem I'm working on:&lt;/p&gt;

&lt;p&gt;CerbiStream – Dev-first logging SDK&lt;br&gt;
 CerbiStream.GovernanceAnalyzer – Optional Roslyn analyzer&lt;br&gt;
 CerbIQ – Routing &amp;amp; observability pipeline (pulls from queue, sends to sinks like Splunk, Elastic, etc.)&lt;br&gt;
 CerbiShield – (Coming soon!) Governance rule dashboard with RBAC &amp;amp; audit logging&lt;/p&gt;

&lt;p&gt;📈 Adoption &amp;amp; Status&lt;br&gt;
📦 Over 2,000+ downloads on NuGet&lt;/p&gt;

&lt;p&gt;Used by Checkmarx, Artifactory, CI systems, and private mirrors&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarked Against Other Loggers
&lt;/h2&gt;

&lt;p&gt;CerbiStream was built with performance in mind. It’s benchmarked alongside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🪵 &lt;strong&gt;Serilog&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🧱 &lt;strong&gt;NLog&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🔩 &lt;strong&gt;Log4Net&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benchmarks show CerbiStream achieving &lt;strong&gt;competitive performance&lt;/strong&gt; while offering additional features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Governance rule enforcement (optional Roslyn or runtime validator)&lt;/li&gt;
&lt;li&gt;Queue-first routing (Kafka, RabbitMQ, Azure, AWS, GCP)&lt;/li&gt;
&lt;li&gt;Minimal dev-mode presets for fast local iteration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re actively working on a public benchmark suite that compares:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Serilog&lt;/th&gt;
&lt;th&gt;NLog&lt;/th&gt;
&lt;th&gt;Log4Net&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;CerbiStream&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structured logging&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Governance enforcement&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue-first routing&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Roslyn analyzer for log rules&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ &lt;em&gt;(optional)&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encryption support&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (AES/Base64)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimal dev mode toggle&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let me know what else you'd like to see compared in future benchmarks!&lt;/p&gt;

&lt;p&gt;In development: Azure Marketplace onboarding &amp;amp; enterprise governance dashboard&lt;/p&gt;

&lt;p&gt;🙏 I Need Your Feedback!&lt;br&gt;
I'd love your thoughts on:&lt;/p&gt;

&lt;p&gt;API clarity — is it intuitive enough?&lt;/p&gt;

&lt;p&gt;Would you use this for audit or security logs?&lt;/p&gt;

&lt;p&gt;What features would make this more useful to you?&lt;/p&gt;

&lt;p&gt;Would a CerbiShield dashboard help your team?&lt;/p&gt;

&lt;p&gt;Thanks for checking it out — and if you install it or give it a test, I’d really appreciate your feedback!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>logging</category>
      <category>devtools</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
