LambdaでCloudWatchにエラーログが流れたらAWS ChatbotでSlack通知するPython製CDKスタック
サーバーのエラーを監視するため、Lambda のログで CloudWatch に[ERROR]の文字列が含まれていたら、AWS Chatbot で Slack チャンネルへ通知するように Python 製 CDK スタックを作成しました。
通知先の Slack チャンネルを作成し、Slack ワークスペース ID とチャンネル ID を確認する
通知先の Slack チャンネルを作成します。私の場合はサービスごと、環境ごと(dev, prod)で分けており、service-name-dev
, service-name-prod
のように名前をつけています。
Slack ワークスペース ID とチャンネル ID は、ブラウザ版 Slack を開けば確認できます
Slack ワークスペース ID とチャンネル ID を cdk.json に追加する
デプロイする際に CDK が参照できるように、cdk.json へ環境ごとに ID を追加します。
"context": {
"hoge": "fuga",
"dev": {
"slack_workspace_id": "hoge_dev",
"slack_channel_id": "fuga_dev"
},
"prod": {
"slack_workspace_id": "hoge_prod",
"slack_channel_id": "fuga_prod"
}
}
AWS Chatbot で Slack workspace へのアクセス権限を付与する
AWS Chatbot は、指定された Slack ワークスペース ID とチャンネル ID にアクセスしますが、ID を知っているだけではアクセスできません。AWS Chatbot が Slack ワークスペースにアクセスする権限を AWS マネジメントコンソールから許可します。
アクセス許可を出しておかないと、CDK でのデプロイ時にエラーになります。
10:50:25 | CREATE_FAILED | AWS::Chatbot::SlackChannelConfiguration | hoge_channel Resource handler returned message: "Invalid request provided: AWS Chatbot can't create the configuration because Slack workspace hoge1 is not authorized with AWS account 0000000000. See https://docs.aws.amazon.com/chatbot/latest/adminguide/setting-up.html#Setup_intro (Service: AWSChatbot; Status Code: 400; Error Code: InvalidRequestException; Request ID: xxxx; Proxy: null)"
CDK スタックで Chatbot と CloudWatch カスタムメトリクスを作る
少し長いですが、Chatbot と CloudWatch カスタムメトリクスを設定する CDK スタックの Python スクリプトです。try_get_context で、コマンドラインオプションと cdk.json から値を取得します。
Chatbot には CloudWatch を参照するための権限を付与しました。CloudWatch カスタムメトリクスのアラームが発火すると、SnsAction が実行されて Slack に通知が飛びます。
#
# エラーをSlack通知するチャットボット
#
stage = self.node.try_get_context('stage')
env = self.node.try_get_context(stage)
slack_channel_name = 'hoge_channel'
slack_channel = aws_chatbot.SlackChannelConfiguration(
self,
slack_channel_name,
slack_channel_configuration_name=slack_channel_name,
slack_workspace_id=env["slack_workspace_id"],
slack_channel_id=env["slack_channel_id"]
)
slack_channel.add_to_role_policy(aws_iam.PolicyStatement(
effect=aws_iam.Effect.ALLOW,
actions=[
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
],
resources=["*"]
))
alerm_sns_topic = aws_sns.Topic(self, 'alerm')
slack_channel.add_notification_topic(alerm_sns_topic)
sns_action = aws_cloudwatch_actions.SnsAction(alerm_sns_topic)
#
# 通知を発火するCloudWatchカスタムメトリクス
#
functions = [my_lambda_functions]
for function in functions:
metric_filter_name = function._physical_name + '_error_metric_filter'
metric_filter = function.log_group.add_metric_filter(
metric_filter_name,
filter_pattern=aws_logs.FilterPattern.any_term("[ERROR]"),
metric_name="filter_pattern [ERROR]",
metric_namespace=metric_filter_name,
metric_value="1"
)
alarm = aws_cloudwatch.Alarm(
self,
function._physical_name + "_error_alarm",
metric=metric_filter.metric(),
threshold=1,
evaluation_periods=1,
comparison_operator=aws_cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
treat_missing_data=aws_cloudwatch.TreatMissingData.NOT_BREACHING,
)
alarm.add_alarm_action(sns_action)
CDK を叩いてデプロイする
CDK を叩く際に stage=dev/prod を渡すことで、適切な Slack ワークスペース ID とチャンネル ID に通知が飛ぶようになります。
cdk deploy --profile hoge-dev --context stage=dev
私が作業中に飲んでいるコーヒーや欲しいマンガなどを集めました。開発・執筆の励みになりますのでクリックして頂ければ幸いです。
<Amazon欲しいものリスト>