using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; namespace HealthMonitor.WebApi.HttpLog { public class CustomLoggingScopeHttpMessageHandler : DelegatingHandler { private readonly ILogger _logger; public CustomLoggingScopeHttpMessageHandler(ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } using (Log.BeginRequestPipelineScope(_logger, request)) { Log.RequestPipelineStart(_logger, request); var response = await base.SendAsync(request, cancellationToken); Log.RequestPipelineEnd(_logger, response); return response; } } private static class Log { private static class EventIds { public static readonly EventId PipelineStart = new EventId(100, "RequestPipelineStart"); public static readonly EventId PipelineEnd = new EventId(101, "RequestPipelineEnd"); } private static readonly Func _beginRequestPipelineScope = LoggerMessage.DefineScope( "HTTP {HttpMethod} {Uri} {CorrelationId}"); private static readonly Action _requestPipelineStart = LoggerMessage.Define( LogLevel.Information, EventIds.PipelineStart, "Start processing HTTP request {HttpMethod} {Uri} [Correlation: {CorrelationId}]"); private static readonly Action _requestPipelineEnd = LoggerMessage.Define( LogLevel.Information, EventIds.PipelineEnd, "End processing HTTP request - {StatusCode}"); public static IDisposable BeginRequestPipelineScope(ILogger logger, HttpRequestMessage request) { var correlationId = GetCorrelationIdFromRequest(request); return _beginRequestPipelineScope(logger, request.Method, request.RequestUri!, correlationId)!; } public static void RequestPipelineStart(ILogger logger, HttpRequestMessage request) { if (logger.IsEnabled(LogLevel.Trace)) { var correlationId = GetCorrelationIdFromRequest(request); _requestPipelineStart(logger, request.Method, request.RequestUri!, correlationId, null); } } public static void RequestPipelineEnd(ILogger logger, HttpResponseMessage response) { if (logger.IsEnabled(LogLevel.Trace)) { _requestPipelineEnd(logger, response.StatusCode, null); } } private static string GetCorrelationIdFromRequest(HttpRequestMessage request) { var correlationId = "Not set"; if (request.Headers.TryGetValues("X-Correlation-ID", out var values)) { correlationId = values.First(); } return correlationId; } } } }