ステートマシンの実行ステータスをCloudWatchイベント経由でSlackにメンション通知してみた
こんにちは、坂巻です。
先日、Step Functionsにアップデートがあり、ステートマシンの実行ステータスが変化したときにCloudWatchイベントが発行できるようになりました。
[アップデート]Step Functionsの実行ステータスが変化したときにCloudWatchイベントが発行できるようになりました!
今回はこちらの機能を利用し、Slackにステートマシンの実行ステータスを通知してみたいと思います。
目次
- 構成図
- Slack Webhook設定
- Lambda関数作成
- ステートマシン作成
- CloudWatchイベントルール作成
- 動作確認
構成
ステートマシンのステータスが変化した際に、CloudWatchイベントを発行し、CloudWatchイベントルールにてLambda関数を起動させます。
Slack Webhook設定
Slackワークスペースに「Incoming WebHooks」アプリを追加します。以下、URLにアクセスします。
https://ワークスペース名.slack.com/apps
上記URLのワークスペース名は適宜読み替えてください。
検索より「Incoming WebHooks」を入力し、結果に表示された「Incoming WebHooks」をクリックします。
「設定を追加」クリックします。
通知先のチャンネルを指定し「Incoming Webhook インテグレーションの追加」をクリックします。
WebHookのURLが表示されますので、このURLを控えておきます。(後ほどLambda関数で使用します。)
Lambda関数作成
CloudWatchイベントルールで起動させるLambda関数と、ステートマシンから起動させるLambda関数を作成します。
LambdaToSlack
CloudWatchイベントルールで起動させるLambda関数を作成します。
ここでは、メンション先(SlackメンバーID)を入力イベントで受けとるようにしました。ステータスがSucceeded
以外の場合、output
フィールドはNULL
になりますので、ステータスを判定してSucceeded
の場合は、ステートマシン(Lambda)が生成した値を通知し、Succeeded
以外の場合は、ステートマシンの実行ARNをメッセージとします。
先程控えた、SlackのWebhook URLは、環境変数に設定します。
Lambda関数のコードは以下となります。
import json import os from urllib.request import Request, urlopen def lambda_handler(event, context): #環境変数よりWebHook URL取得 hook_url = os.environ['HOOK_URL'] #ステートマシンのステータス取得 sf_status = event['detail']['status'] #ステートマシン実行ARN取得 sf_exec_arn = event['detail']['executionArn'] #inputイベントは文字列型のため辞書型に変換 input_event = json.loads(event['detail']['input']) #SlackメンバーID取得 slack_user_id = input_event['SlackUserId'] #ステータス判定 if sf_status == "SUCCEEDED": #outputイベントは文字列型のため辞書型に変換 output_event = json.loads(event['detail']['output']) #メッセージを取得(ステートマシンにて実行されるLambdaで生成) sf_result = output_event['result'] #メッセージ整形 message = "status : " + sf_status + "\n" + "result : " + sf_result else: #メッセージ整形 message = "status : " + sf_status + "\n" + "result : " + sf_exec_arn #SlackメンバーIDをメンション形式に整形 mention = "<@" + slack_user_id + ">" slack_message = { 'text': mention + "\n" + message, # メンション有効 'link_names': 1 } req = Request( hook_url, json.dumps(slack_message).encode('utf-8'), ) #リクエスト response = urlopen(req) response.read()
Function1
ステートマシンから起動させるLambda関数を作成します。実行時に渡すイベントで、戻り値を変えています。
def lambda_handler(event, context): flg = event['Function1'] if flg == "Success": ret_msg = "Function1 Success" else: ret_msg = "Function1 Fail" return ret_msg
Function2
ステートマシンから起動させるLambda関数を作成します。実行時に渡すイベントで、戻り値を変えています。
def lambda_handler(event, context): flg = event['Function2'] if flg == "Success": ret_msg = "Function2 Success" else: ret_msg = "Function2 Fail" return ret_msg
ステートマシン作成
Lambda関数を実行するステートマシンを作成しました。呼び出されたLambda関数は戻り値を返すようにしているので、Choice
にて戻り値を判定し、ステートを分岐させています。また、ResultPath
を使用して入力イベントの一部を置き換えています。
ステートマシンの定義は以下となります。
{ "StartAt": "Functions1", "States": { "Functions1": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:Function1", "ResultPath": "$.result", "Next": "Functions1 Success ?" }, "Functions1 Success ?": { "Type": "Choice", "Choices": [{ "Variable": "$.result", "StringEquals": "Function1 Success", "Next": "Functions2" }], "Default": "EndFail" }, "Functions2": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:Function2", "ResultPath": "$.result", "Next": "Functions2 Success ?" }, "Functions2 Success ?": { "Type": "Choice", "Choices": [{ "Variable": "$.result", "StringEquals": "Function2 Success", "Next": "EndSuccess" }], "Default": "EndFail" }, "EndFail": { "Type": "Fail" }, "EndSuccess": { "Type": "Succeed" } } }
CloudWatchイベントルール作成
ステートマシンが発行するCloudWatchイベントにて、Lambda関数を起動させるルールを作成します。
先程作成したステートマシンのARNを指定し、ここではSUCCEEDED
と、FAILED
ステータスを設定しました。ターゲットには先程作成したLambda関数「LambdaToSlack」を指定します。
動作確認
成功時
SUCCEEDED
ステータスの動作を確認します。以下のイベントを渡しステートマシンを実行します。
{ "Function1": "Success", "Function2": "Success", "SlackUserId": "UA7TVTSD6" }
「EndSuccess」ステートが実行され、ステータスが「成功」になりました。
指定したSlackユーザに、Lambda関数(Functions2)が生成した値「Function2 Success」が通知されました。
失敗時
Function1エラー
FAILED
ステータスの動作を確認します。以下のイベントを渡しステートマシンを実行します。
{ "Function1": "Fail", "Function2": "Success", "SlackUserId": "UA7TVTSD6" }
「EndFail」ステートが実行され、ステータスが「失敗」になりました。
指定したSlackユーザに、ステートマシンの実行ARNが通知されました。
Function2エラー
FAILED
ステータスの動作を確認します。以下のイベントを渡しステートマシンを実行します。
{ "Function1": "Success", "Function2": "Fail", "SlackUserId": "UA7TVTSD6" }
「EndFail」ステートが実行され、ステータスが「失敗」になりました。
指定したSlackユーザに、ステートマシンの実行ARNが通知されました。
さいごに
これまでステートマシン内で生成した値を通知しようとなると、つくりこみが必要でしたが、今回のアップデートで簡単に通知できるようになりましたね!!