using CoreAgent.Infrastructure.Options; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Diagnostics; using System.Text; namespace CoreAgent.Infrastructure.Middleware { public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly RequestLoggingOptions _options; public RequestLoggingMiddleware( RequestDelegate next, ILogger logger, IOptions options) { _next = next; _logger = logger; _options = options.Value; } public async Task InvokeAsync(HttpContext context) { if (ShouldSkipLogging(context)) { await _next(context); return; } var sw = Stopwatch.StartNew(); var requestBody = string.Empty; try { if (_options.LogRequestBody && context.Request.Body != null) { requestBody = await ReadRequestBodyAsync(context.Request); } _logger.LogInformation( "Request started: {Method} {Path} {QueryString} {RequestBody}", context.Request.Method, context.Request.Path, context.Request.QueryString, requestBody); await _next(context); } finally { sw.Stop(); _logger.LogInformation( "Request completed: {Method} {Path} in {ElapsedMilliseconds}ms with status code {StatusCode}", context.Request.Method, context.Request.Path, sw.ElapsedMilliseconds, context.Response.StatusCode); } } private bool ShouldSkipLogging(HttpContext context) { if (_options.ExcludePaths.Any(p => context.Request.Path.StartsWithSegments(p))) { return true; } if (_options.ExcludeMethods.Contains(context.Request.Method)) { return true; } return false; } private async Task ReadRequestBodyAsync(HttpRequest request) { if (!request.Body.CanRead || !request.Body.CanSeek) { return string.Empty; } var originalPosition = request.Body.Position; request.Body.Position = 0; try { using var reader = new StreamReader( request.Body, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024 * 45, leaveOpen: true); var body = await reader.ReadToEndAsync(); return body.Length > _options.MaxRequestBodySize ? body.Substring(0, _options.MaxRequestBodySize) + "..." : body; } finally { request.Body.Position = originalPosition; } } } }