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

Rebus 8下IErrorHandler获取内部异常及优化上报方案咨询

Rebus 8 错误消息上报优化及内部异常获取方案

一、正确获取内部异常信息

Rebus 8 中的 ExceptionInfo 提供了结构化的异常链信息,无需通过字符串匹配判断异常类型:

  • 每个 ExceptionInfo 实例的 Type 属性存储了异常的完整类型全名(如 System.InvalidOperationException),类型匹配精准可靠;
  • Inner 属性对应原异常的 InnerException,可通过遍历该属性链获取所有嵌套异常。

示例代码(检查异常链中是否包含目标类型):

private bool ContainsTargetException(ExceptionInfo exceptionInfo, string targetExceptionFullTypeName)
{
    var currentExceptionInfo = exceptionInfo;
    while (currentExceptionInfo != null)
    {
        if (string.Equals(currentExceptionInfo.Type, targetExceptionFullTypeName, StringComparison.Ordinal))
        {
            return true;
        }
        currentExceptionInfo = currentExceptionInfo.Inner;
    }
    return false;
}

使用时传入目标异常的完整类型名(如MyProject.Exceptions.PaymentFailedException)即可,完全替代不可靠的字符串匹配逻辑。

二、更优的失败消息上报实现方案

方案1:复用 IErrorHandler 并适配 ExceptionInfo

如果仍需处理毒消息(多次失败后进入死信的消息),可基于 IErrorHandler 结合上述异常类型检查逻辑实现:

public class SlackErrorHandler : IErrorHandler
{
    private readonly ISlackNotificationService _slackService;

    public SlackErrorHandler(ISlackNotificationService slackService)
    {
        _slackService = slackService;
    }

    public async Task HandlePoisonMessage(ErrorInfo errorInfo, Message message, ITransactionContext transactionContext)
    {
        var hasPaymentException = ContainsTargetException(errorInfo.Exception, "MyProject.Exceptions.PaymentFailedException");
        
        if (hasPaymentException)
        {
            await _slackService.SendPaymentFailureAlert(message, errorInfo);
        }
        else
        {
            await _slackService.SendGeneralFailureAlert(message, errorInfo);
        }
    }
}

方案2:使用自定义中间件捕获原始异常

若希望完全复用 Rebus 7 的逻辑,可通过自定义入站消息中间件在异常被序列化为 ExceptionInfo 之前捕获原始异常:

// 注册中间件
Configure.With(container)
    .Transport(t => t.Use...())
    .Options(options =>
    {
        options.Decorate<IPipeline>(c =>
        {
            var originalPipeline = c.Get<IPipeline>();
            return new PipelineStepInjector(originalPipeline)
                .OnReceive(new SlackErrorReportingMiddleware(c.Get<ISlackNotificationService>()), 
                           PipelineRelativePosition.After, 
                           typeof(HandleMessageStep));
        });
    })
    .Start();

// 自定义中间件类
public class SlackErrorReportingMiddleware : IIncomingStep
{
    private readonly ISlackNotificationService _slackService;

    public SlackErrorReportingMiddleware(ISlackNotificationService slackService)
    {
        _slackService = slackService;
    }

    public async Task Process(IncomingStepContext context, Func<Task> next)
    {
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            // 直接操作原始Exception及InnerException,完全复用Rebus7的上报逻辑
            await _slackService.SendFailureNotification(ex, context.Load<Message>().Headers);
            throw; // 必须重新抛出,保证Rebus的重试、死信队列等流程正常执行
        }
    }
}

该方案优势:

  • 无需适配 ExceptionInfo,迁移成本极低;
  • 可在消息重试阶段就上报错误,覆盖更多错误场景;
  • 保留原始异常的完整上下文信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:51:37