Cloud FunctionsとCloud Schedulerを利用してDatadogで監視しているホスト数を通知させてみた

## 作ったもの

指定された期間のDatadogの監視台数について、最小,最大,合計(ホスト数×時間)を算出してSlackに通知してくれるCloudFunctionsを作成しました。そのCloudFunctionsはCloud Pub/Subで実行され、Cloud SchedulerはそのCloud Pub/SubのTopicを一日一度実行してくれます。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f32333630362f32306237373066382d356364322d323232312d363762302d6139623430663830616433382e706e67_censored.jpg](https://qiita-image-store.s3.amazonaws.com/0/23606/031e4088-19bd-46e9-e621-7c315a3dfb13.jpeg)


コードはこちらです。
https://github.com/selmertsx/datadog_slack_report

## この資料に記載されていること

- Cloud SchedulerからCloud Pub/Subを実行する方法
- DatadogでのRollup functionの使い方
- ※ Cloud Functionsに関する詳細な説明はしません。

CloudFunctionsを実行するための方法については、こちらの記事を参照してください。

https://qiita.com/selmertsx/items/31b10bfc4b72b05627e1
https://qiita.com/selmertsx/items/27686e51b4471eaf8c86

## 作った理由

- 今いる企業では複数のプロダクトでDatadogを利用してリソースの監視を行っていません
- Datadogでの監視はアカウントを分けていません
  - サーバーメトリクスは企業の資産であり、すべてのエンジニアが隣のプロダクトのサーバーメトリクスや監視方法を見て学ぶことができるように、敢えてアカウントは分けないようにしています
  - ちょっと声を掛けて見せて貰えばいいでないという声はあるかと思いますが、気になったときに誰の手も煩わせずに確認できるようにしたいという意図でそうしています
- アカウントを分けないで運用をしていると、プロダクト毎のコストを集計する必要がある
- コストの集計は自動でやってしまいたい
- 最近でた Cloud Schedulerを使ってみたい

## 事前準備

- 監視したいリソースにタグ付けをしてください
- 今回は `product: xxx` とタグ付けをしました
- タグの付け方は[こちらの資料](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Using_Tags.html)を参照してください
- もし僕のコードをそのまま動かす場合は、こちらのリポジトリをcloneしておいてください
    - https://github.com/selmertsx/datadog_slack_report

タグ付けを行ったら次の準備に進んでください。

## DatadogでのQueryの実行

DatadogではAPIを実行して、メトリクスを取得することができます。さらに、それらメトリクスに対して様々な計算処理を入れることも可能です。その実行方法については、[こちらの資料](https://docs.datadoghq.com/ja/api/#metrics-query)に記載されています。

さて、シンプルに各プロダクト毎のホスト数をAPIで取得したい場合、`count:system.cpu.user{*} by {product}`のようなクエリになります。ECインスタンスのメトリクスは5分毎にagentから送信されているため、１日分のデータを取得してしまうと`12 * 24 * プロダクト数`分のデータが必要になってしまいます。Datadogの課金体系から考えても、1時間未満の粒度でのデータは取得する必要がありません。そのため、不要なデータを削ぎ落とす必要があります。今回は`Rollup`関数を使って、データを１時間単位で丸め込んでから取得しました。これによって`24*プロダクト数`分のデータにすることができました。Rollup関数の説明は[こちら](https://docs.datadoghq.com/graphing/functions/rollup/)になります。抜粋した文書が下記になります。

> Rollup
> The function takes two parameters, method and time: .rollup(method,time) The method can be sum/min/max/count/avg and time is in seconds. You can use either one individually, or both together like .rollup(sum,120). 

この説明通りにクエリを作成してみると、`count:system.cpu.user{*} by {product}.rollup(count, 3600)` という形になりました。TypeScriptのコードは下記のようになります。

```typescript
// https://github.com/selmertsx/datadog_slack_report/blob/master/src/DatadogClient.ts#L28
  public async countHosts(from: string, to: string): Promise<DatadogHostMetrics[]> {
    const params: CountHostRequest = {
      api_key: API_KEY,
      application_key: APP_KEY,
      from,
      query: `count:system.cpu.user{*} by {product}.rollup(count, 3600)`,
      to,
    };

    const res: DatadogQueryReponse = await this.request.get("/query", { params });
    return res.data.series.map((product: SeriesMetrics) => {
      const pointlists: PointList[] = product.pointlist.map((point: number[]) => {
        return { unixTime: point[0], count: point[1] };
      });
      return { product: product.scope, pointlists }
    });
  }
```

僕のコードの中にDatadogのAPIで帰ってくるレスポンスの型(の一部)を記載しておきましたので、データの中身について気になる方は目を通されると良いでしょう。

## Cloud Functionsのデプロイ

Google Cloud Pub/SubをトリガーにCloud Functionsを起動する設定をしていきます。Google Consoleから`datadog_report`というtopicを作成し、下記のコマンドでCloud Functionsをデプロイしましょう。

```console
gcloud beta functions deploy datadog_handler \
  --region=asia-northeast1 \
  --stage-bucket=datadog_report \
  --trigger-event=google.pubsub.topic.publish \
  --trigger-resource=datadog_report \
  --runtime=nodejs8
```

Cloud FunctionsのトリガーとしてCloud Pub/Subを利用する方法については、[このドキュメント](https://cloud.google.com/functions/docs/calling/pubsub)に詳細が記載されています。

## Cloud Schedulerの設定

GCPのConsoleから、cloud schedulerを開いてみましょう。そこでcreate jobを選び、下記のように設定をします。ここでFrequencyが実行頻度を設定する部分です。cronと同じフォーマットで実行する頻度を設定することができます。そしてTargetがトリガーの設定部分です。ここではApp Engineのアプリケーション、Cloud Pub/Sub, HTTP Requestの３つを設定することができます。今回のCloudFunctionsはPub/Subをトリガーにしているので、ここではPub/Subを指定しておきましょう。

![スクリーンショット 2018-11-11 22.53.10.png](https://qiita-image-store.s3.amazonaws.com/0/23606/ac654db5-78b9-8ab1-d225-981bfa40b5c1.png)

`create` ボタンを押せば終了です。気になるお値段ですが、[こちらのドキュメント](https://cloud.google.com/scheduler/)によると1人あたり３ジョブまで無料ということです。

## 動作確認

![スクリーンショット 2018-11-11 22.59.31.png](https://qiita-image-store.s3.amazonaws.com/0/23606/82bec9b7-1e88-a4de-24a5-dee5529d7525.png)

すぐに動作確認をしたいので、上記画面の`Run now` ボタンをクリックし、Pub/SubのTopicに対してメッセージを送ってみましょう。するとSlackに下記のようにメッセージが送信されます。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f32333630362f32306237373066382d356364322d323232312d363762302d6139623430663830616433382e706e67_censored.jpg](https://qiita-image-store.s3.amazonaws.com/0/23606/031e4088-19bd-46e9-e621-7c315a3dfb13.jpeg)

以上で、Cloud FunctionsとCloud Schedulerを利用してDatadogで監視しているホスト数を通知させることができました。今後は、集計期間をpub/subのメッセージで設定できるようにするなど機能を追加していく予定です。もし、使ってくださる方がいて、追加で欲しい機能などございましたら、お気軽にIssue登録おねがいします〜