Clywell.Core.Logging 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Clywell.Core.Logging --version 1.0.0
                    
NuGet\Install-Package Clywell.Core.Logging -Version 1.0.0
                    
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="Clywell.Core.Logging" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Clywell.Core.Logging" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Clywell.Core.Logging" />
                    
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 Clywell.Core.Logging --version 1.0.0
                    
#r "nuget: Clywell.Core.Logging, 1.0.0"
                    
#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 Clywell.Core.Logging@1.0.0
                    
#: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=Clywell.Core.Logging&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Clywell.Core.Logging&version=1.0.0
                    
Install as a Cake Tool

Note: The tool simplified the command to ` cat > /Users/sodiqyekeen/Documents/dev/clywell-core/clywell-logging/README.md << 'ENDOFFILE'

Clywell.Core.Logging

NuGet License: MIT

Structured logging infrastructure with Serilog for the Clywell platform. Provides log enrichers, configuration helpers, and performance-optimized logging utilities with zero business logic - can be used in any .NET application.


Features

✅ Serilog Integration - Fluent configuration for Serilog with best practices
✅ Correlation & Request Tracking - Automatic correlation IDs and request IDs for distributed tracing
✅ Performance Optimized - IsEnabled() checks built into shorthand extension methods
✅ Sensitive Data Redaction - Automatic redaction of passwords, credit cards, API keys
✅ Multiple Sinks - Console, File, Seq, Application Insights
✅ Environment Enrichers - Machine name and log context enrichment
✅ Execution Time Logging - Built-in helpers for measuring operation duration
✅ Logging Scopes - Strongly-typed property scopes for tenant, user, and operation context
✅ ASP.NET Core Middleware - Track correlation IDs and request IDs across HTTP requests
✅ Testing Utilities - In-memory sink and assertion helpers for unit tests
✅ .NET 10.0+ - Modern C# features and latest language version
✅ 80%+ Test Coverage - Comprehensive unit tests with FluentAssertions


Installation

dotnet add package Clywell.Core.Logging

Quick Start

1. Basic Setup (ASP.NET Core)

using Clywell.Core.Logging.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.AddLogging();

var app = builder.Build();

app.UseRequestTracking(); // adds CorrelationId + RequestId middleware
app.UseRequestLogging();  // adds Serilog HTTP request logging

app.MapGet("/", (ILogger<Program> logger) =>
{
    logger.LogInformation("Hello from Clywell logging!");
    return "Hello World!";
});

app.Run();

AddLogging() with no arguments applies:

  • WithClywellDefaults() — correlation ID, request ID, environment enrichers, sensitive data redaction
  • WithConsoleSink() — human-readable console output
  • ReadFromConfiguration() — merges appsettings.json Serilog section if present

2. Custom Configuration

using Serilog.Events;

builder.AddLogging(config =>
{
    config
        .WithMinimumLevel(LogEventLevel.Debug)
        .WithConsoleSink(useJson: true)
        .WithFileSink("logs/app-.txt")
        .WithSeqSink("http://localhost:5341")
        .WithApplicationInsightsSink();
});

3. Manual Setup (Console App)

using Clywell.Core.Logging.Configuration;
using Serilog.Events;

ClywellLoggerConfiguration.Create()
    .WithMinimumLevel(LogEventLevel.Information)
    .WithConsoleSink()
    .WithCorrelationId()
    .WithSensitiveDataRedaction()
    .BuildAndSetGlobalLogger();

Log.Information("Application started");

Core Components

1. ApplicationBuilderExtensions

AddLogging — registers Serilog as the logging provider
// Default setup
builder.AddLogging();

// With custom configuration
builder.AddLogging(config =>
{
    config
        .WithMinimumLevel(LogEventLevel.Debug)
        .WithConsoleSink()
        .WithClywellDefaults();
});
UseRequestTracking — adds correlation ID and request ID middleware
app.UseRequestTracking();

Call this early in the pipeline so IDs are available for all logs in subsequent middleware.

UseRequestLogging — adds Serilog HTTP request logging
app.UseRequestLogging();

Logs every HTTP request with method, path, status code, elapsed time, host, scheme, remote IP, user agent, correlation ID, and request ID.


2. ClywellLoggerConfiguration

Fluent builder for Serilog, used inside AddLogging() or standalone for console apps.

ClywellLoggerConfiguration.Create()              // static factory; accepts optional IConfiguration
    .WithMinimumLevel(LogEventLevel.Information)
    .WithConsoleSink(useJson: false)             // false = human-readable, true = JSON
    .WithFileSink("logs/app-.txt", RollingInterval.Day)
    .WithSeqSink("http://localhost:5341")
    .WithApplicationInsightsSink(connectionString)
    .WithCorrelationId()                         // add CorrelationIdEnricher
    .WithRequestId()                             // add RequestIdEnricher
    .WithEnvironmentEnrichers()                  // MachineName + FromLogContext
    .WithSensitiveDataRedaction()                // SensitiveDataRedactionPolicy
    .WithClywellDefaults()                       // all 4 enrichers/policies in one call
    .OverrideMinimumLevel("Microsoft", LogEventLevel.Warning)
    .ReadFromConfiguration()                     // merge appsettings.json Serilog section
    .Build();                                    // returns Serilog ILogger

// Or set the global Serilog logger directly:
config.BuildAndSetGlobalLogger();

WithClywellDefaults() is shorthand for: WithCorrelationId() + WithRequestId() + WithEnvironmentEnrichers() + WithSensitiveDataRedaction()


3. LoggerExtensions

Performance-optimized shorthand methods on ILogger. Every method includes a built-in IsEnabled() guard to prevent unnecessary string allocations.

using Clywell.Core.Logging.Extensions;

logger.Trace("Entering {Method}", nameof(MyMethod));
logger.Debug("Processing item {ItemId}", itemId);
logger.Info("User {UserId} logged in", userId);
logger.Warning("Retry attempt {Attempt} for {Operation}", attempt, operation);
logger.Error("Failed to save order {OrderId}", orderId);
logger.Error(exception, "Unhandled error processing {OrderId}", orderId);
logger.Critical("Database unreachable");
logger.Critical(exception, "Fatal startup error");

These are drop-in replacements for the standard LogTrace, LogDebug, LogInformation, etc. with the automatic IsEnabled check built in.

Execution Time Logging
// Synchronous
var result = logger.LogExecutionTime("DatabaseQuery", () => db.QueryData());
// Logs: DatabaseQuery completed in 45ms

// Asynchronous
var data = await logger.LogExecutionTimeAsync("ApiCall",
    async () => await httpClient.GetAsync("https://api.example.com"));
// Logs: ApiCall completed in 230ms
Timed Scopes
using (logger.BeginTimedScope("ProcessOrder", new Dictionary<string, object>
{
    ["OrderId"] = orderId,
    ["CustomerId"] = customerId
}))
{
    // all logs here include the scope properties
}
// Logs: Starting ProcessOrder with properties { OrderId: 123, CustomerId: 456 }
// Logs: Completed ProcessOrder in 1234ms

4. LoggerScopeExtensions

Creates structured logging scopes. All log messages within a scope automatically carry its properties.

using Clywell.Core.Logging.Extensions;

// Single property
using (logger.BeginPropertyScope("OrderId", orderId))
    logger.Info("Order processing started");

// Two or three properties (tuples)
using (logger.BeginPropertyScope(("TenantId", tenantId), ("UserId", userId)))
    logger.Info("User action performed");

// Dictionary of properties
using (logger.BeginPropertyScope(new Dictionary<string, object?>
{
    ["Environment"] = env,
    ["Version"] = version
}))
    logger.Info("Deployment started");

// Params tuples (any number)
using (logger.BeginPropertyScope(
    ("Region", region),
    ("Service", service),
    ("InstanceId", instanceId)))
    logger.Info("Service registered");
Convenience Scopes
// Adds "TenantId" property
using (logger.BeginTenantScope(tenantId)) { ... }

// Adds "UserId" property
using (logger.BeginUserScope(userId)) { ... }

// Adds "TenantId" and "UserId" properties
using (logger.BeginTenantUserScope(tenantId, userId)) { ... }

// Adds "OperationName" (and optionally "OperationId") properties
using (logger.BeginOperationScope("PlaceOrder", operationId)) { ... }

5. Enrichers

CorrelationIdEnricher

Adds a CorrelationId property to every log entry.

  • Uses AsyncLocal<string?> — scoped to the current async execution context
  • If no value is set, a new GUID is generated automatically per log event
  • The CorrelationIdMiddleware reads X-Correlation-ID from the request header (or generates a GUID), stores it on the enricher, writes it to the response header, and stores it in HttpContext.Items["CorrelationId"]
using Clywell.Core.Logging.Enrichers;

// Set manually (e.g., in a background job or test)
CorrelationIdEnricher.CurrentCorrelationId = "my-correlation-id";
RequestIdEnricher

Adds a RequestId property to log entries when a value is set.

  • Uses AsyncLocal<string?> — only enriches when a value is present (no fallback GUID)
  • The RequestIdMiddleware reads X-Request-ID from the request header (or generates a GUID), stores it on the enricher, writes it to the response header, and stores it in HttpContext.Items["RequestId"]
using Clywell.Core.Logging.Enrichers;

RequestIdEnricher.CurrentRequestId = "my-request-id";

6. Middleware

Both middleware components are registered together via app.UseRequestTracking(), or individually:

app.UseMiddleware<CorrelationIdMiddleware>();
app.UseMiddleware<RequestIdMiddleware>();
Middleware Header read Header written HttpContext.Items key
CorrelationIdMiddleware X-Correlation-ID X-Correlation-ID "CorrelationId"
RequestIdMiddleware X-Request-ID X-Request-ID "RequestId"

7. Sensitive Data Redaction

SensitiveDataRedactionPolicy is a Serilog IDestructuringPolicy that scans string log values and replaces matched patterns with ***REDACTED***.

Default patterns:

Pattern Example input Result
Credit card 4532-1234-5678-9010 ***REDACTED***
SSN 123-45-6789 ***REDACTED***
Password field password: secret ***REDACTED***
API key field api_key: abc123 ***REDACTED***
Email + password combo user@example.com: secret ***REDACTED***
Enable via ClywellLoggerConfiguration
config.WithSensitiveDataRedaction(); // included automatically in WithClywellDefaults()
Enable via dependency injection
// Default — all built-in patterns
builder.Services.AddSensitiveDataRedaction();

// Custom configuration
builder.Services.AddSensitiveDataRedaction(options =>
{
    options
        .DisableCreditCardRedaction()
        .AddCustomPattern(@"\bINTERNAL_TOKEN\b");
});
SensitiveDataRedactionPolicyOptions
SensitiveDataRedactionPolicyOptions.Create()
    .AddCustomPattern(@"\bDATABASE_URL\b")
    .AddCustomPattern(@"\bAPI_TOKEN\b", RegexOptions.None)
    .DisableCreditCardRedaction()
    .DisableSocialSecurityRedaction()
    .DisablePasswordRedaction()
    .DisableApiKeyRedaction()
    .DisableEmailPasswordRedaction()
    .DisableAllDefaults()
    .Build(); // returns SensitiveDataRedactionPolicy
Static utility
var redacted = SensitiveDataRedactionPolicy.RedactSensitiveData("password: secret123");
// Returns: ***REDACTED***

8. Testing Utilities

The Clywell.Core.Logging.Testing namespace provides helpers for unit testing logging behaviour.

InMemoryLogSink

Captures Serilog log events during a test.

var sink = new InMemoryLogSink();

sink.LoggedEvents                               // all captured events
sink.GetEvents(LogEventLevel.Warning)           // at or above a level
sink.GetEventsForLevel(LogEventLevel.Error)     // at exactly a level
sink.GetEventsContaining("OrderId")             // by message template text
sink.GetEventsWithProperty("TenantId")          // by property name
sink.Clear()                                    // reset between tests
TestLoggerFactory

Creates Microsoft.Extensions.Logging.ILogger instances backed by an InMemoryLogSink.

// Logger + sink together (most common)
var (logger, sink) = TestLoggerFactory.CreateTestLoggerWithSink();

// Typed logger
var (logger, sink) = TestLoggerFactory.CreateTestLoggerWithSink<MyService>();

// Provide your own sink
var sink = new InMemoryLogSink();
var logger = TestLoggerFactory.CreateTestLogger(sink, LogEventLevel.Debug);
LogAssertions

Extension methods on InMemoryLogSink for test assertions.

sink.ShouldHaveLogged(LogEventLevel.Information);
sink.ShouldHaveLogged(LogEventLevel.Error, "OrderId");
sink.ShouldNotHaveLogged(LogEventLevel.Warning);
sink.ShouldHaveProperty("CorrelationId");
sink.ShouldHavePropertyValue("TenantId", "acme");
sink.ShouldHaveException<InvalidOperationException>();

Example test:

[Fact]
public void LogsUserIdInScope()
{
    var (logger, sink) = TestLoggerFactory.CreateTestLoggerWithSink<UserService>();

    using (logger.BeginUserScope("user-123"))
    {
        logger.Info("Action performed");
    }

    sink.ShouldHaveLogged(LogEventLevel.Information, "Action performed");
    sink.ShouldHavePropertyValue("UserId", "user-123");
}

appsettings.json Configuration

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/app-.txt",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 31
        }
      }
    ],
    "Enrich": ["FromLogContext", "WithMachineName"]
  },
  "Logging": {
    "Seq": {
      "ServerUrl": "http://localhost:5341"
    }
  },
  "ApplicationInsights": {
    "ConnectionString": "InstrumentationKey=..."
  }
}

ReadFromConfiguration() is called automatically by AddLogging(), or explicitly:

builder.AddLogging(config => config.ReadFromConfiguration().WithClywellDefaults());

Environment-Specific Examples

Development

builder.AddLogging(config =>
{
    config
        .WithMinimumLevel(LogEventLevel.Debug)
        .WithConsoleSink()
        .WithFileSink("logs/dev-.txt")
        .WithClywellDefaults();
});

Production

builder.AddLogging(config =>
{
    config
        .WithMinimumLevel(LogEventLevel.Information)
        .WithConsoleSink(useJson: true)
        .WithApplicationInsightsSink()
        .WithClywellDefaults()
        .OverrideMinimumLevel("Microsoft", LogEventLevel.Warning)
        .OverrideMinimumLevel("System", LogEventLevel.Warning);
});

Middleware Pipeline Order

var app = builder.Build();

app.UseRequestTracking(); // FIRST — sets CorrelationId and RequestId for all logs below
app.UseRequestLogging();  // SECOND — logs each request with enriched properties

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

Best Practices

Use structured logging

// ❌ BAD: string interpolation loses structure
logger.LogInformation($"User {userId} logged in");

// ✅ GOOD: named placeholder preserves structure
logger.LogInformation("User {UserId} logged in", userId);

Use shorthand extensions for expensive log values

// ❌ BAD: serialization always runs even if Debug is disabled
logger.LogDebug($"Query result: {JsonSerializer.Serialize(largeObject)}");

// ✅ GOOD: Debug() checks IsEnabled first; serialization only runs when needed
logger.Debug("Query result: {Result}", JsonSerializer.Serialize(largeObject));

Use execution time helpers instead of manual stopwatches

// ❌ BAD: boilerplate
var sw = Stopwatch.StartNew();
var result = await database.QueryAsync();
sw.Stop();
logger.LogInformation("Query took {ElapsedMs}ms", sw.ElapsedMilliseconds);

// ✅ GOOD
var result = await logger.LogExecutionTimeAsync("DatabaseQuery", () => database.QueryAsync());

Use scopes to correlate log groups

// All logs inside this scope automatically include TenantId and UserId
using (logger.BeginTenantUserScope(tenantId, userId))
{
    logger.Info("Processing request");
    await ProcessAsync();
    logger.Info("Request complete");
}

Troubleshooting

Logs Not Appearing

  1. Check log level configuration
  2. Ensure middleware is added to the pipeline
  3. Verify sinks are configured correctly
// Debug: Enable verbose logging temporarily
config.WithMinimumLevel(LogEventLevel.Verbose);

Correlation IDs Not Working

Ensure middleware is added early in the pipeline:

app.UseRequestTracking(); // Must be early
app.UseRouting();
app.UseAuthorization();
app.MapControllers();

And confirm the enricher is registered:

config.WithCorrelationId();
// Or use defaults:
config.WithClywellDefaults();

High Memory Usage

Reduce log verbosity in production and rely on the built-in IsEnabled guards:

config
    .WithMinimumLevel(LogEventLevel.Information)
    .OverrideMinimumLevel("Microsoft", LogEventLevel.Warning)
    .OverrideMinimumLevel("System", LogEventLevel.Warning);

// Shorthand extensions check IsEnabled — no allocation when level is disabled
logger.Debug("Result: {Data}", GetExpensiveData());

Requirements

  • .NET 10.0+
  • Serilog 4.0+
  • ASP.NET Core 10.0+ (for AddLogging, UseRequestTracking, UseRequestLogging)

Dependencies

  • Serilog
  • Serilog.AspNetCore
  • Serilog.Sinks.Console
  • Serilog.Sinks.File
  • Serilog.Sinks.Seq
  • Serilog.Sinks.ApplicationInsights
  • Serilog.Enrichers.Environment
  • Serilog.Enrichers.Thread
  • Microsoft.Extensions.Logging.Abstractions

License

MIT License - See LICENSE file


Contributing

This is an infrastructure package with no business logic. Contributions are welcome!

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Ensure 80%+ code coverage
  5. Submit a pull request

Support

For issues and questions, open a GitHub Issue.


Built with ❤️ by the Clywell team ENDOFFILE`, and this is the output of running that command instead:      ...  clywell-logging  main  ?5 ~5  09:24  0.131s  cat > / Users/sodiqyekeen/Documents/dev/clywell-core/clywell-logging/README.md << 'ENDOF FILE'

Clywell.Core.Logging

[NuGet](https://ww w.nuget.org/packages/Clywell.Core.Logging/) [License: MIT](https:/ /opensource.org/licenses/MIT)

Structured logging infrastructure with Serilog for the Clywell platform. Provi des log enrichers, configuration helpers, and performance-optimized logging util ities with zero business logic - can be used in any .NET application.


Features

✅ Serilog Integration - Fluent configuration for Serilog with best practi ces
✅ Correlation & Request Tracking - Automatic correlation IDs and request IDs for distributed tracing
✅ Performance Optimized - IsEnabled() checks built into shorthand exten sion methods
✅ Sensitive Data Redaction - Automatic redaction of passwords, credit car ds, API keys
✅ Multiple Sinks - Console, File, Se# Clywell.Core.Logging

[NuGet](hm [![NuGet](https://im Ti![License: MIT](https://img.shields.io/badge/License-M IT-yellow.svg)

Structured es Structured logging infrastructure with Serilog for the Clywell platform. Provi des log enrichers, configurues

Features

✅ Serilog Integration - Fluent configuration for Serilog with best practi ces
✅ Correlation & Request Tracking - Automatic correlation IDs and request IDs for distributed tracing
✅ **Performanceest #wit ✅ **Serser✅ Correlation & Request Tracking - Automatic correlation IDs a nd request IDs --✅ Performance Optimized - IsEnabled() checks built into shorthand extension methods
✅ **Sensitibu✅ Sensitive Data Redaction - Automatic redaction of passwor ds, credit cards, API keys );✅ Multiple Sinks - Console, File, Se# Clywell. Core.Logging

[![NuGet](https://img.shieng [![NuGet](https://img.shields.io/nuget/v/Clywell.Core.Logging.gge[![NuGet](htt ps://im Ti[![License: MIT](https://im"Hello from Clywell l Structured es Structured logging infrastructure with Serilog for the Clywell platform. Provi des log enrichers, configurues

<ffffffff> cStructured lD,---

Features

✅ Serilog Integration - Fluent configuration for Serilog with best practi ces
✅ le #utp ✅ **SerFro✅ Correlation & Request Tracking - Automatic correlation IDs a nd request IDs Cu✅ **Performanceest #wit ✅ **Serser✅ Correlation & Request Tracking - Automatic correlation IDs a nhM#wit ✅ **Serser<ffffffff>L✅l.✅ **Sensitibu✅ Sensitive Data Redaction - Auto matic redaction of passwords, credit cards, API keys );✅ Multiple Sinks - C onsole, File, Se# Clywell.Core.Logging

[![NuGet](httpan [![NuGet](https://img.shieng [![NuGet](https://img.shields.io/nuget/v/Clywell.Core.Logging.gge[![NuGet](htt ps://im Ti[![License: MIT](https://im"Hello from Clywell l StrucInf[![NuGet](https://img.shielinStructured es Structured logging infrastructure with Serilog for the Clywell platform. Provi des log enrichers, configurues

<ffffffff> cStru `Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ Serilog Integration - Fluent configuration for Serilog withpr <ffffffff>ide

Features

✅ *aul ✅ **Serild✅ le #utp ✅ **SerFro✅ Correlation & Request Tracking - Automatic correlaton#utp ✅ #wit ✅ **Serser✅ Correlation & Request Tracking - Automatic correlation IDs a nhM#wit ✅ **Serser<ffffffff>L✅l.<ffffffff>e✅st✅ **Serser<ffffffff>L✅l.✅ **Sensit ibu✅ Sensitive Data Redaction - Automatic redacra [![NuGet](httpan [![NuGet](https://img.shieng [![NuGet](https://img.shields.io/nuget/v/Clywell.Core.Logging.gge[![NuGet](htt ps://im Ti[![License: MIT](https://im"Hello from Cly`csharp app.UseRequ[![NuGet](https``[![NuGet](https://img.shielitStrucInf[![NuGet](htt ps://img.shielinStructured es Structured logging infrastructure with Serilog for the Clywell platform. Provi ellLoggeStructured logging infrastructure with Serilog foin---

<ffffffff> cStru `Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ Serilog Integration - Fluent co
<ffffffff> //`Strucc <ffffffff> cStructured lDopt

Features

✅ *n

✅ **Sernim<ffffffff>ide

Features

✅ *aul ✅ **Serild✅ le #utp ✅ **SerFro✅ *se##
<ffffffff> // f✅ **Shu#utp ✅ **SerFroe ✅SO ✅ #wit ✅ **Serser✅ Correlation & Request Tracking - Automatic cht✅ **Sersho✅ **Serser<ffffffff>L✅l.<ffffffff>e✅st✅ **Serser<ffffffff>L✅l.✅ **Sensitibu✅ **Sensitive Data [![NuGet](httpan [![NuGet](https://img.shieng [![NuGet](https://img.shields.io/nuget/v/Clywell.Core.Logging.gge[![NuGnr[![Nu Get](httpsEn[![NuGet](https://img.shiel app.UseRequ[![NuGet](https``[![NuGet](h ttps://img.shielitStrucInf[![NuGet](https://img.shielinStructured es Structured logging infhClywellStructured logging infrastructure with Serilog f or the Clywell platform. ProviellLoggeStructured logging iof <ffffffff> cStru `Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ Serilog Integration - Fluent co
<ffffffff> //Strucc <ffffffff> cStructured lDopt Stru
<ffffffff> cStructured lD//

Features

✅ *gge ✅ **Seret <ffffffff> //`Strucc <ffffffff> cStructured lDopt

Featig<ffffffff> cStructurtG## Features

✅ *

✅ *n

llD ✅ts()## Features

<ffffffff>o ✅ *aul rre✅ *nId(#utp ✅ **SerFroId✅ +<ffffffff> // f✅ **Shu#uer✅ **SerFroe ✅SO ✅aR✅ **S erser✅ **Correlationer[![NuGet](https://img.shieng [![NuGet](https://img.shields.io/nuget/ery method includes a built-in IsEnabl ed() guard to prevent unnecessary string allocations.

using Clyw[![NuGet](https://img.shiel;
Structured logging infhClywellStructured logging infrastructure with Serilog f

or the Clywell platform. ProviellLoggeStructured logging iof

<ffffffff> cStru `Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ **Serilog Integratiio<ffffffff> cStru `Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ Serilog Integration - Fluent co
<ffffffff> //Strucc <ffffffff> cStructured lDoptggStructi <ffffffff> cStructured lDeac

Features

✅ *tic ✅ **Seron,<ffffffff> //Strucc <ffffffff> cStructured lDopt Strdr<ffffffff> cStructurce `Stru
<ffffffff> cStrda<ffffffff> cStrucrace## Features

✅ *gI ✅ *gge `, ✅ **Sth<ffffffff> cStructured lDopt

ed## Featig<ffffffff> cStruct

✅ *

✅ *n

llD ✅ts()##sha

<ffffffff> Sy llDnous✅r <ffffffff>o ✅ *aul rrogE✅utrre✅ ("✅ **SerFroId<ffffffff>([![NuGet](https://img.shields.io/nuge t/ery method includes a built-in IsEnabled() guard to prevent unnecessary stri ng allocatipi

using Clyw[![NuGet](https://img.shiel;
Structured logging infhClywellStructured logging infrastructure with Serilog f

or copusing ClshStructured logging infhClywellStructuoc<ffffffff> cStru

`Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ **Serilog Integratiio<ffffffff> cStru `Structured lCo---

<ffffffff> cStructured lD,--- t`Strucpe <ffffffff> cStructured lDLog

Features

✅ *Ord <ffffffff>with prope`Structured lCo---

<ffffffff> cStructurd: <ffffffff> cStructured lDomp

Features

✅ *in ✅ **Ser

-<ffffffff> //Strucc <ffffffff> cStructured lDoptggStrucs <ffffffff> cStructurlo<ffffffff> cStruct ured lDeac

Featues## Features

✅ *to ✅ *tic car✅ **Spr<ffffffff> cStructured lDopt in Strdr<ffffffff> cStructgi<ffffffff> cStrda<ffffffff> cStrucrace## Fea tures ty ✅ *gI ✅ *gge , ✅ **Sthope✅ *grI`, ✅ er## ed## Featig<ffffffff> cStruct

✅ oc# ✅ *

✅ *n

llDTwo

<ffffffff>ree llDerti✅(t <ffffffff> Sy llg (llDnou.B<ffffffff>o ✅ *ayS✅e(rrogE<ffffffff>I```csharp using Clyw[![NuGet](https://img.shiel; Structured logging infhClywellStructured logging infrastructure with Serilog f or copusing ClshStructured logging infjeusing Cl Structured logging infhClywell Structu"]`Structured lCo---

<ffffffff> cStructured lD,---

Features

✅ **Serilog Integratiio<ffffffff> cStru `Structured lCo---opertyScope( ("Region", region) <ffffffff> cStructured lD se

Features

✅ *nce ✅ **Sernce`Structured lCo---

<ffffffff> cStructurre <ffffffff> cStructured lD### t`Strucpe <ffffffff> cStrucs <ffffffff> cStructp

Features

✅ * p ✅ *Ord ing<ffffffff>with r. <ffffffff> cStructurd: <ffffffff> cStructured ..<ffffffff> cStructure "## Features

✅ *si ✅ *in .Be✅ **SSc -<ffffffff> //`SId)<ffffffff> cStructure/ ## Featues## Features

✅ *to ✅ *tic car✅ **Spr<ffffffff> cStrucen ✅ *to ✅ *tic cad, ✅ *t))car<ffffffff> } in Strdr<ffffffff> cStructgi<ffffffff> cStopty ✅ *gI ✅ *gge , ✅ **Sthope✅ *grI, ✅ er## pe<ffffffff>t✅ *gpe, ✅ Or# ✅ oc# ✅ *

✅ *n

llDTwo

<ffffffff>ree llDerti✅

##<ffffffff>Corre

<ffffffff>nId licher

<ffffffff>rea `llDertat<ffffffff> Sy llgerllg (lev✅ *ayS✅ry.

  • using Clyw[![NuGet](https://im sStructured logging infhClywellStrucn co <ffffffff> cStructured lD,---

Features

✅ **Serilog Integratiio<ffffffff> cStru `Structured lCo---opertyScope( ("Region", region) <ffffffff> cStructured lD se

Features

✅ *nce ✅ **Sernce`Structsto

Features

✅ *her ✅ **Sert t`Structured lCo---opertyScope( es ("Region", region) <ffffffff> cStrrr<ffffffff> cStructured lD se #rp## Features

✅ *e. ✅ *nce ric✅ **S// Set manually (e.g., in a backgr<ffffffff> cStructurete<ffffffff> c Strucs <ffffffff> cStructp

Featrr<ffffffff> cStrucla## Featur"m

✅ * p <ffffffff>on✅ *O``ing<ffffffff>wi R<ffffffff> cStructuric<ffffffff> cStructur eR ✅ *si ✅ *in .Be✅ **SSc -<ffffffff> //SId)val✅ *ise.Be✅ se-<ffffffff> //SId)<ffffffff>al ✅ *to ✅ *tic car✅ **Spr<ffffffff> cStrucen ✅ pr✅ *t(ncar✅ ac✅ *to ✅ *tic cad,tI✅ *tewcad, <ffffffff>d in Strdr<ffffffff> cStrm ✅ *gI ✅ *gge , ✅ **Sthope<ffffffff> ✅ *g s, ✅ t ✅ oc# ✅ *

✅ *n

llDTwo

<ffffffff>ree llDerti✅nd stor✅ * in

<ffffffff>pCo llD.Ite <ffffffff>requellDert`

u
<ffffffff>nId 
elllicherLo
<ffffffff>r.Enllgerllg (lev✅ *ayS<ffffffff>c
- using Clyw[![NuGet](htt-re<ffffffff> cStructured lD,---

## Features

✅ **Serilog Integratiio<ffffffff> cStru
`Streg
## Features

✅ *a `
✅ **Serues`Structured lCo---opertyScope(

`    ("Region", region)
<ffffffff> cStrrr<ffffffff> cStructured lD se
#);## Features

✅ *<R
✅ *nce
ddl✅ **S);## Features

✅ *herHe
✅ *her
| H✅ **Sries    ("Region", region)
<ffffffff> cStrrr<ffffffff> cStruc|-<ffffffff> cStrrr<ffffffff> cStructured ld

M#rp## Features

✅ *e. <ffffffff>- ✅ *e. ✅ ela✅ *ID`ric✅ rr<ffffffff> cStructp

Featrr<ffffffff> cStrucla## Featur"m

✅ * p <ffffffff>on✅ *Oing<ffffffff>-## Featrreq✅ * p <ffffffff>on✅ *Oing<ffffffff>wi Rti<ffffffff>on<ffffffff> Redaction

SensitiveDataRedactionPolicy is a Se✅ *iI.Be✅ tu-<ffffffff> //SId)v t✅ *to ✅ *tic car✅ **Spr<ffffffff> cStrucen <ffffffff>t✅ *tatcar✅ it✅ pr✅ *t(ncar✅ **✅ *tic cad,tI✅ *tewcad, <ffffffff> cad,tI<ffffffff>e✅ *gge , ✅ **Sthope<ffffffff> ✅ *g s, ✅ t ✅ oc#32`, ✅ 67✅ *

✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9 llD*RED <ffffffff>r***llDertasin

<ffffffff>pCo llD.Ite <ffffffff>d sellD.It| <ffffffff>reqDA

u
<ffffffff>I u
<ffffffff>nIdd | elllicey<ffffffff>r.Enllg| - using Clyw[![NuGet](htt-re<fffff

fff> as

Features

✅ **Serilog Integratiio<ffffffff> cStru RED ✅ **Ser|

`Streg

Features

✅ *a <ffffffff>n## Feat ✅ *a sha✅ **Sig ` ("RegiveDataRedaction(); // included a<ffffffff> cStrrr<ffffffff> cStruct ured yw#);## Features

✅ *<R <ffffffff>b ✅ *<R ✅ enc✅ *nctddl✅ c ✅ *herHe ✅ *her |ll ✅ *her pa| H✅ bu<ffffffff> cStrrr<ffffffff> cStruc|-<ffffffff> cStrrr<ffffffff> cStr uctct ✅ *e. <ffffffff>- ✅ *e. ✅ ela✅ *IDric✅ rr<ffffffff> cStructpiti<ffffffff>- <ffffffff>e✅ti✅ elio## Featrr<ffffffff> cStrucla## Featur"m <ffffffff>l✅ * p <ffffffff>on✅ *Oing<ffffffff>-## <ffffffff>on<ffffffff>t<ffffffff>on✅ *O ing<ffffffff>wi Rti<ffffffff>on<ffffffff> Reda); SensitiveDataRedactionPolicy is a SeyOp✅ *tic car✅ **Spr<ffffffff> cStrucen <ffffffff>t✅ *tatcar✅ it✅ pr✅ *t(ncar✅ tocar✅ n(<ffffffff>t✅ *tatcar✅ it cad,tI✅ *tewcad, <ffffffff> cad,tI<ffffffff>e✅ *gge , ✅ **StNo, ✅ .DisableCreditCardRedaction()

✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac llD)

<ffffffff>rsablllDertyR <ffffffff>9` () llD*.Dis<ffffffff>r**ai <ffffffff>pCo llD.Ite n()llD.ItDi<ffffffff>d sll sfa```csharp u <ffffffff>I u );u <ffffffff>I u rns <ffffffff>nit## Features

✅ **Serilog Integratiio<ffffffff> cStru RED ✅ **Ser| r ✅ **Ser SeRED ✅ **Ser|

`Streg

Featuct<ffffffff>s

Streg #("p## Ferd ✅ *a 3")<ffffffff>n## tu✅ *a sDAsha✅ `` ("Regi# ✅ *<R <ffffffff>b ✅ *<R ✅ enc✅ *nctddl✅c ✅ *herHe ✅ *her |ll ✅ *her ers<ffffffff>r uni✅es✅ enog✅ *herHe ✅ *her |llIn✅ *her Si|ll ✅ptpa| H✅ bug ✅ *e. <ffffffff>- ✅ *e. ✅ ela✅ *IDric✅ rk = new InMem✅Lo✅ el);<ffffffff>e✅ti✅ elio## Featrr<ff ffffff> cStrucla## Fe <ffffffff>l✅ * p <ffffffff>on✅ *O``ing<ffffffff>-## <ffffffff>on<ffffffff>t<ffffffff>(L<ffff ffff>on✅ *OelSensitiveDataRedactionPolicy is a SeyOp✅ *tic car✅ **Spr<ffffffff> cStogcar✅ **Spr<ffffffff> cStrucen <ffffffff>t✅ *tatcar✅ it✅ .G<ffffffff>t✅ *tatcar✅ itrd, ✅ **StNo`, ✅
.DisableCreditCardRedaction()

✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac s

✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9 r set llDeen <ffffffff>re```llDert <ffffffff>9 erFllD*RE <ffffffff>dacesllD) os
.E<ffffffff>e<ffffffff>9` () llD*.ILllD*.Disns<ffffffff>pCo llked by llD.ItMen()llDgS sll sfa```csaru <ffffffff>I u );u <ffffffff>I nk t);u he<ffffffff>(mrns co ✅ **Serilog InteginkRED ✅ **Ser| r ✅ **Ser SeRtL<ffffffff>er ✅ **()<ffffffff> ✅ **Ser|

`Sr

Streg #er,## Fe) Streg #("p##ac#("p#Cr✅ *a 3gg3")<ffffffff>ninsDAsha✅ `` (" P`` ("Rur✅ *<R <ffffffff>b s<ffffffff>b <ffffffff>e✅nM✅ enog✅ *herHe ✅ *her |llst✅ *her to|ll ✅teers<ffffffff>r unisi✅ *her |llIn✅ *her Si|ll ✅p##|llIn<ffffffff>eSi|ll ✅ptpen<ffffffff>- ✅ *e. ✅ ela✅ *IDrink✅or✅ elas<ffffffff>on✅ *O``ing<ffffffff>-## <ffffffff>on <ffffffff>t<ffffffff>(L<ffffffff>on✅ *OelSensitiveDataRedactionPolicy is aHav eLogged(LogEventLecar✅ **Spr<ffffffff> cStogcar✅ **Spr<ffffffff> cStrucen <ffffffff>t✅ *tatcar✅ it✅ .G<ffffffff>t✅ *tatcar✅ itrd`, ("<ffffffff>t✅ *tatcar✅ it✅ .G<ffffffff>t✅ *tatcVa

✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac s
ception>();


**Example test:*


` 
llDarp

<ffffffff>re
pullDertoi
<ffffffff>9`  erIllD*REpe<ffffffff>dac  s  

(l
<ffffffff>er 
llDk) =
<ffffffff>reoggllDertor
<ffffffff>9`  Tes r
setrWsthllDk<<ffffffff>re`rv<ffffffff>9`  erFllD*Rin<ffffffff>dacesllD)
 osse os  
.E<ffffffff>er-.E<ffffffff>))llD*.ILllD*.D  llked by llD.ItMenn perfo<ffffffff
I u
);u
<ffffffff>I nk t);u
he<ffffffff>(mrns co
✅ *(L);u
en<ffffffff>evhe<ffffffff>(formati✅ **Seril p✅ **Ser|
r 
✅ **Ser ulr 
✅ **er<ffffffff>V✅ **()<ffffffff>
✅ **Ser-1✅ **Ser``
`Sr

`St appsett#er,#js#("p##ac#("p#Cr<ffffffff>
3gg3")<ffffffff>ninsDAsha✅  {``    (" P``    ("Rur{
<ffffffff>b
 s<ffffffff>b
<ffffffff>e✅nM✅ enoon s<ffffffff> <ffffffff>e<ffffffff>v✅ *her
|llst✅ *her
toso|llst<ffffffff>rto|ll ✅tee  |llIn✅ *her
Si|ll ✅p##|llIn  Si|ll ✅p##eT✅ *e.
✅ ela✅ *ID`rink✅or✅ el",✅ el  <ffffffff>t✅ *tatcar✅ it✅ .G<ffffffff>t 

✅ *tatcar✅ itrd`, ("<ffffffff>t✅ *tatcar✅ it✅ .G<ffffffff>t✅ *tatcVa

✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac s
ception>()
✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac s
ception>();


**Ex          "reta 
llDileC
<ffffffff>remitllDert  
<ffffffff>9`     llD*RE  <ffffffff>dac  s  
cchce [```

**Exant
*t",

` 
llDarp

<ffffffff>e"]l  
<ffffffff>r"Lopullg"<ffffffff>9`  erSe
(l
<ffffffff>er 
llDk) =
<ffffffff>reogglltp:<ffffffff>lllDkho<ffffffff>reo1"<ffffffff>9`  Tes r
seApsetrWsthllDsi osse os  
.E<ffffffff>er-.E<ffffffff>))llD*.ILllD*.D  llked by lKe.E<ffffffff>er-.E}
);u
<ffffffff>I nk t);u
he<ffffffff>(mrns co
✅ *(L);u
en<ffffffff>evhe<ffffffff>(formatby<ffffffff>Adhe<ffffffff>(mrns `,✅ *(L);u
tlen<ffffffff>evhe<ffffffff>ar 
✅ **Ser ulr 
✅ **er<ffffffff>V✅ **()<ffffffff>
ea<ffffffff>r✅ **er<ffffffff>V<ffffffff>n✅ **Ser-1✅ **Serts`Sr

`St appsett#er,#ir
`ment-Specific Examples

### Development<ffffffff>b
 s<ffffffff>b
<ffffffff>e✅nM✅ enoon s<ffffffff> <ffffffff>e<ffffffff>v✅    s<ffffffff>i<f

fffffff>e<ffffffff> |llst✅ *her

toso|llst<ffffffff>rttLevel.Debtoso|llst<ffffffff>.WSi|ll ✅p##|llIn Si|ll ✅ p##eT✅ *e"l✅ ela✅ *ID`rink✅or✅ el",✅ el ul ✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac s
ception>()
✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac

llDithC <ffffffff>reSinllDerJso <ffffffff>9`
llD*RE.W<ffffffff>daclis
cnIceig✅ *n

l
llD.Wit <ffffffff>rellDllDerts( <ffffffff>9` .llD*REde<ffffffff>dacmLs
c"Mcero```

**Ex Ev tLellDileC <ffffffff>remitll <ffffffff>remid<ffffffff>9` llDRSycchce [```

**Exant *t",

` ); **Exant

--*t",

Mi ` eware <ffffffff>eine<ffffffff>r"Lop``(l <ffffffff>er llDk) = <ffffffff>reoer<ffffffff>ullDk);<ffffffff>reoUsseApsetrWsthllDsi osse os
.E<ffffffff>er-.E<ffffffff>))re.E<ffffffff>er-.E<ffffffff>))llD*.ILllD*.D a);u

<ffffffff>I nk t);u he<ffffffff>(mrns co ✅ *(L);u en<ffffffff>evhe<ffffffff><ffffffff>P lhe<ffffffff>(mrns eq✅ *(L);u nren<ffffffff>evhe<ffffffff>etlen<ffffffff>evhe<ffffffff>ar ✅ **Ser ulr ✅ **er<ffffffff>V<ffffffff>e✅ **Ser ulr pp✅ **er<ffffffff>V<ffffffff>iea<ff ffffff>r✅ **er<ffffffff>V<ffffffff>nle St appsett#er,#ir ment-Specific Examples s

`ment-Specific Exd

Development<ffffffff>b

❌ s<ffffffff>b <ffffffff>e✅nM✅po<ffffffff>e<ffffffff> toso|llst<ffffffff>rttLevel.Debtoso|l lst<ffffffff>.WSi|ll ✅p##|llIn Sid ✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`
llD*RED <ffffffff>dac s
ception>()
✅ *n

llDTwo

<ffffffff>ree llDerti-4

<ffffffff>9`

llDse s <ffffffff>rand llDertio <ffffffff>9` xpellD*RElo<ffffffff>dacess
ccscerp✅ *n

ll:
llDliza <ffffffff>ralwallDerts <ffffffff>9 DebllD*s di<ffffffff>dac l .LllDeb<ffffffff>reSue<ffffffff>9
llDRnS llDzecnIceig✅ *n

l ec l
llD.<ffffffff><ffffffff> GllD. D<ffffffff>rel c<ffffffff>9` .llD*R fc"st; s erialization only runs **Ex Ev ed *tLell.D<ffffffff>remitlly **Exant *t",

` ); **Exant

--*t",

Mi ` ewaregeO*t",

);


**E U
--*t"cut
Mi
`ime`he<ffffffff>einens<ffffffff>er 
llDk) =
<ffffffff>rpwllDkes<ffffffff>reosh.E<ffffffff>er-.E<ffffffff>))re.E<ffffffff>e

r-.E<ffffffff>))llD*.ILllD*.D a);u

<ffffffff>I tN<ffffffff>I nk t);u he<ffffffff>(mrns co ✅ *(L);u en<ffffffff>evhe<ffffffff>;he<ffffffff>(mrns ; ✅ *(L);u nfen<ffffffff>evhe<ffffffff>Qnren<ffffffff>evhe<ffffffff>etlen<ffffffff>evhe<f fffffff>ar ✅ **SMi✅ **Ser ulr ✅ **er<ffffffff>Vvar✅ **er<ffffffff>V<ffffffff>tSt appsett#er,#ir ment-Specific Examples s

ment-Specific Exd #Asment-;


### Uss

`ment-Specific Exd log g### Development<ffffffff>/  ❌ s<ffffffff>b
<ffffffff>e✅nis<ffffffff>e✅nM<ffffffff>o 
llDTwo 

<ffffffff>ree 
llDerti-4

<ffffffff>9`  
llD*RED
<ffffffff>dac
s  
ception>()  
✅ *n
 
llDTwo rId)
<ffffffff>re  lllDertIn
<ffffffff>9`  essllD*REqu<ffffffff>dac
 s  
caicePr✅ *n
 
ll); 
llDlogg
<ffffffff>reo("llDertt 
<ffffffff>9`

");
 
l``

-<ffffffff>ran R<ffffffff>9`  xpellD*R**ccscerp✅ *n
 
ll:  
llDliz+* 
ll:  
llDlT CollDl0.<ffffffff>ralfo<ffffffff>9`  DebllD*s `l    
.LllDeb<ffffffff>reSue<ffffffff>e.Llles  llD*RnS  llD*zecnIcep 
l   ec 
l    
llD.<ffffffff><ffffffff> GllD. ilogl    
tCllD.
-**Ex Ev
ed
*tLell.D<ffffffff>remitlly 
**Exant
*t",

` );
**Exant

--*t",
q`
ed
*tLil*g.**Exant
*t",

` );
si*t",

- 
` ril**EEn
--*t"s.E
Mi
`nme`t`
);

**E nrihers.Th--*t Mi icrosftllDk) = <ffffffff>rpwllDkesAb<ffffffff>rpwio<ffffffff>I tN<ffffffff>I nk t);u he<ffffffff>(mrns co ✅ *(L);u en<ffffffff>evhe<ffffffff>;he<ffffffff>(mrns ; --he<ffffffff>(mrns co ✅ng✅ *(L);u n en<ffffffff>evhe<ffffffff>t✅ *(L);u nfen<ffffffff>evhe bnfen<ffffffff>evhog✅ **SMi✅ **Ser ulr ✅ **er<ffffffff>Vvar<ffffffff> ✅ **er<ffffffff>Vvar✅ **erte`ment-Specific E xamples s

`ment-Specific Exd sts

ment-Specific Exd cover#Asment-;


##ll```

### 
-
#

#
`mentort<ffffffff>e✅nis<ffffffff>e✅nM<ffffffff>o 
llDTwo 

<ffffffff>ree 
llDerti-4

<ffffffff>/cllDTwo 

<ffffffff>ree 
llDs:
<ffffffff>reub.llDertyw
<ffffffff>9`  ellllD*REng<ffffffff>dacs)s  
ccucent✅on: [docs/getting-s<ffffffff>re  lll(d<ffffffff>9`  essllD*Rrt s  
caicePr✅ *n
 
llthcai<ffffffff><ffffffff>
ll); 
llDlywelllDlam<ffffffff>reoOF<ffffffff>9`
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
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.1.1 257 4/18/2026
1.1.0 236 3/8/2026
1.0.0 137 2/25/2026