監視用サーバーを立てずにWEBのURLヘルスチェックを行う

# 目的
構築したWEBサーバーのページがちゃんと見えてるか確認したい
でもわざわざ監視用のサーバーは立てたくない

# 構成
１．CloudWatch EventsのスケジュールイベントでLambdaを呼び出す
２．Lambdaで指定したページにリクエストを飛ばす
３．200が返ってきたらCloudWatchに1をputし、それ以外の場合は0をputする

![image](https://qiita-image-store.s3.amazonaws.com/0/40136/56fc1d23-7aa1-d99c-937e-0e8ebd9fdd6f.png)

# 実装
## IAMロールの作成

LambdaからCloudWatchにメトリクスをputするためのロールを作成します。

今回は、「urlHealthCheckRole」というロールを作成し、以下ポリシーを設定しました。

```json:urlHealthCheckPolicy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1477640920000",
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

## Lambdaファンクションの作成

各種設定は以下を選んでください。

>Runtime ： **Node.js 4.3**
Role ： **urlHealthCheckRole**

また、今回は

>Memory ： **128MB**
Timeout ： **10 sec**

としています。

Lambdaのコードは以下のとおりです。

```js:urlHealthCheckFunction
'use strict';

console.log('Loading function');
const AWS = require("aws-sdk");

exports.handler = (event, context, callback) => {

    const generator  = (function *() {

        try {
            
            const siteUrl = event.url;
            const result  = yield checkUrl(siteUrl, generator);

            // メトリクスをput
            yield putMetricData(siteUrl, result, generator);

            callback(null, 'success');

        } catch (e) {

		    callback(e.message);

		}
    })();

    /* 処理開始 */
    generator.next();
};

function checkUrl(siteUrl, generator) {
    const request = require('request');

    request(siteUrl, function(error, response, body) {
        if(!error && response.statusCode === 200) {
            // 正常の場合は1
            generator.next(1);
        } else {
            // 異常の場合は0
            generator.next(0);
        }
    });
}

function putMetricData(siteUrl, result, generator) {
    const cloudwatch = new AWS.CloudWatch();

    const params = {
        MetricData: [
            {
                MetricName: 'urlHealth',
                Dimensions: [
                    {
                        Name: 'siteUrl',
                        Value: siteUrl
                    }
                ],
                Timestamp: new Date(),
                Unit: 'None',
                Value: result
            }
        ],
        Namespace: 'urlHealth'
    };

    cloudwatch.putMetricData(params, function(err, data) {
        if(err) {
            console.log(err, err.stack);
			generator.throw(new Error('put metric data error'));
			return;
        }
        generator.next();
    });
}
```

このコードを[requestモジュール](https://www.npmjs.com/package/request)と一緒にzip化してアップロードしてください。

## CloudWatch Eventsの設定

CloudWatch Eventsでルールの作成を行います。
今回は、

>http://www.shinko-1930.co.jp/index.html というページに1分間隔でヘルスチェックを行う

という設定を行っています。
具体的な設定値は以下のとおりです。

>イベントソースの選択 ： **スケジュール　一定の速度　1分**
ターゲット ： **Lambda関数**
　機能 ： **urlHealthCheckFunction**
　バージョン/エイリアスの設定 ： **デフォルト**
　入力の設定 ： **定数 (JSON テキスト)**
　　　　　　　 **{"url":"http://www.shinko-1930.co.jp/index.html"}**
　　
<img width="1123" alt="CloudWatch_Management_Console.png" src="https://qiita-image-store.s3.amazonaws.com/0/40136/a3d05da9-71de-f158-c1b5-bbbf7c9cfce1.png">

# 確認

CloudWatch Eventsを作成後しばらくするとCloudWatchのトップ画面左ペインのカスタムメトリックスに「urlHealth」というメトリクスが表示されるので選択してみてください。

<img width="165" alt="スクリーンショット 2016-10-28 17.27.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/40136/8591bd29-9439-f547-14fd-c91071a4e78a.png">

1分おきに**1（正常）**がputされていることを確認できます。

<img width="1128" alt="CloudWatch_Management_Console.png" src="https://qiita-image-store.s3.amazonaws.com/0/40136/a5f71229-62e5-e134-9e56-eb569e347e3a.png">

# 以上

ここまでできればCloudWatchのアラームを作成し、SNSで通知等いつもどおりの運用ができるはずです！
※私はサイト異常時にSNS経由でLambdaをキックし、インスタンスの再起動を行うようにしてみました。

小規模なWEBサイト構築時にわざわざ監視用のサーバーを立てるのは馬鹿らしいし、Lambdaだったら無料利用枠の範囲内でURL監視できるので素敵だなと感じました。

何かありましたら是非コメントをお願いします！