using System.Data.Common; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; namespace Budget.Infrastructure.Data; public class SlowQueryInterceptor(ILogger logger) : DbCommandInterceptor { private static readonly TimeSpan Threshold = TimeSpan.FromMilliseconds(500); public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) { LogIfSlow(command, eventData.Duration); return result; } public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default) { LogIfSlow(command, eventData.Duration); return new ValueTask(result); } public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result) { LogIfSlow(command, eventData.Duration); return result; } public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default) { LogIfSlow(command, eventData.Duration); return new ValueTask(result); } public override object? ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object? result) { LogIfSlow(command, eventData.Duration); return result; } public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object? result, CancellationToken cancellationToken = default) { LogIfSlow(command, eventData.Duration); return new ValueTask(result); } private void LogIfSlow(DbCommand command, TimeSpan duration) { if (duration >= Threshold) logger.LogWarning("Slow query ({Duration}ms): {CommandText}", (long)duration.TotalMilliseconds, command.CommandText); } }