Cloud FunctionsとCloud Schedulerを利用してDatadogで監視しているホスト数を通知させてみた
作ったもの
指定された期間のDatadogの監視台数について、最小,最大,合計(ホスト数×時間)を算出してSlackに通知してくれるCloudFunctionsを作成しました。そのCloudFunctionsはCloud Pub/Subで実行され、Cloud SchedulerはそのCloud Pub/SubのTopicを一日一度実行してくれます。
コードはこちらです。
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
とタグ付けをしました - タグの付け方はこちらの資料を参照してください
- もし僕のコードをそのまま動かす場合は、こちらのリポジトリをcloneしておいてください
タグ付けを行ったら次の準備に進んでください。
DatadogでのQueryの実行
DatadogではAPIを実行して、メトリクスを取得することができます。さらに、それらメトリクスに対して様々な計算処理を入れることも可能です。その実行方法については、こちらの資料に記載されています。
さて、シンプルに各プロダクト毎のホスト数をAPIで取得したい場合、count:system.cpu.user{*} by {product}
のようなクエリになります。ECインスタンスのメトリクスは5分毎にagentから送信されているため、1日分のデータを取得してしまうと12 * 24 * プロダクト数
分のデータが必要になってしまいます。Datadogの課金体系から考えても、1時間未満の粒度でのデータは取得する必要がありません。そのため、不要なデータを削ぎ落とす必要があります。今回はRollup
関数を使って、データを1時間単位で丸め込んでから取得しました。これによって24*プロダクト数
分のデータにすることができました。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のコードは下記のようになります。
// 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をデプロイしましょう。
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を利用する方法については、このドキュメントに詳細が記載されています。
Cloud Schedulerの設定
GCPのConsoleから、cloud schedulerを開いてみましょう。そこでcreate jobを選び、下記のように設定をします。ここでFrequencyが実行頻度を設定する部分です。cronと同じフォーマットで実行する頻度を設定することができます。そしてTargetがトリガーの設定部分です。ここではApp Engineのアプリケーション、Cloud Pub/Sub, HTTP Requestの3つを設定することができます。今回のCloudFunctionsはPub/Subをトリガーにしているので、ここではPub/Subを指定しておきましょう。
create
ボタンを押せば終了です。気になるお値段ですが、こちらのドキュメントによると1人あたり3ジョブまで無料ということです。
動作確認
すぐに動作確認をしたいので、上記画面のRun now
ボタンをクリックし、Pub/SubのTopicに対してメッセージを送ってみましょう。するとSlackに下記のようにメッセージが送信されます。
以上で、Cloud FunctionsとCloud Schedulerを利用してDatadogで監視しているホスト数を通知させることができました。今後は、集計期間をpub/subのメッセージで設定できるようにするなど機能を追加していく予定です。もし、使ってくださる方がいて、追加で欲しい機能などございましたら、お気軽にIssue登録おねがいします〜
Author And Source
この問題について(Cloud FunctionsとCloud Schedulerを利用してDatadogで監視しているホスト数を通知させてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/selmertsx/items/bc7cd3eae10522f7ca27著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .