我有一个主要用Javascript编写的Lambda函数的AWS步骤函数/状态机(尽管一个是用Java编写的),我想更好地管理错误处理。
我有一个错误条件被捕获然后被转发到流中的另一个状态没有问题。因此,例如,我的状态机中的以下状态定义将执行传递到NotifyOfError
状态,在那里我能够通过电子邮件和短信正确地了解错误状态。
Closure:
Type: Task
Resource: >-
arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:xxx-services-${opt:stage}-transportClosure
Next: WaitForCloudWatch
Catch:
- ErrorEquals:
- "States.ALL"
ResultPath: "$.error-info"
Next: NotifyOfError
然而,不是将所有错误交给这个状态,而是有一些错误,我喜欢处理不同的错误。所以起初我以为如果我把一个Javascript / Node错误与给定的"名称"那个名字就是我可以在 ErrorEquals 配置中分支的东西。例如:
catch(e) {
if (e.message.indexOf('something') !== -1) {
e.name = "SomethingError";
throw e;
}
但很快就意识到这个名字只是在步骤函数的Cause
部分之前,而不是分支的东西。然后我尝试扩展基本的Error类,如下所示:
export default class UndefinedAssignment extends Error {
constructor(e: Error) {
super(e.message);
this.stack = e.stack;
}
}
但抛出此错误实际上什么也没做,这意味着当它出现在Step Function中时,Error类型仍然只是"错误":
"error-info": {
"Error": "Error",
"Cause": "{\"errorMessage\":\"Error: the message",\"errorType\":\"Error\",\"stackTrace\":[\"db.set.catch.e (/var/task/lib/prepWorker/Handler.js:247:23)\",\"process._tickDomainCallback (internal/process/next_tick.js:135:7)\"]}"
}
所以我还不清楚如何区分在步骤函数中 branchable 的Node中出现的错误。
注意:使用Java,它似乎 正确拾取错误类(虽然我在Java方面做的测试少得多)
答案 0 :(得分:1)
以下是我如何使用“步骤功能”将自定义错误和消息报告为Error
和Cause
。注意我使用带有async
和try/catch
的Node.js 8.10 Lambda运行时。
exports.handler = async (event) => {
function GenericError(name, message) {
this.name = name;
this.message = message;
}
GenericError.prototype = new Error();
try {
// my implementation which might throw an error
// ...
}
catch (e) {
console.log(e);
let error = new GenericError('CustomError', 'my message');
throw error;
}
};
为简单起见,我忽略了catch(e)
中的错误对象。如果需要,您还可以将其stack
提供给GenericError。
这个lambda函数返回:
{
"errorMessage": "my message",
"errorType": "CustomError",
"stackTrace": [
"exports.handler (/var/task/index.js:33:28)"
]
}
步骤功能将其转换为:
{
"error": "CustomError",
"cause": {
"errorMessage": "my message",
"errorType": "CustomError",
"stackTrace": [
"exports.handler (/var/task/index.js:33:28)"
]
}
}
在其LambdaFunctionFailed
事件历史记录中,最终将其再次转换为此状态输出(取决于我们的ResultPath
- 此处不包含任何内容):
{
"Error": "CustomError",
"Cause": "{\"errorMessage\":\"my message\",\"errorType\":\"CustomError\",\"stackTrace\":[\"exports.handler (/var/task/index.js:33:28)\"]}"
}
答案 1 :(得分:0)
您应该使用callback
从Lambda返回抛出的异常。创建lambda和状态机的示例Cloud Formation模板:
AWSTemplateFormatVersion: 2010-09-09
Description: Stack creating AWS Step Functions state machine and lambda function throwing custom error.
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Handler: "index.handler"
Role: !GetAtt LambdaExecutionRole.Arn
Code:
ZipFile: |
exports.handler = function(event, context, callback) {
function SomethingError(message) {
this.name = "SomethingError";
this.message = message;
}
SomethingError.prototype = new Error();
const error = new SomethingError("something-error");
callback(error);
};
Runtime: "nodejs6.10"
Timeout: 25
StateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
RoleArn: !GetAtt StatesExecutionRole.Arn
DefinitionString: !Sub
- >
{
"Comment": "State machine for nodejs error handling experiment",
"StartAt": "FirstState",
"States": {
"FirstState": {
"Type": "Task",
"Resource": "${ThrowErrorResource}",
"Next": "Success",
"Catch": [
{
"ErrorEquals": ["SomethingError"],
"ResultPath": "$.error",
"Next": "CatchSomethingError"
}
]
},
"Success": {
"Type": "Pass",
"End": true
},
"CatchSomethingError": {
"Type": "Pass",
"Result": {
"errorHandlerOutput": "Huh, I catched an error"
},
"ResultPath": "$.errorHandler",
"End": true
}
}
}
- ThrowErrorResource: !GetAtt LambdaFunction.Arn
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
StatesExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: ExecuteLambda
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: arn:aws:lambda:*:*:function:*
基本部分是Lambda函数定义:
exports.handler = function(event, context, callback) {
function SomethingError(message) {
this.name = "SomethingError";
this.message = message;
}
SomethingError.prototype = new Error();
const error = new SomethingError("something-error");
callback(error);
};
此处定义了自定义名称的自定义错误。当然你也可以简单地覆盖名称(但我不建议这样做):
exports.handler = function(event, context, callback) {
var e = new Error();
e.name = "SomethingError";
callback(e);
};
返回错误,因为它将传递给步骤函数而不会丢失错误名称。我建议您在Lambda函数中创建一些顶级try-catch
语句,只需向callback
调用错误。