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
<PackageReference Include="Nedo.AspNet.Logging.Serilog" Version="1.1.0" />
<PackageVersion Include="Nedo.AspNet.Logging.Serilog" Version="1.1.0" />
<PackageReference Include="Nedo.AspNet.Logging.Serilog" />
paket add Nedo.AspNet.Logging.Serilog --version 1.1.0
#r "nuget: Nedo.AspNet.Logging.Serilog, 1.1.0"
#:package Nedo.AspNet.Logging.Serilog@1.1.0
#addin nuget:?package=Nedo.AspNet.Logging.Serilog&version=1.1.0
#tool nuget:?package=Nedo.AspNet.Logging.Serilog&version=1.1.0
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.Codecolorization 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)
Codedefaults 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) intoSerilog.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.
HeaderEchoeswrites the raw header value into structured logs. Echo something likeAuthorizationor a session cookie and the bearer token / session ID lands in the JSON file, Seq, Elasticsearch, OTLP — wherever your sinks ship to. UseRedactto 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
UseSerilogRequestLoggingseparately). - Not OpenTelemetry trace/metric wiring — use the sibling
Nedo.AspNet.Logging.OpenTelemetrypackage 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 | Versions 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. |
-
net9.0
- Serilog.AspNetCore (>= 9.0.0)
- Serilog.Enrichers.Environment (>= 3.0.1)
- Serilog.Enrichers.Process (>= 3.0.0)
- Serilog.Enrichers.Thread (>= 4.0.0)
- Serilog.Formatting.Compact (>= 3.0.0)
- Serilog.Sinks.Async (>= 2.1.0)
- Serilog.Sinks.File (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.