You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为所有MediatR处理器添加全局异常日志记录?

如何为MediatR添加全局异常日志管道行为

问题背景

我尝试用IRequestExceptionAction记录MediatR处理器抛出的所有异常,不需要处理这些异常(它们可能已经被处理了)。我用的是Microsoft依赖注入,已经把RequestExceptionActionProcessorStrategy设置为ApplyForAllExceptions。

针对特定请求类型实现IRequestExceptionAction时,日志记录能正常工作;但想创建单个处理程序记录所有处理器的异常却失败了,我试过两种实现方式:

  • 泛型处理程序
  • 以IRequest作为TRequest

请问该如何添加一个能触发所有MediatR处理器异常的管道行为?

解决方案

方法1:自定义泛型IRequestExceptionAction并手动注册

MediatR的自动扫描不会识别开放泛型的IRequestExceptionAction,需要手动注册这个泛型实现。

首先创建全局异常日志处理类:

public class GlobalRequestExceptionAction<TRequest, TException> : IRequestExceptionAction<TRequest, TException>
    where TRequest : notnull, IRequest
    where TException : Exception
{
    private readonly ILogger<GlobalRequestExceptionAction<TRequest, TException>> _logger;

    public GlobalRequestExceptionAction(ILogger<GlobalRequestExceptionAction<TRequest, TException>> logger)
    {
        _logger = logger;
    }

    public Task Execute(TRequest request, TException exception, CancellationToken cancellationToken)
    {
        _logger.LogError(exception, "MediatR请求处理异常,请求类型:{RequestType}", typeof(TRequest).FullName);
        return Task.CompletedTask;
    }
}

然后在依赖注入配置中注册该开放泛型类型:

services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
    cfg.RequestExceptionActionProcessorStrategy = RequestExceptionActionProcessorStrategy.ApplyForAllExceptions;
    // 注册全局泛型异常处理动作
    cfg.AddOpenRequestExceptionAction(typeof(GlobalRequestExceptionAction<,>));
});

方法2:自定义管道行为(更灵活的替代方案)

如果IRequestExceptionAction的方式不符合预期,可以直接实现IPipelineBehavior来捕获所有经过管道的异常并记录,这种方式不受RequestExceptionActionProcessorStrategy设置的限制:

public class GlobalExceptionLoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : notnull, IRequest<TResponse>
{
    private readonly ILogger<GlobalExceptionLoggingBehavior<TRequest, TResponse>> _logger;

    public GlobalExceptionLoggingBehavior(ILogger<GlobalExceptionLoggingBehavior<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
    {
        try
        {
            return await next();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "MediatR请求处理异常,请求类型:{RequestType}", typeof(TRequest).FullName);
            // 不处理异常,直接重新抛出,保留原有异常处理逻辑
            throw;
        }
    }
}

接着在依赖注入中注册这个管道行为:

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(GlobalExceptionLoggingBehavior<,>));

关键注意事项

  • 使用IRequestExceptionAction时,必须通过AddOpenRequestExceptionAction手动注册开放泛型,无法通过自动扫描识别
  • 管道行为方式可以捕获所有流经MediatR管道的异常,不受RequestExceptionActionProcessorStrategy的约束
  • 两种方案都仅记录日志,不会拦截或处理异常,原有异常处理逻辑仍会生效

内容的提问来源于stack exchange,提问作者Craig Smitham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 12:20:32