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
<PackageReference Include="Serilog.Enrichers.Yarp" Version="1.0.0" />
<PackageVersion Include="Serilog.Enrichers.Yarp" Version="1.0.0" />
<PackageReference Include="Serilog.Enrichers.Yarp" />
paket add Serilog.Enrichers.Yarp --version 1.0.0
#r "nuget: Serilog.Enrichers.Yarp, 1.0.0"
#:package Serilog.Enrichers.Yarp@1.0.0
#addin nuget:?package=Serilog.Enrichers.Yarp&version=1.0.0
#tool nuget:?package=Serilog.Enrichers.Yarp&version=1.0.0
Serilog.Enrichers.Yarp
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
1. Register Services (Recommended)
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 identifierYarpClusterId- The YARP cluster identifierYarpDestinationId- The YARP destination identifierTraceIdentifier- 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:
- Uses IReverseProxyFeature: Accesses YARP's feature from HttpContext.Features
- Type-Safe Extraction: Uses YARP's RouteModel, ClusterModel, and DestinationState types directly
- 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
- Use DI Registration: Always call
AddYarpLogEnricher()to ensureIHttpContextAccessoris registered - Configure Early: Set up Serilog enrichment during application startup
- Low Cardinality: The enricher only logs safe, low-cardinality fields suitable for production
- Correlation: Enable
IncludeCorrelationContextfor distributed tracing scenarios - 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.0tonet6.0 - YARP Dependency: Now requires
Yarp.ReverseProxypackage (version 2.2.0+) as a direct dependency - Implementation: Replaced reflection-based extraction with YARP's public
IReverseProxyFeatureAPI
Migration Steps
- Update Target Framework: Ensure your application targets .NET 6.0 or higher
- Update Package: Update to version 2.0.0 or higher:
dotnet add package Serilog.Enrichers.Yarp --version 2.0.0 - No Code Changes Required: The public API remains the same; only the internal implementation changed
- 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
- Built with Serilog
- Designed for use with YARP (Yet Another Reverse Proxy)
Support
For issues, questions, or contributions, please visit the GitHub repository.
| Product | Versions 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. |
-
net6.0
- Microsoft.AspNetCore.Http (>= 2.2.0)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 6.0.0)
- Serilog (>= 2.10.0)
- Yarp.ReverseProxy (>= 2.2.0)
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 |