CloudWatchカスタムメトリクスに任意の値を登録してグラフで監視する

## 概要
CoudWatchカスタムメトリクスって知ってますか？
通常のCloudWatchメトリクスは使ったことがある人が多いと思いますがカスタムメトリクスはそうでもないかもしれません
通常のメトリクスがAWSが用意したリソースしか監視できないのに対し、CloudWatchカスタムメトリクスは何でも監視してグラフ化出来る優れものです


### どうやって監視するか
監視といってもカスタムメトリクスは変動する値を継続的に読み込んでくれるわけではありません
CLIやSDK等を使って監視したい値をその都度メトリクスに送信してグラフを作成するわけです
今回はAWSCLIを使用する方法とLambdaを使用する方法を紹介します

## AWSCLIを使う
まずCLIを使える環境を用意しましょう
私はローカルに導入するのが面倒だったのでEC2インスタンスを立てました
### アクセスキーの作成
認証情報にアクセスキーが必要なので作成しておきましょう
IAMコンソール→ユーザー→認証情報→アクセスキーの作成ボタンをクリックです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/9751a0ef-210b-aca9-9fed-c6862a0dd323.png)
IDが二つ表示されますのでメモしといてください
### CLIのセットアップ
SSHで接続したら`aws configure`コマンドで簡単に設定しちゃいましょう

    $ aws configure
    AWS Access Key ID [None]: さっきメモしたやつ
    AWS Secret Access Key [None]: さっきメモしたやつ
    Default region name [None]: ap-northeast-1
    Default output format [None]: json
これでawsコマンドがちゃんと使えるようになりました
### カスタムメトリクスを登録する
AWSCLIのセットアップが終わったところで早速カスタムメトリクスを登録してみましょう
次のコマンドを叩いてください
`$ aws cloudwatch put-metric-data --namespace CustomMetrics --metric-name Test --dimensions CLI=RandomNum --value 100`
なんだかオプションがたくさん並んでいますが実は簡単です
`namespace`,`metric-name`,`dementions`は全て識別子なので好きな名前を付けちゃってください
大事なのは`value`だけです。これが実際にメトリクスに登録される値です
今回は100という数値を登録しました
早速メトリクスを見てみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/8d392391-2ff3-10db-6471-8788cc9564d2.png)
しっかり送信されていますね
見にくいですが青い点が今登録した値です
しかしこんな点を登録したところで何の役にも立たないのでグラフにしていきましょう

    #!/bin/bash
    while true
    do
    NUM=$(($RANDOM % 100))
    aws cloudwatch put-metric-data --namespace CustomMetrics --metric-name Test --dimensions CLI=RandomNum --value $NUM
    sleep 60
    done &

今回は0~100のランダム数値を送信する簡単なスクリプトを書きました
これをEC2上で実行してみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/afbab456-9073-c2ae-75bb-5daeeb6a8e55.png)
いい感じのグラフが出来ましたね

## Lambdaを使う
Lambdaを使った登録も可能です
大体の流れは一緒ですがLambdaではランタイム毎に用意されたSDKを使うことになります
今回はNode.jsで実装してみましょう

### IAMロールの作成
CloudWatchにアクセスするロールをLambdaにアタッチする必要があります
ユースケースからLambdaを選んでCloudWatchFullAccessを含んだロールを作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/29c82689-8845-0cc9-9cb3-bcbbeb952598.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/fb3ca2b6-7f2f-3337-297e-7dc1454052aa.png)

### Lambda関数の作成
ロールを作成したらLambda関数を作成します
先程作成したロールを作成時にアタッチしましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/3fa84a9a-24a4-40e9-5801-bb2c0fdd4394.png)


### サンプルコード
    const AWS = require('aws-sdk');

    exports.handler = (event, context, callback) => {
      const rundom_num = Math.floor(Math.random() * (100))
      const params = {
        MetricData: [ 
          {
            MetricName: 'Test', 
            Dimensions: [
              {
                Name: 'Lambda', 
                Value: 'Random_num' 
              }
            ],
            Timestamp: new Date,
            Unit: 'Count',
            Value: rundom_num,
          }
        ],
        Namespace: 'CustomMetrics' 
      };
      
      const cloudwatch = new AWS.CloudWatch({ region: 'ap-northeast-1' });
      cloudwatch.putMetricData(params, function (err, data) {
        if (err) console.log(err, err.stack);
        else console.log(data);
      });
    }

今回も0~100のランダム数値を登録します
Lambda関数ではオプションをMetricDataに記述してputMetricDataで送信します
CLIで登録した時と同じようなオプションが並んでいるので難しくないですね

`Timestamp`はメトリクスに登録される時刻です 
基本的には現在時刻を登録することになると思いますがそれ以外も指定することが可能です  
`unit`は登録する値の単位です
以下の中から選択できますが今回は`Count`を選択しました

    "Seconds"
    "Microseconds"
    "Milliseconds"
    "Bytes"
    "Kilobytes"
    "Megabytes"
    "Gigabytes"
    "Terabytes"
    "Bits"
    "Kilobits"
    "Megabits"
    "Gigabits"
    "Terabits"
    "Percent"
    "Count"
    "Bytes/Second"
    "Kilobytes/Second"
    "Megabytes/Second"
    "Gigabytes/Second"
    "Terabytes/Second"
    "Bits/Second"
    "Kilobits/Second"
    "Megabits/Second"
    "Gigabits/Second"
    "Terabits/Second"
    "Count/Second"
    "None"
    

任意の値を登録、監視するにはこれで十分ですが他のパラメータも用意されています
今回使用しなかったパラメータの詳細は公式ドキュメントを参照してください
さて、実際にコードを走らせてみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/6e4ffa7f-7062-f503-6b29-80c9ad80961b.png)
ちゃんと登録されていますね

### 関数を定期実行させる
Lambdaの場合シェルスクリプトみたいにWhileで定期実行させられないのでEventBridgeの機能を使っていきます
設定から「トリガーを追加」ボタンをクリックです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/1ae00df2-c3e5-e103-d925-fb4c762ff761.png)
![image](https://user-images.githubusercontent.com/66783124/120430227-a7fdfc00-c3b1-11eb-970d-340095bbd966.png) 
トリガーにEventBridgeを選択してルールを決めます
今回は一分毎に実行させる`rate(1 minute)`を設定しました
ここら辺を詳しく知りたい方はEventBridgeの公式ドキュメントを読んでください 
最後にメトリクスを見に行きましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662213/73d52b59-3d65-e7e0-2bc8-01a3bb6be36c.png)

ちゃんとグラフになっていますね

## さいごに
今回はただの乱数を使用しましたがValueさえ変えてしまえば様々なことに応用できます
みなさん独自のオレオレメトリクスを作って自慢してやりましょう