Serilog.Enrichers.Yarp 1.0.0

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

Serilog.Enrichers.Yarp

NuGet License

A production-grade Serilog enricher that adds YARP (Yet Another Reverse Proxy) reverse proxy context to log events in ASP.NET Core applications. This library enriches logs with critical proxy information (RouteId, ClusterId, DestinationId) extracted from HttpContext using direct integration with YARP.ReverseProxy package.

Features

  • Direct YARP Integration: Uses YARP's public APIs for type-safe context extraction
  • Exception Enrichment: Automatically enriches exception logs with YARP metadata for better debugging
  • Production-Ready: Follows SOLID, DRY, and KISS principles
  • Configurable: Customize property names and control what gets logged
  • DI-Friendly: Easy integration with ASP.NET Core dependency injection
  • Distributed Tracing: Supports correlation context for distributed systems
  • Safe Low-Cardinality: Enriches with safe, low-cardinality fields suitable for production logging
  • .NET 6.0+: Compatible with .NET 6.0 and higher
  • Well-Tested: Comprehensive unit test coverage (49 tests)

Installation

Install via NuGet:

dotnet add package Serilog.Enrichers.Yarp

Or via Package Manager:

Install-Package Serilog.Enrichers.Yarp

Quick Start

In your Program.cs or Startup.cs:

using Serilog;
using Serilog.Enrichers.Yarp;

var builder = WebApplication.CreateBuilder(args);

// Register YARP enricher services (registers IHttpContextAccessor)
builder.Services.AddYarpLogEnricher();

// Configure Serilog with YARP enrichment
builder.Host.UseSerilog((context, services, configuration) => configuration
    .ReadFrom.Configuration(context.Configuration)
    .Enrich.WithYarpContext(services.GetRequiredService<IHttpContextAccessor>())
    .WriteTo.Console());

var app = builder.Build();
app.Run();

2. Direct Configuration

If you prefer not to use DI:

using Serilog;
using Serilog.Enrichers.Yarp;
using Microsoft.AspNetCore.Http;

var httpContextAccessor = new HttpContextAccessor();

Log.Logger = new LoggerConfiguration()
    .Enrich.WithYarpContext(httpContextAccessor)
    .WriteTo.Console()
    .CreateLogger();

Configuration Options

Default Configuration

By default, the enricher includes all available YARP context properties:

services.AddYarpLogEnricher();

builder.Host.UseSerilog((context, services, configuration) => configuration
    .Enrich.WithYarpContext(services.GetRequiredService<IHttpContextAccessor>())
    .WriteTo.Console());

This will add the following properties to your log events (when available):

  • YarpRouteId - The YARP route identifier
  • YarpClusterId - The YARP cluster identifier
  • YarpDestinationId - The YARP destination identifier
  • TraceIdentifier - ASP.NET Core trace identifier for correlation

Custom Configuration

Customize which properties are logged and their names:

services.AddYarpLogEnricher(options =>
{
    options.IncludeRouteId = true;
    options.IncludeClusterId = true;
    options.IncludeDestinationId = true;
    options.IncludeCorrelationContext = true;
    
    // Customize property names
    options.RouteIdPropertyName = "ProxyRoute";
    options.ClusterIdPropertyName = "ProxyCluster";
    options.DestinationIdPropertyName = "ProxyDestination";
});

builder.Host.UseSerilog((context, services, configuration) => configuration
    .Enrich.WithYarpContext(
        services.GetRequiredService<IHttpContextAccessor>(),
        services.GetRequiredService<YarpEnricherOptions>())
    .WriteTo.Console());

Inline Configuration

Configure options inline without DI:

builder.Host.UseSerilog((context, services, configuration) => configuration
    .Enrich.WithYarpContext(
        services.GetRequiredService<IHttpContextAccessor>(),
        opts =>
        {
            opts.IncludeRouteId = true;
            opts.IncludeClusterId = false; // Don't log cluster
            opts.IncludeDestinationId = true;
        })
    .WriteTo.Console());

How It Works

The enricher uses YARP's public IReverseProxyFeature API to extract proxy context from HttpContext. This approach:

  1. Uses IReverseProxyFeature: Accesses YARP's feature from HttpContext.Features
  2. Type-Safe Extraction: Uses YARP's RouteModel, ClusterModel, and DestinationState types directly
  3. Safe Failure: Silently handles cases where YARP feature is not present

This design ensures:

  • ✅ Type-safe integration with YARP
  • ✅ Works with YARP 2.2.0 and later versions
  • ✅ Safe for non-YARP requests (no errors if YARP isn't processing the request)
  • ✅ Zero performance impact when YARP context is not available

Exception Enrichment

The enricher automatically enriches all log events with YARP metadata when the YARP proxy context is available, including logs for exceptions. This is particularly valuable for debugging and troubleshooting proxy failures.

Supported Exception Scenarios

When standard .NET exceptions occur during YARP proxy operations, they are automatically enriched with YARP metadata:

  • HttpRequestException - Connection failures, timeout errors to backend servers
  • TaskCanceledException - Request cancellations due to timeouts or client disconnects
  • TimeoutException - Operations that exceed configured timeout limits
  • InvalidOperationException - Invalid proxy state or configuration issues
  • OperationCanceledException - Canceled proxy operations
  • AggregateException - Multiple proxy failures

Example: Exception with YARP Context

try
{
    // YARP proxy operation that fails
}
catch (HttpRequestException ex)
{
    // This log will be enriched with YARP metadata
    logger.Error(ex, "Failed to proxy request to backend");
}

The resulting log event will include both the exception details and YARP context:

{
  "Timestamp": "2026-01-27T10:15:30.1234567Z",
  "Level": "Error",
  "MessageTemplate": "Failed to proxy request to backend",
  "Exception": "System.Net.Http.HttpRequestException: Connection timeout...",
  "Properties": {
    "YarpRouteId": "api-route",
    "YarpClusterId": "backend-cluster",
    "YarpDestinationId": "backend-server-1",
    "TraceIdentifier": "0HMVFE3QK9K8H:00000001"
  }
}

This makes it easy to identify which route, cluster, and destination were involved when an exception occurred.

Log Output Example

When YARP context is available, your logs will include:

{
  "Timestamp": "2026-01-27T10:15:30.1234567Z",
  "Level": "Information",
  "MessageTemplate": "Request processed successfully",
  "Properties": {
    "YarpRouteId": "api-route",
    "YarpClusterId": "backend-cluster",
    "YarpDestinationId": "backend-server-1",
    "TraceIdentifier": "0HMVFE3QK9K8H:00000001"
  }
}

Advanced Scenarios

Structured Logging with Elastic/Seq

builder.Host.UseSerilog((context, services, configuration) => configuration
    .Enrich.WithYarpContext(services.GetRequiredService<IHttpContextAccessor>())
    .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200"))
    {
        AutoRegisterTemplate = true,
        IndexFormat = "logs-{0:yyyy.MM}"
    }));

Conditional Enrichment

services.AddYarpLogEnricher(options =>
{
    // Only log route and cluster in production
    var isProduction = builder.Environment.IsProduction();
    options.IncludeRouteId = isProduction;
    options.IncludeClusterId = isProduction;
    options.IncludeDestinationId = true; // Always log destination
});

Multiple Enrichers

builder.Host.UseSerilog((context, services, configuration) => configuration
    .Enrich.FromLogContext()
    .Enrich.WithMachineName()
    .Enrich.WithEnvironmentName()
    .Enrich.WithYarpContext(services.GetRequiredService<IHttpContextAccessor>())
    .WriteTo.Console());

Best Practices

  1. Use DI Registration: Always call AddYarpLogEnricher() to ensure IHttpContextAccessor is registered
  2. Configure Early: Set up Serilog enrichment during application startup
  3. Low Cardinality: The enricher only logs safe, low-cardinality fields suitable for production
  4. Correlation: Enable IncludeCorrelationContext for distributed tracing scenarios
  5. Customize Names: Use custom property names to match your logging conventions

Requirements

  • .NET 6.0 or higher
  • Serilog 2.10.0 or higher
  • ASP.NET Core 6.0 or higher (for HttpContext support)
  • YARP.ReverseProxy 2.2.0 or higher (automatically included as a dependency)

Migration from v1.x to v2.0

Version 2.0 introduces breaking changes due to the direct YARP integration:

What Changed

  • Target Framework: Changed from netstandard2.0 to net6.0
  • YARP Dependency: Now requires Yarp.ReverseProxy package (version 2.2.0+) as a direct dependency
  • Implementation: Replaced reflection-based extraction with YARP's public IReverseProxyFeature API

Migration Steps

  1. Update Target Framework: Ensure your application targets .NET 6.0 or higher
  2. Update Package: Update to version 2.0.0 or higher:
    dotnet add package Serilog.Enrichers.Yarp --version 2.0.0
    
  3. No Code Changes Required: The public API remains the same; only the internal implementation changed
  4. Verify YARP Version: If you're already using YARP, ensure you're on version 2.2.0 or later

Benefits of Migration

  • Type-safe integration with YARP
  • Better long-term maintainability
  • No reliance on reflection or internal YARP APIs
  • Improved performance through direct API access

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Support

For issues, questions, or contributions, please visit the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 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.0.0 364 1/28/2026