AWS Lambdaのメモリ使用率をCloudWatchで可視化する一連の手順

AWS Lambdaには、Lambda関数の実行時間や実行回数などが記録されるCloudWatchメトリクスが標準で備わっています。しかし、メモリ使用率についてはメトリクスがありません（2017-12-06時点）。

クラスメソッド社の渡辺さんが公開されている[`mem2cw`を使うと、AWS Lambdaのメモリ利用率メトリクスをCloudWatchに追加](https://dev.classmethod.jp/cloud/aws/send-lambda-memory-usage-to-cloudwatch/)することができます。ぜひともAWS公式でサポートされて欲しいところですね。

上記リンク先の記事中では詳細な手順が省かれておりました。そこで、AWS歴の浅い私のような初心者向けに必要な手順をまとめます。


## 前提

この記事は以下を使用して検証しました。

* `aws-cli/1.11.129 Python/3.6.1`
* `mem2cw` ([`20ebd42551`](https://github.com/watanabeshuji/mem2cw/blob/20ebd425519d96112dc0d22fb80bbdaebee30e1e/mem2cw.yml))
* `jq` (version 1.3)


## 手順

### 1. CloudFormationで`mem2cw`を作成

スタックの作成は、同一AWSアカウントの同一リージョンであれば、基本的に1回やれば十分かと思います。
そこでこの記事では割り切ってGUI（CloudFormationコンソール）を使います。
`mem2cw`を作成したいリージョンが多ければ、CLIでスクリプト化するのもよいでしょう。

#### 1-1. テンプレートを入手する

Githubレポジトリ https://github.com/watanabeshuji/mem2cw を clone し、テンプレートファイル`mem2cw.yml` を入手します。

#### 1-2. スタック作成画面に行く
![step1.jpg](https://qiita-image-store.s3.amazonaws.com/0/1020/4a3242c9-2a2e-c1f1-aaf5-06dff5d97cf3.jpeg)


#### 1-3. テンプレートをアップロード
テンプレートファイル`mem2cw.yml`をS3アップロードし、CloudFormationに読み込ませるのが便利です。
![step2.png](https://qiita-image-store.s3.amazonaws.com/0/1020/8c754742-76ee-4cd7-1732-d8f80851db52.png)

#### 1-4. スタック名をつける
スタック名は空欄となっているので、妥当な名前を自分で入力する必要があります。
![step3.jpg](https://qiita-image-store.s3.amazonaws.com/0/1020/8d93fc19-ac5e-0327-2783-691971f087db.jpeg)

#### 1-5. 必要に応じてオプション設定
![step4.jpg](https://qiita-image-store.s3.amazonaws.com/0/1020/2f2c3f20-854e-28ca-1849-7b9b7159f691.jpeg)

#### 1-6. CAPABILITYを確認し、スタック作成
`mem2cw.yml`テンプレートは、ある権限を持ったIAMロールを必要とします。
組織のセキュリティポリシーに応じて、自分でIAMロールを用意することもできますが、「CAPABILITY」欄のチェックボックスにチェックを入れて自動作成してもらうこともできます。
![step6.jpg](https://qiita-image-store.s3.amazonaws.com/0/1020/0c99f38b-5b18-9731-0f5f-b69bb0d12a2b.jpeg)

#### 1-7. スタックが作成されるまで待つ
状況が `CREATE_COMPLETE` になればOKです。
![step7.jpg](https://qiita-image-store.s3.amazonaws.com/0/1020/3bcd725e-d735-3fb5-d4dc-662438a74670.jpeg)


### 2. メモリ使用率を知りたいLambdaのログを`mem2cw`に監視させる


#### CloudWatchのサブスクリプション・フィルタとは

サブスクリプション・フィルタは「特定のパターン（filter-pattern）にマッチするログ」がロググループに出力されたときに任意のLambdaを起動し、何か処理させる仕組みです。

`mem2cw`は、サブスクリプション・フィルタを使ってロググループを監視するようになっています。

#### サブスクリプション・フィルタの設定

メモリ使用率を可視化したいLambda関数は、いくつもあると思います。多数の関数に同じ設定を手入力で指定するのは時間もかかり、間違えやすいですね。

そこで、次のような `aws-cli` を使ったコマンドで一括指定するのが良いでしょう。

```bash
# 自身の環境に合わせて修正します。
region="XXXXXX"
accountId="0000000000"
memoryMetricsLambda="Lambda-memory-2-CloudWatc-PutMetricDataWhenFindMem-XXXXXXXXXXX"
mem2cwLambdaARN="arn:aws:lambda:${region}:${accountId}:function:${memoryMetricsLambda}"
env="DEV"

# 「自分がメモリ使用率を見たいLambdaのロググループ」だけになるよう、`jq`で絞り込む条件を適宜修正します
logGroups=$(aws logs describe-log-groups | jq --arg ENV $env '.logGroups[] | select(.logGroupName | (contains("/aws/lambda") and contains($ENV) )) | .logGroupName' -r)
while read -r myLogGroup; do
    aws logs put-subscription-filter \
        --log-group-name ${myLogGroup} \
        --filter-name LambdaMemory \
        --filter-pattern "\"Memory Size:\"" \
        --destination-arn ${mem2cwLambdaARN}
done <<< "${logGroups}"
```

### 3. メトリクスを利用する

対象のLambdaを実行してみて、メトリクスに値が表示されるのを確認できたら成功です。
![metrics.png](https://qiita-image-store.s3.amazonaws.com/0/1020/0289cdfe-1c3b-a673-596c-6911354144d7.png)


## まとめ

* Lambdaのメモリ使用率をメトリクスにする `mem2cw` すばらしい
* 作者のクラスメソッド社 渡辺さん、ありがとうございます
* CloudWath Logsのサブスクリプション・フィルタを使うと、ログに特定のパターンが現れたときにLambdaを実行できる