WideEvents.AspNetCore 0.2.3

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

WideEvents

WideEvents is a .NET library for wide events (also known as canonical log lines).

Instead of scattering many log lines across a request, you accumulate context into a single rich, structured event and emit it once at the end.

Heavily inspired by loggingsucks.com and Stripe's canonical log lines.


The problem

A single HTTP request typically produces:

Request started
Loading cart for user_456
Calling payment provider stripe
Retrying payment (attempt 2)
Payment failed: card_declined
Request finished with 500

Six lines. Fragmented context. Expensive to correlate.

The solution

WideEvents accumulates all context and emits one structured event:

{
  "http":     { "method": "GET", "path": "/checkout/user_456", "status_code": 200 },
  "user":     { "id": "user_456" },
  "payment":  { "method": "card", "provider": "stripe" },
  "duration_ms": 29.52,
  "trace_id": "23ca1dc84f7b4cc4b44b7717ca231c2b",
  "span_id":  "2454b21b523f02f4",
  "trace_flags": "None"
}

One event. Full context.


Packages

Package Description
WideEvents.Abstractions IWideEventContext and IWideEventExporter contracts.
WideEvents.Core WideEvent static accumulator and WideEventContext.
WideEvents.AspNetCore Middleware that emits one wide event per HTTP request.

Targets net8.0 and net10.0.


Installation

# ASP.NET Core apps (brings in Core and Abstractions transitively)
dotnet add package WideEvents.AspNetCore

# Non-web or console apps
dotnet add package WideEvents.Core

Quick start (ASP.NET Core)

Register the middleware and call WideEvent.Add anywhere in the request pipeline:

using WideEvents.AspNetCore;
using WideEvents.Core.Context;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWideEvents(); // emit one wide event per request

app.MapGet("/checkout/{userId}", (string userId) =>
{
    WideEvent.Add("user.id", userId);
    WideEvent.Add("payment.method", "card");
    WideEvent.Add("payment.provider", "stripe");
    return Results.Ok();
});

app.Run();

The middleware automatically adds http.method, http.path, http.status_code, duration_ms, and — when Activity.Current is set — trace_id, span_id, trace_flags.

On unhandled exceptions it captures error.type and error.message instead of http.status_code.


Dotted keys → nested JSON

Dotted key names are expanded into nested objects when the event is built:

WideEvent.Add("payment.method", "card");
WideEvent.Add("payment.provider", "stripe");
{
  "payment": {
    "method": "card",
    "provider": "stripe"
  }
}

Duplicate keys overwrite the previous value. null values are ignored. Empty or whitespace keys throw ArgumentException.


Using without ASP.NET Core

using WideEvents.Core.Context;

WideEvent.Add("job.name", "invoice-sync");
WideEvent.Add("job.records", 142);

var evt = WideEvent.Current.Build(); // IReadOnlyDictionary<string, object?>
// ... send evt to your logger or exporter

WideEvent.Reset();

Structured log output

The middleware logs via ILogger using {@WideEvent}. The default .NET console logger serializes dictionaries as ToString() — to get proper nested JSON you need a structured logger that supports destructuring, such as Serilog:

builder.Host.UseSerilog((ctx, lc) => lc
    .WriteTo.Console(new PrettyJsonFormatter()));

A runnable sample with Serilog lives in sample/WideEvents.Sample.Api.


Custom exporters

IWideEventExporter is the contract for custom destinations. It is not consumed by the middleware yet — today the middleware emits via ILogger. The interface exists so exporter packages can build against a stable contract:

public class MyExporter : IWideEventExporter
{
    public Task ExportAsync(
        IReadOnlyDictionary<string, object?> wideEvent,
        CancellationToken cancellationToken = default)
    {
        // send to OTLP, Kafka, ClickHouse, stdout, ...
        return Task.CompletedTask;
    }
}

Documentation

Full documentation in docs/:


License

Licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 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
0.2.4 166 6/16/2026
0.2.3 132 5/28/2026
0.2.2 121 5/28/2026
0.2.1 112 5/26/2026
0.1.0-alpha.0.69 72 6/30/2026