使用Npgsql的EnableRetryOnFailure时如何查看重试发生的日志或相关提示?
监控Npgsql EF Core重试事件的实现方案
你可以通过两种常用方式捕获EnableRetryOnFailure的重试触发事件,确认机制是否正常生效:
方法1:自定义执行策略(推荐,灵活性最高)
继承Npgsql官方的NpgsqlRetryingExecutionStrategy类,重写OnRetry方法注入自定义的日志、事件触发逻辑:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using Npgsql; using Microsoft.Extensions.Logging; public class LoggingNpgsqlRetryingExecutionStrategy : NpgsqlRetryingExecutionStrategy { private readonly ILogger _logger; public LoggingNpgsqlRetryingExecutionStrategy( ExecutionStrategyDependencies dependencies, int maxRetryCount, TimeSpan maxRetryDelay, ICollection<string> errorCodesToAdd) : base(dependencies, maxRetryCount, maxRetryDelay, errorCodesToAdd) { _logger = dependencies.Logger.Logger; } protected override void OnRetry(Exception exception, TimeSpan delay) { // 自定义日志输出,包含重试次数、延迟时长、故障原因 _logger.LogWarning( "数据库临时故障触发重试,第{RetryCount}次重试,延迟{Delay}ms,错误信息:{Message}", RetryCount + 1, delay.TotalMilliseconds, exception.Message); // 如需对外暴露重试事件,可在这里触发自定义事件 RetryTriggered?.Invoke(this, new RetryEventParams(RetryCount + 1, delay, exception)); base.OnRetry(exception, delay); } // 自定义重试事件参数 public class RetryEventParams : EventArgs { public int RetryCount { get; } public TimeSpan Delay { get; } public Exception Exception { get; } public RetryEventParams(int retryCount, TimeSpan delay, Exception exception) { RetryCount = retryCount; Delay = delay; Exception = exception; } } public static event EventHandler<RetryEventParams> RetryTriggered; }
替换原来的EnableRetryOnFailure配置,注册自定义执行策略:
builder.Services.AddDbContext<你的上下文类名>(options => options.UseNpgsql("你的数据库连接字符串", npgsqlOpts => { // 替换原有EnableRetryOnFailure调用 npgsqlOpts.ExecutionStrategy(dependencies => new LoggingNpgsqlRetryingExecutionStrategy( dependencies, maxRetryCount: 5, // 保持和你之前配置的重试次数一致 maxRetryDelay: TimeSpan.FromSeconds(30), // 保持和你之前配置的最大重试延迟一致 errorCodesToAdd: null)); // 额外需要重试的PostgreSQL错误码,无额外需求传null即可 }));
方法2:监听EF Core内置日志事件(无需修改原有执行策略配置)
EF Core本身会输出重试对应的日志事件,事件ID为CoreEventId.ExecutionStrategyRetrying,你可以直接通过日志过滤或者诊断监听器捕获:
日志过滤配置示例
builder.Services.AddLogging(logging => { // 开启EF Core Warning级别的日志即可收到重试通知 logging.AddFilter("Microsoft.EntityFrameworkCore", LogLevel.Warning); });
诊断监听器捕获示例(适合需要代码层面处理重试事件的场景)
using Microsoft.EntityFrameworkCore.Diagnostics; using System.Diagnostics; public class EfCoreRetryObserver : IObserver<KeyValuePair<string, object>> { public void OnNext(KeyValuePair<string, object> value) { if (value.Key == CoreEventId.ExecutionStrategyRetrying.Name) { var eventData = (ExecutionStrategyRetryingEventData)value.Value; // 这里处理重试逻辑,比如上报监控、记录详细日志 Console.WriteLine($"重试触发:第{eventData.RetryAttempt}次,延迟{eventData.Delay.TotalMilliseconds}ms,错误原因:{eventData.Exceptions.FirstOrDefault()?.Message}"); } } public void OnError(Exception error) { } public void OnCompleted() { } } // 项目启动时注册观察者 DiagnosticListener.AllListeners.Subscribe(listener => { if (listener.Name == "Microsoft.EntityFrameworkCore") { listener.Subscribe(new EfCoreRetryObserver()); } });
功能验证
- 测试时可以临时断开数据库网络,或者主动触发PostgreSQL可重试错误(比如序列化失败错误码
40001、连接中断错误码57P01),查看是否有对应的重试日志/事件触发即可确认机制生效。
内容的提问来源于stack exchange,提问作者Reuven Trabin
相关产品推荐
相关产品推荐

