AWSのLambda関数をイベントで起動した時、複数回エラーを起こしたら、DeadLetterQueue、すなわちDLQを飛ばしたい。DLQを試すもの。Cloudformation使う。DLQはSNSとSQSが指定できるが、今回はSNSを使う。
系
以下の系を試す。
CloudWatch -> Lambda -(error)-> SNS -> Email
やってみる
CloudWatchで1分ごとにLambda関数を起動するようなものを、Cloudformationwと使って用意する。SNS Topicについては、コンソールから作成する。
SNS Topicを作る
コンソールからSNS Topicを作成する。名前は仮に DeadLetterQueueTopicとする。とりあえずEメールに飛ばすようにしておくと、確認しやすいと思う。
ディレクトリ構成
ディレクトリ構成は以下。__init__.pyは空。
. ├── __init__.py ├── hello_world_function │ ├── __init__.py │ ├── hello_world │ │ ├── __init__.py │ │ └── app.py │ └── requirements.txt ├── samconfig.toml └── template.yaml
という構成でやってみる。
template.yaml
TargetArn に SNS Topic のARNを入れる。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world_function
Handler: hello_world/app.lambda_handler
Runtime: python3.8
Policies:
- AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
Events:
HelloWorld:
Type: Schedule
Properties:
Schedule: rate(1 minute)
DeadLetterQueue:
Type: SNS
TargetArn: arn:aws:sns:xxxxxxxxxxxxxxxxxx:DeadLetterQueueTopic
samconfig.toml
sam build --use-container の後に sam deploy --guided で作るとよい。以下のようになる。
version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "sam-app"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1miie23rwqpqg"
s3_prefix = "sam-app"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM"
requirement.txt
空でもいいけど。
requests
six
regex
hello_world/app.py
def lambda_handler(event, context):
# print(event)
# raise Exception
return True
DLQ
sam build --use-container
# 初回で samconfig.tomlがない状態では sam deploy --guided
sam deploy
デプロイすると、1分間にLambda関数が起動する。で、このままだと正常に終了してDLQが飛ばないので、わざとエラーを起こす。そのためには、上記コードの raise Exception のエラーを外してデプロイする。しばらく待っていたら、DLQがSNSに飛ぶ。SNSのSubscriberにEmailを用意しておけば、すぐに確認できる。
後片付け
SNSのトピックは手動で作成したので、手動で消す。
忘れずにスタックを消す。消し忘れると延々とLambda関数が起動し続けることになってしまうので注意。
aws cloudformation delete-stack --stack-name sam-app
DLQ -> SNS -> Lambdaにした時のproperty
Slackとかに飛ばしたい時は、DLQのSNS経由でLambda関数に飛ばすことになる。Lambda関数のeventのpropertyをメモしておく。
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "xxxxx",
"Sns": {
"Type": "Notification",
"MessageId": "xxxx",
"TopicArn": "xxxx"
"Subject": None,
"Message": "xxxxxxx",
"Timestamp": "2021-05-13T03:02:52.129Z",
"SignatureVersion": "1",
"Signature": "xxxx",
"SigningCertUrl": "xxxx",
"UnsubscribeUrl": "xxxx",
"MessageAttributes": {
"RequestID": {
"Type": "String",
"Value": "xxxx",
},
"ErrorCode": {
"Type": "String",
"Value": "200"
}
}
}
}
]
}
気になるのは event.Sns.Message だが、これはシリアライズされたJSON。json.loads()でデシリアライズすると以下のようになる。
{
"version": "0",
"id": "xxxx",
"detail-type": "Scheduled Event",
"source": "aws.events",
"account": "xxxx",
"time": "2021-05-13T02:47:42Z",
"region": "xxxx",
"resources": [
"xxxx",
],
"detail": {}
}
resourcesとidから、エラーを起こした元のLambda関数を辿ることができる。
参考URL
ありがとうございました。
コメント