using Serilog.Context; using System.Diagnostics; using System.Security.Claims; namespace MarcoBMS.Services.Middleware { public class LoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; //private readonly UserHelper _userHelper; private readonly List _ignoredPaths = new List { "/hubs/marco", "/hubs/marco/negotiate", "/swagger" }; public LoggingMiddleware(RequestDelegate next, ILogger logger) { _next = next; _logger = logger; } public async Task Invoke(HttpContext context) { if (_ignoredPaths.Any(path => context.Request.Path.StartsWithSegments(path, StringComparison.OrdinalIgnoreCase))) { await _next(context); return; } var stopwatch = Stopwatch.StartNew(); var response = context.Response; var request = context.Request; var tenantId = context.User.FindFirst("TenantId")?.Value; var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier); string origin = request.Headers["Origin"].FirstOrDefault() ?? ""; using (LogContext.PushProperty("TenantId", tenantId)) using (LogContext.PushProperty("TraceId", context.TraceIdentifier)) using (LogContext.PushProperty("UserAgent", request.Headers["User-Agent"].ToString())) using (LogContext.PushProperty("HttpMethod", request.Method)) using (LogContext.PushProperty("Timestamp", DateTime.UtcNow)) using (LogContext.PushProperty("IpAddress", context.Connection.RemoteIpAddress?.ToString())) using (LogContext.PushProperty("RequestPath", request.Path)) using (LogContext.PushProperty("Origin", origin)) using (LogContext.PushProperty("LogOrigin", "ASP .NET Api")) using (LogContext.PushProperty("UserId", userId)) try { await _next(context); stopwatch.Stop(); using (LogContext.PushProperty("StatusCode", response.StatusCode.ToString())) using (LogContext.PushProperty("ResponseTimeMs", stopwatch.ElapsedMilliseconds)) using (LogContext.PushProperty("LogLevel", "Information")) _logger.LogInformation("HTTP {method} {path} responded {statusCode} in {timeTaken} ms", request.Method, request.Path, response.StatusCode.ToString(), stopwatch.ElapsedMilliseconds); } catch (Exception ex) { stopwatch.Stop(); using (LogContext.PushProperty("Error", ex)) using (LogContext.PushProperty("StatusCode", "500")) using (LogContext.PushProperty("ResponseTimeMs", stopwatch.ElapsedMilliseconds)) using (LogContext.PushProperty("LogLevel", "Error")) _logger.LogError("API Error{error}", ex.Message); throw; } } } }