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

在Azure Functions独立模式主编排器中获取原始错误与堆栈跟踪

解决Durable Functions主编排器获取原始异常堆栈跟踪的问题

在你的场景中,主编排器捕获到的TaskFailedException仅包含框架堆栈,是因为子编排器未对活动函数的异常做处理,导致异常被Durable框架二次包装。要让主编排器拿到原始错误信息和堆栈,可通过以下两种方式实现:

方法一:子编排器捕获异常并封装原始信息后重抛

在CityOrchestrator中捕获活动函数抛出的TaskFailedException,提取其中的原始错误详情(包括堆栈跟踪),将其封装到新的异常中再抛出。这样主编排器就能获取到完整的原始错误内容。

修改后的CityOrchestrator代码:

[Function(nameof(CityOrchestrator))]
public static async Task CityOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context, string city, FunctionContext executionContext)
{
    string[] postfixes = ["a", "b"];

    foreach (var postfix in postfixes)
    {
        try
        {
            await context.CallActivityAsync(nameof(SayHello), input: $"{city}-{postfix}");
        }
        catch (TaskFailedException ex)
        {
            // 提取原始异常的详细信息
            var originalDetails = ex.FailureDetails;
            // 封装自定义异常,携带原始错误信息与堆栈
            var wrappedException = new Exception(originalDetails.ErrorMessage)
            {
                Data = {
                    ["OriginalStackTrace"] = originalDetails.StackTrace,
                    ["OriginalErrorType"] = originalDetails.ErrorType
                }
            };
            // 抛出封装后的异常,传递给主编排器
            throw new TaskFailedException(nameof(CityOrchestrator), wrappedException);
        }
    }
}

此时主编排器中捕获的TaskFailedException,可从InnerException中取出原始错误信息:

catch (TaskFailedException ex)
{
    var originalStackTrace = ex.InnerException?.Data["OriginalStackTrace"] as string;
    var originalErrorMessage = ex.InnerException?.Message;
    // 执行业务错误处理逻辑
}

方法二:子编排器返回错误结果而非抛出异常

若不想通过异常传递信息,可让子编排器返回包含执行状态和错误详情的结果对象,主编排器通过判断结果获取原始错误。

  1. 定义结果类型:
public class OrchestrationExecutionResult
{
    public bool IsSuccess { get; set; }
    public string ErrorMessage { get; set; }
    public string ErrorStackTrace { get; set; }
}
  1. 修改CityOrchestrator返回该类型:
[Function(nameof(CityOrchestrator))]
public static async Task<OrchestrationExecutionResult> CityOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context, string city, FunctionContext executionContext)
{
    string[] postfixes = ["a", "b"];

    foreach (var postfix in postfixes)
    {
        try
        {
            await context.CallActivityAsync(nameof(SayHello), input: $"{city}-{postfix}");
        }
        catch (TaskFailedException ex)
        {
            return new OrchestrationExecutionResult
            {
                IsSuccess = false,
                ErrorMessage = ex.FailureDetails.ErrorMessage,
                ErrorStackTrace = ex.FailureDetails.StackTrace
            };
        }
    }
    return new OrchestrationExecutionResult { IsSuccess = true };
}
  1. 主编排器调用并处理结果:
[Function(nameof(MainOrchestrator))]
public static async Task MainOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context, FunctionContext executionContext)
{
    string[] cities = ["Seattle", "London"];
    foreach (var city in cities)
    {
        var result = await context.CallSubOrchestratorAsync<OrchestrationExecutionResult>(nameof(CityOrchestrator), city);
        if (!result.IsSuccess)
        {
            // 获取原始错误信息与堆栈
            var originalErrorMsg = result.ErrorMessage;
            var originalStack = result.ErrorStackTrace;
            // 执行业务处理逻辑
        }
    }
}

关键说明

Durable Functions在跨编排/活动传递异常时,会自动将异常包装为TaskFailedException,且默认不会传递完整原始堆栈(避免序列化开销与信息泄露)。通过子编排器手动捕获并封装原始错误,是确保主编排器获取所需信息的可靠方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:13:09