using System.Diagnostics; using System.Text.RegularExpressions; using MediatR; using Microsoft.Extensions.Logging; namespace CMSMicroservice.Application.Common.Behaviours; public partial class PerformanceBehaviour : IPipelineBehavior where TRequest : IRequest { private readonly Stopwatch _timer; private readonly ILogger _logger; private readonly ICurrentUserService _currentUserService; [GeneratedRegex(@"ImageFile(?:Bytes|Mime|FileName)|ImageFile|File", RegexOptions.None)] private static partial Regex BinaryPropertyPattern(); public PerformanceBehaviour(ILogger logger, ICurrentUserService currentUserService) { _timer = new Stopwatch(); _logger = logger; _currentUserService = currentUserService; } public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { _timer.Start(); var response = await next(); _timer.Stop(); var elapsedMilliseconds = _timer.ElapsedMilliseconds; if (elapsedMilliseconds > 500) { var requestName = typeof(TRequest).Name; var userId = _currentUserService.UserId ?? string.Empty; var safeLog = SanitizeForLog(request); _logger.LogWarning("Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {UserId} {Request}", requestName, elapsedMilliseconds, userId, safeLog); } return response; } private static string SanitizeForLog(TRequest request) { var text = request?.ToString() ?? ""; if (text.Length > 2000) return text[..2000] + "... [TRUNCATED]"; return text; } }