CloudWatchのログで特定の文字列が出たらLambdaを起動させる

2021/03/24に公開
2

CloudWatchのサブスクリプションフィルターという機能を使うことで、例えばECSでバッチ処理を行っていて、開始,終了やエラーをCloudWatchログに出してそれらをLambda経由でSlackへ通知することができます。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/SubscriptionFilters.html

Lambda作成

あらかじめLambdaを作成しておく必要があります。
後にCloudWatchサブスクリプションフィルターを作成する時にどのLmanda関数を使うか選択する画面があるので。

Lambdaが起動されたか確認するために、
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/SubscriptionFilters.html にあるように以下のようにindex.jsを実装します。
console.logの部分がCloudWatchログへ出力されます。
inputにはClouWatchサブスクリプションフィルターから送られてくるデータが入っています。

// index.js
var zlib = require('zlib');
exports.handler = function(input, context) {
    var payload = Buffer.from(input.awslogs.data, 'base64');
    zlib.gunzip(payload, function(e, result) {
        if (e) { 
            context.fail(e);
        } else {
            result = JSON.parse(result.toString('ascii'));
            console.log("Event Data:", JSON.stringify(result, null, 2));
            context.succeed();
        }
    });
};

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

ログの検知を行いたいCloudWatchログでサブスクリプションフィルターを作成します。

先ほど作成したLambdaを選択。


パターンは
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html
を参考に
?start ?end
とします。
(日本語や一部記号は使えませんでした)
これでstartもしくはendの文字列が含まれるログが出力されるとLambdaが起動します。

動作確認

実際にECSのタスクを起動->CloudWatchへのログ出力->サブスクリプションフィルターでLamnda起動->LambdaのCloudWatchログをみて起動を確認

ECSタスク定義にてコマンドをecho startとし、タスクが実行されるとstartという文字が出力されるようにしておきます。

タスクを実行してみるとstartがCloudWatchログへ出力。

このログをサブスクリプションで拾ってLambdaが実行されているはず。
Lambdaのログをみてみると、実行されていることが確認できました。

Lambdaが受け取れるパラメータは以下のようになっています。

{
    "messageType": "DATA_MESSAGE",
    "owner": "hogehogehoge",
    "logGroup": "/ecs/embulk",
    "logStream": "ecs/embulk/0cd3f8e4a13840c396f45fa9b7ff90c9",
    "subscriptionFilters": [
        "embulk-test-filter-name"
    ],
    "logEvents": [
        {
            "id": "36048248338279890932333964403104620581013505171129171968",
            "timestamp": 1616459361217,
            "message": "start"
        }
    ]
}

どのログで検知したのか、検知したログの内容などが取得できます。

あとは、Lambdaに行いたい処理を書けば、例えばslackへ通知したりSNSでメールを送信したりすることができます。

Discussion