4xx Client Error (クライアントエラー)をCloudWatchLogsで検知してメール送信する

#初めに
CloudWatch Logsにて、特定のエラーログを取得したいケースは多いかと思います。
今回はWebサーバにて4xx台のレスポンスが返ってきた際に、CloudWatch Logsで検知してメール送信するための方法を備忘録として纏めていきたいと思います。

#前提
・事前にEC2（Amazon Linux 2）を作成済み
・EC2にnginxをインストール済み

#実装
###①CloudWatch Logsエージェントの設定
EC2にログインし、CloudWatch Logsエージェントをインストールします。

```linux:
# yum install -y awslogs
```


次にCloudWatch Logsエージェントが出力する先のリージョンを指定します。
/etc/awslogs/awscli.confに設定されているリージョンを、デフォルトのus-east-1からap-northeast-1に変更します。

```linux:awscli.conf
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
```

続いてCloudWatch Logsエージェントの設定ファイルである/etc/awslogs/awslogs.confの設定を行います。
今回はnginxのaccess.logに出力されるログを収集する必要があるので、その設定を行います。
以下設定値を、ファイルの末尾に追記します。

```linux:awslogs.conf
~~~省略~~~

[Nginx_AccessLog]
log_group_name = /var/log/nginx/access.log
log_stream_name = {instance_id}_accesslog
file = /var/log/nginx/access.log
datetime_format = %b %d %H:%M:%S
initial_positon = start_of_file
buffer_duration = 5000
```

最後にCloudWatch Logsエージェントの起動を行います。
systemctlでstartを行い、status確認でエラー無く起動されていれば、エージェントの設定は完了です。

```linux:
# systemctl start awslogsd
# systemctl status awslogsd
● awslogsd.service - awslogs daemon
   Loaded: loaded (/usr/lib/systemd/system/awslogsd.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-02-11 11:35:42 UTC; 22s ago
 Main PID: 3895 (aws)
   CGroup: /system.slice/awslogsd.service
           mq3895 /usr/bin/python2 -s /usr/bin/aws logs push --config-file /e...

Feb 11 11:35:42 ip-10-0-0-219.ap-northeast-1.compute.internal systemd[1]: Sta...
Hint: Some lines were ellipsized, use -l to show in full.
```

###②IAMロールの割り当て
続いてCloudWatch LogsエージェントがCloudWatch Logsにログを連携可能とするための権限割り当てを行っていきます。
IAMロールの作成画面にて[一般的なユースケース]から[EC2]を選択し、[次へ]をクリックします。
![WS000072.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/776ee3f5-9b84-de3e-2b8c-48c07a06d402.jpeg)

許可ポリシーの設定画面にて、[CloudWatchLogsFullAccess]ポリシーを選択し、[次へ]をクリックします。
![WS000005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/8d14fd06-2dfa-d8c6-64ec-59d9acca9335.jpeg)

ロール名を入力し、画面下部の[ロールの作成]をクリックします。
（今回は「nginx-Access-Log-Policy」という名前にしました）
![WS000006.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/3050aeea-c0cc-42bb-1588-66b3f66eb01f.jpeg)

[ロール nginx-Access-Log が作成されました]と出力されれば、作成は成功です。
![WS000007.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/5c8e4874-368f-3ef4-5243-7df47bdbe33b.jpeg)

あとはこのロールを、CloudWatch Logsエージェントをインストールしたインスタンスにアタッチします。
EC2のコンソール画面から対象EC2を選択し、[アクション]>[セキュリティ]>[IAMロールを変更]をクリックし、アタッチを行います。
![WS000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/ae2637c7-67ad-9627-78b4-36a7632036d4.jpeg)

これにより、CloudWatch Logsのロググループに今回設定したロググループが表示されるようになります。
![WS000011.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/f18142e0-9bb1-26f0-6d79-338a25c06989.jpeg)

###③メトリクスフィルターの設定
nginxのアクセスログをCloudWatch Logsで取得するところまでは出来たので、今回の対象のエラーコードである4xxのみをフィルターする設定を行っていきます。

CloudWatch Logsの画面から、作成した「/var/log/nginx/access.log」のロググループを選択し、「メトリクスフィルターを作成」をクリックします。
![WS000013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/65ff25aa-9414-c58f-034e-a8f7aae6080b.jpeg)

フィルターパターン[host, logName, user, timestamp, request, statusCode=4*, size]を指定し、[Next]をクリックします。
![WS000014.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/48cbd5d8-2741-9d8f-bbac-81355cc8fd6f.jpeg)

フィルター名、メトリクス名前空間、メトリクス名、メトリクス値、デフォルト値をそれぞれ入力し、画面下部の[Next]をクリックします。
![WS000016.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/1086899e-b242-1db8-b95f-826354e1d18d.jpeg)

設定内容を確認し、[メトリクスフィルターを作成]をクリックします。
![WS000018.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/bab92a8d-cb68-a0d5-1d0e-f1c4a4df5300.jpeg)

メトリクスフィルター画面で、作成したメトリクスフィルターが表示されていれば設定は完了です。
![WS000019.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/0820df95-9ed1-2055-24b5-4e2ed8d34a1b.jpeg)

###④CloudWatch Alarmの作成
最後に、フィルターして拾ってきたログをメールに通知するための設定を行います。
CloudWatch Logsの画面から、[アラームの作成]をクリックします。
![WS000020.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/57ce0000-d017-61cd-a59c-4404761fb1a9.jpeg)

[メトリクスの選択]>[③で設定した名前空間]>[ディメンションなしのメトリクス]をクリックし、作成したメトリクスフィルターにチェックを入れます。
そして[メトリクスの選択]をクリックします。
![WS000040.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/e8f7fbe4-00cb-815c-84a7-959bcfa6ad65.jpeg)

次にメトリクスの条件を指定します。
今回はメトリクス名を「Nginx-4xx-Error-Metrics」とし、1分間の間に1回以上の4xxエラーを検知した場合にトリガーされるように設定します。
そして画面下部の[次へ]をクリックします。
![WS000039.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/cb5cc012-5fce-0874-5c4f-503537242211.jpeg)

続いてアクションの設定を行います。
アラーム状態トリガーは[アラーム状態]を選択します。
そして今回は「nginx-4xx-Topic」という名前のSNSトピックを新たに作成してアラームの送信先のEメールエンドポイントを設定し、画面下部の[次へ]をクリックします。
![WS000024.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/62cfbaa0-034e-0ffc-a573-974250efc03d.jpeg)

アラーム名を入力し、[次へ]をクリックします。
（今回は「nginx-4xxError-Alarm」としました）
![WS000025.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/37eb0f29-d7aa-cde4-4e54-db1aa6e291fd.jpeg)

プレビューにて設定を確認し、問題なければ[アラームの作成]をクリックします。
![WS000027.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/0d2bdf24-2d6d-2115-6fa1-035636857296.jpeg)

「アラームnginx-4xxError-Alarmが正常に作成されました。」と表示されれば、作成は完了です。
![WS000028.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/ddb87b9d-de3c-f5e9-c89d-1d89397e28c3.jpeg)

また、アクションの設定で作成したSNSトピックの送信先のメールアドレス宛にサブスクリプションを承認するためのメールが届いているので、Confirmを行います。
![WS000030.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/b68a0fd7-537e-8402-52c0-d7a024e1c651.jpeg)

Confirmされると以下のメッセージが表示されます。
これにて全ての設定は完了になります。
![WS000031.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/ca102276-7e2b-3ffd-162d-3815c35970a0.jpeg)

#検証
作成したEC2のパブリック IPv4 DNSをブラウザのアドレスバーに入力し、存在しないページを末尾に追加して404エラーを意図的に発生させてみます。
![WS000035.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/34574d13-186d-380c-3d57-aa21c7fd01f8.jpeg)

暫くすると、404エラーを通知するメールがちゃんと届くことを確認できました。
![WS000041.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689573/3070be2b-22f6-05d3-41bc-00a7c93c807b.jpeg)

#最後に
以上、今回は4xx Client Error (クライアントエラー)をCloudWatchLogsで検知してメール送信する方法を纏めてみました。
こんなにシンプルにエラーログの通知が行えるは凄いですね。