Nedo.AspNet.Logging.Serilog 1.1.0

dotnet add package Nedo.AspNet.Logging.Serilog --version 1.1.0
                    
NuGet\Install-Package Nedo.AspNet.Logging.Serilog -Version 1.1.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="Nedo.AspNet.Logging.Serilog" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nedo.AspNet.Logging.Serilog" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Nedo.AspNet.Logging.Serilog" />
                    
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 Nedo.AspNet.Logging.Serilog --version 1.1.0
                    
#r "nuget: Nedo.AspNet.Logging.Serilog, 1.1.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 Nedo.AspNet.Logging.Serilog@1.1.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=Nedo.AspNet.Logging.Serilog&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Nedo.AspNet.Logging.Serilog&version=1.1.0
                    
Install as a Cake Tool

Nedo.AspNet.Logging.Serilog

Platform-standard Serilog configuration for ASP.NET Core. Two extension methods replace the ~40 lines of Serilog setup boilerplate that every service on the platform would otherwise paste into Program.cs.

dotnet add package Nedo.AspNet.Logging.Serilog

Quickstart

using Nedo.AspNet.Logging.Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.UseNedoLogging();                   // ← console (color-themed) + JSON file sink
// … other services

var app = builder.Build();

app.UseNedoLogContext();                    // ← RequestId / TenantId / etc. on every log line
// … other middleware
app.Run();

What the standard config does

UseNedoLogging():

  • Console sink with AnsiConsoleTheme.Code colorization and the platform output template:
    {Timestamp} [{Level:u3}] {Code} {Message} (req=… machine=… pid=… tid=…)
    {Exception}
    
  • File sink at logs/app-.json, daily rolling, 14-day retention, CompactJsonFormatter — one JSON object per event for log aggregators.
  • Enrichers: FromLogContext, WithMachineName, WithProcessId, WithThreadId.
  • Level overrides:
    • Microsoft.AspNetCore → Warning (silences routing/hosting noise)
    • Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware → suppressed (silences ASP.NET's built-in exception logger — useful when your service has its own structured exception handler that emits the same event, since otherwise every unhandled exception lands twice in the logs)
  • Code defaults to - for non-Nedo log events so the column stays aligned.

UseNedoLogContext():

  • Pushes RequestId (HttpContext.TraceIdentifier), RequestPath, and configured header echoes (default: X-Tenant-Id → TenantId, X-Client-Id → ClientId, X-Correlation-Id → CorrelationId) into Serilog.Context.LogContext. Every log line emitted during the request — yours, EF Core's, an HTTP client's — picks them up.

Customizing

builder.UseNedoLogging(opts =>
{
    opts.JsonFilePath = builder.Environment.IsProduction() ? null : opts.JsonFilePath;
    opts.AnsiConsole = !builder.Environment.IsProduction();
    opts.BufferFile = true;                                          // async file sink (default — keeps disk I/O off the request path)
    opts.LevelOverrides["MyNoisyClient"] = LogEventLevel.Warning;    // extend platform defaults
    opts.AdditionalConfiguration = cfg => cfg.WriteTo.Seq("http://seq:5341");
});

app.UseNedoLogContext(opts =>
{
    opts.HeaderEchoes["UserId"] = "X-User-Id";                       // add a custom header echo
    opts.EmitMissingAsEmpty = true;                                  // (opt-in) push absent headers as empty string
    opts.Redact = (name, value) =>                                   // sanitize sensitive values before they reach any sink
        name is "Authorization" or "Cookie" ? "***" : value;
});

⚠ Heads-up on header echoes. HeaderEchoes writes the raw header value into structured logs. Echo something like Authorization or a session cookie and the bearer token / session ID lands in the JSON file, Seq, Elasticsearch, OTLP — wherever your sinks ship to. Use Redact to scrub values for properties whose source headers might carry secrets, or just don't echo those headers in the first place.

Forwarding to log aggregators

The platform writes to console + a local JSON file. To also ship events to a remote aggregator, install the relevant Serilog sink package and append it via AdditionalConfiguration — events fan out to all sinks in the chain.

Seq

The canonical structured-log server. Default ingestion port is 5341.

dotnet add package Serilog.Sinks.Seq
opts.AdditionalConfiguration = cfg => cfg.WriteTo.Seq("http://seq:5341");

Elasticsearch (ECS-compliant)

Use the official Elastic-maintained sink — events ship as ECS-shaped documents into a data stream.

dotnet add package Elastic.Serilog.Sinks
opts.AdditionalConfiguration = cfg => cfg.WriteTo.Elasticsearch(esOpts =>
{
    esOpts.Nodes = new[] { new Uri("http://elasticsearch:9200") };
    esOpts.DataStream = new DataStreamName("logs", builder.Environment.ApplicationName, "default");
    // esOpts.BootstrapMethod = BootstrapMethod.Failure;   // create the data stream on startup
});

OpenTelemetry (OTLP)

Pairs with Nedo.AspNet.Logging.OpenTelemetry — Serilog events ship to your OTel collector via OTLP, landing in the same APM as the spans the OTel package emits. Serilog's automatic Activity enrichment means every event already carries TraceId / SpanId, so log/trace correlation works end-to-end without extra wiring.

dotnet add package Serilog.Sinks.OpenTelemetry
opts.AdditionalConfiguration = cfg => cfg.WriteTo.OpenTelemetry(otlp =>
{
    otlp.Endpoint = "http://otel-collector:4317";        // gRPC default; use 4318 for HTTP
    otlp.ResourceAttributes = new Dictionary<string, object>
    {
        ["service.name"] = builder.Environment.ApplicationName,
    };
});

The OTel sink only forwards logs. Traces and metrics still come from Nedo.AspNet.Logging.OpenTelemetry.

What it doesn't do

  • Not a request-logging middleware (use Serilog's UseSerilogRequestLogging separately).
  • Not OpenTelemetry trace/metric wiring — use the sibling Nedo.AspNet.Logging.OpenTelemetry package for that. (Forwarding logs to OTLP is shown above.)
  • Not audit/business event logging (separate concern).

Just the standard structured-log configuration plus the request-context middleware.

Standards

Concern Implementation
Output template Platform-standard
Trace correlation W3C Trace Context (auto-enriched)
Date/time RFC 3339 / ISO 8601 with offset
JSON format Serilog Compact JSON (@t, @mt, @l, @x, …)

License

MIT.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 142 5/3/2026
1.0.0 1,085 5/2/2026