Amazon-CloudWatch

CloudWatch Logsに記録されたエラー文をサブスクリプションフィルターでSlackに通知するようにしてみた

はじめに

こんにちは、omkです。
Lambdaで動作するアプリケーションでエラーが発生した際に、ログを簡単に確認できるようにしたかったのでSlackに通知してみました。

アプリケーション上で直接通知することも可能ですが、既存のアプリケーションを触りたくはなかったので後付けで設定出来るようにしています。

アーキテクチャ

ログの発行元はLambdaです。
LambdaはネイティブでログをCloudWatch Logsに出力してくれます。

CloudWatch LogsのエラーログをSlackに通知するのにCloudWatchL Logsのサブスクリプションフィルターを利用します。
これはログをフィルタリングして「OpenSearch Service」「Kinesis Data Streams」「Kinesis Data Firehose」「Lambda」へストリーミングしてくれます。
今回は最終的にSlackに通知したいので、SlackのメールアドレスをサブスクリプションしたSNSに通知することとし、Lambdaにストリームするサブスクリプションフィルターを作成します。
(メールではなくChatbotとかAPIでも出来るかもしれませんが検証してないです)

簡単にですがこんな感じの構成になります。

やってみた

Lambdaのエラー出力としては「ERROR」「error」がそれぞれ別の内容で出力される前提で以降記載していきます。
また、Lamdbaには適切なIAMポリシーが割り当たっており、CloudWatch Logsへの出力は問題なく行われている想定です。

図の後ろの方から作成していきます。

SNSトピックの作成とSlackメールのサブスクライブ

Slackの通知したいチャンネル上で「チャンネルにメールを送信する」というボタンがありますのでこれを押してメールアドレスを取得します。
便利なので私はよく使っています。

適当なスタンダードのSNSトピックを作成してこのメールアドレスをサブスクライブします。
チャンネルに認証メールが来るので認証します。

エラー通知用のLambdaを作成

今回はPython3.12で通知用の関数を作っていきます。
Python3.12であれば必要なライブラリは標準で導入されています。ログの形式はサブスクリプションフィルターでの「その他」を想定しています。

import json
import boto3
import base64
import gzip

topic = "{通知先トピックのARN}"

def lambda_handler(event, context):
    # ログはbase64にエンコードした上でgzipで圧縮されているのでデコード、解凍する
    log_gzip = gzip.decompress(base64.b64decode(event['awslogs']['data']))

    # 解凍後はバイトになっているのでUTF-8に変換する
    log = log_gzip.decode('utf8')

    log_dict = json.loads(log)

    # エラー文が複数件ヒットする場合もあるのでforでまとめる
    error_message = ""

    for log in log_dict['logEvents']:
        error_message += log['message']
        error_message+= "\n"

    # 通知
    sns = boto3.client('sns')
    sns.publish(
        TopicArn=topic,
        Message=error_message
    )

    return

サブスクリプションフィルターの作成

エラー文を通知したい対象のロググループに対して設定します。
コンソールから簡単に作れます。
今回はLambdaに渡したいので「Lamdbaサブスクリプションフィルター」を指定します。

フィルターパターンはフィルタリングしたいログの形式に合わせて設定します。
今回はエラー文が「ERROR」もしくは「error」という文言が含まれて出力されるので以下で設定します

?ERROR ?error

?で設定することでOR条件でフィルタリングしてくれます。
Lambdaは作成したもので、ログの形式はその他で作成します。

確認

これで必要な設定は完了したのでアプリでエラーを出して確認していきます。

RequestId: 2f29afee-f334-48e6-8b2f-178f542ac032 Error: Runtime exited with error: exit status 1
Runtime.ExitError

--
If you wish to stop receiving notifications from this topic, please click or visit the link below to unsubscribe:(略)

メールが来ました。
全然伝わらないと思うので皆様もご自分の環境で試してみてください。

おわりに

メトリクスフィルターはよく使ってたのですがサブスクリプションフィルターはあんまり使っていなかったので良い機会になりました。
ログベースで処理出来るので扱いやすく、Lambdaが使えるのでどこにでも集約できて便利ですね。

以上、最後までお付き合いありがとうございました!

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA