using System.Diagnostics; using MediatR; using Microsoft.Extensions.Logging; namespace Application.Behaviors; public sealed class LoggingBehavior(ILogger> logger) : IPipelineBehavior where TRequest : notnull { private const long SlowThresholdMs = 500; public async Task Handle( TRequest request, RequestHandlerDelegate next, CancellationToken ct ) { var requestName = typeof(TRequest).Name; var sw = Stopwatch.StartNew(); try { var result = await next(ct); sw.Stop(); if (sw.ElapsedMilliseconds > SlowThresholdMs) { logger.LogWarning("[Slow] {Request} took {Elapsed}ms", requestName, sw.ElapsedMilliseconds); } else if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("[Done] {Request} {Elapsed}ms", requestName, sw.ElapsedMilliseconds); } return result; } catch (Exception ex) { sw.Stop(); logger.LogError(ex, "[Failed] {Request} after {Elapsed}ms", requestName, sw.ElapsedMilliseconds); throw; } } }