はじめに
この記事は、ミロゴス Advent Calendar 2023 22日目の投稿です。
業務でLambdaからSlackへAWS Chatbotのカスタム通知を送る実装を行ったので、実際のコードとポイントを紹介していきたいと思います。
既にSlackチャンネルと紐づいたSNSトピックを作成済みの前提で、カスタム通知をLambdaから送信する方法を記述していきます。
カスタム通知とは
Chatbotのカスタム通知は通常の通知とは異なり、ユーザー側でメッセージをカスタマイズすることが可能です。
今まではSlackで任意のメッセージ通知を行いたい場合、LambdaとSlackのIncomming Webhook機能を組み合わせて使うことが主流だったかと思います。
Chatbotのカスタム通知機能の登場により、Slackと紐づいたSNSトピックを準備するだけで任意のメッセージを送ることが可能になりました。
実行環境
-
AWS CDK
- パッケージ:
aws-cdk
- バージョン:
2.110.1
- パッケージ:
-
AWS CDK ライブラリ
- パッケージ:
aws-cdk-lib
- バージョン:
2.110.0
- パッケージ:
-
AWS SDK
- パッケージ:
aws-sdk
- バージョン:
2.1304.0
- パッケージ:
-
TypeScript
- パッケージ:
typescript
- バージョン:
4.8.4
- パッケージ:
-
Lambda Node.js
- バージョン:
18.x
- バージョン:
実装の紹介
LambdaからSlackへカスタム通知を送るに当たり必要な実装を紹介します。
Lambda関数の作成
まずは呼び出すLambdaの作成です。
Lambdaを作成するに当たり、下記の二つが必要になります。
- LambdaからSNSへのアクセス権限を設定する
- SNSのTopic ARNを環境変数として渡す
SNSトピックの作成、SNSとChatbotを紐付けてSlackに通知できるようにするには別途設定が必要になります。
今回は作成済みのSNSからTopic ARNを引用する想定で記載しています。
import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as nodejs from 'aws-cdk-lib/aws-lambda-nodejs';
export default class LambdaConstruct extends Construct {
constructor(
scope: Construct,
id: string,
topicArn: string
) {
super(scope, id);
const customRole = new iam.Role(this, 'S3DownloaderRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSNSFullAccess'),
],
}),
},
});
new nodejs.NodejsFunction(
this,
'lambda',
{
role: customRole,
environment: {
TOPIC_ARN: topicArn
},
//その他設定は省略
},
);
}
}
Slackクラスの定義
Lambdaで使用するSlackクラスを作成します。
このクラスからカスタム通知を送信します。
PublishCommand
で送信するMessage
プロパティは、型にあったJSON化できる文字列でなければいけないので注意が必要です。
型の参考:https://docs.aws.amazon.com/ja_jp/chatbot/latest/adminguide/custom-notifs.html#parameter-details
import { PublishCommand, SNSClient } from '@aws-sdk/client-sns';
export class Slack {
private topic: SNSClient;
private topicArn: string;
constructor(topicArn: string) {
this.topic = new SNSClient({ region: 'ap-northeast-1' });
this.topicArn = topicArn;
log.info('slack', { slack: this });
}
public async sendMessage() {
const description =
`@channel\n$エラーが発生しました`
const message = {
version: '1.0',
source: 'custom',
content: {
title: this.service,
description: description,
},
};
const result = await this.topic.send(
new PublishCommand({
Message: JSON.stringify(message),
TopicArn: this.topicArn,
})
);
log.info('Success send message');
}
Lambda本体の実装
エラーをキャッチして、カスタム通知を送信する処理の例です。
import { Slack } from './slack';
import { ScheduledEvent } from 'aws-lambda';
const TOPIC_ARN = process.env.TOPIC_ARN || '';
export const handler = async (event: ScheduledEvent) => {
const slack = new Slack(TOPIC_ARN);
try {
// 処理を記述
log.info('Success All Process');
} catch (error) {
log.error('Error S3Downloader', { error });
await slack.sendMessage(error);
throw error;
}
};
まとめ
今回は、Chatbotを利用してLambdaからSlackへカスタム通知を送る方法を紹介しました。
Chatbotのカスタム通知設定は新機能で情報も少ないと思われるので、少しでも他の方の助けになれば幸いです。