首页 > 解决方案 > 如何从先前处于 Catch 状态的函数访问 Step Function 中的错误信息

问题描述

我想知道如何访问我的 lambda 函数中引发的自定义异常的原因。我需要在 Step Functions 工作流程结束时访问它,如下所示。

下图是执行失败的示例。在 的输出中找到了错误(error-info对象,具有自己的ErrorCause部分)ParseTextractOutput,但我想知道如何访问它,OutputNotFound如下所示。

阶跃函数图

在此处输入图像描述

输出

的输出ParseTextractOutput

{
  "event"...
  "error-info": {
    "Error": "OutputNotFoundException",
    "Cause": "{\"errorMessage\": \"Contents of Textracted file: {...}}"
    }
  }
}

我想以某种方式在这些字段(Step Functions 定义)中访问这些数据:

...
  "States": {
    "OutputNotFound": {
      "Type": "Fail",
      "Error": "<useful stuff here, like $.error-info.Error or something>",
      "Cause": "<useful stuff here, like $.error-info.Cause or something>"
    },
...
    "ParseTextractOutput": {
      "Type": "Task",
      "Resource": "functionARN",
      "Catch": [
        {
          "ErrorEquals": ["OutputNotFoundException"],
          "ResultPath": "$.error-info",
          "Next": "OutputNotFound"
        }
      ],
      "End": true
    }

Python代码

这是 Function 的相关代码ParseTextractOutput

class OutputNotFoundException(Exception):
  pass

...

try:
  blocks = data['Blocks']
except KeyError as e:
  raise OutputNotFoundException('Contents of Textracted file: {}'.format(data))

标签: pythonamazon-web-servicesaws-lambdastate-machineaws-step-functions

解决方案


目前(使用当前版本的https://states-language.net/spec.htmlFail.Error并且Fail.Cause不能是动态的。传递给Fail状态的输入被忽略,修复字符串用于错误和原因。

我们可以将Fail其视为执行中的一个点,以宣布修复消息,指示执行结束并出现错误并退出。

这意味着必须在这些公告点之前完成任何处理。正如@frosty 在评论中提到的,Choice状态可能很有用。

备选方案 1:使用选择

这是一个例子:

在失败状态之前有选择的状态机

假设我的 Lambda 函数中有这个 Python 代码:

class OutputNotFoundException(Exception):
  pass



def lambda_handler(event, context):
    raise OutputNotFoundException('Error message A')

当函数返回时,输出将是这样的 JSON:

{
  "Error": "OutputNotFoundException",
  "Cause": "{\"errorMessage\":\"Error message A\",\"errorType\":\"OutputNotFoundException\",\"stackTrace\":[\"...\\n\"]}"
}

注意“原因”是另一个字符串编码的 JSON。我们可以转换OutputNotFoundPass并使用内部函数StringToJson()将编码的字符串转换为普通的 JSON,以便以后处理:

    "OutputNotFound": {
      "Type": "Pass",
      "Parameters": {
        "details.$": "States.StringToJson($.Cause)"
      },
      "Next": "Error message?"
    },

现在我们有这样的输出:

{
  "details": {
    "errorMessage": "Error message A",
    "errorType": "OutputNotFoundException",
    "stackTrace": ["...\n"]
  }
}

下一个状态将是Choice查看$.details.errorMessage以决定适当的失败状态:

    "Error message?": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.details.errorMessage",
          "StringEquals": "Error message A",
          "Next": "Error A"
        },
        {
          "Variable": "$.details.errorMessage",
          "StringEquals": "Error message B",
          "Next": "Error B"
        }
      ],
      "Default": "Unknown Error"
    },

现在每个选项都指向一个正常Fail状态来宣布一个修复字符串:

    "Error A": {
      "Type": "Fail",
      "Error": "OutputNotFoundException",
      "Cause": "OutputNotFoundException of type A happened"
    },

备选方案 2:以 Pass 结束

如果您的意图是将确切的错误消息作为执行的输出以供以后记录/处理,则一种方法可以留在该Pass状态:

    "OutputNotFound": {
      "Type": "Pass",
      "Parameters": {
        "details.$": "States.StringToJson($.Cause)",
        "isError": true
      },
      "End": true
    }

当然,这个解决方案的缺点是执行以成功状态结束,我们需要处理输出以发现错误(因此isError上面的额外字段)


推荐阅读