Cloud Monitoring で custom metrics を活用する
Cloud Monitoring で Custom Metrics?
GCP を使っていると、使っているリソースによって、たとえば GCE instance であれば CPU 使用率などの metrics が追加の設定無しで利用可能になっており、すぐに dashboard をつくって値を見ることができ、非常に便利です。
これら標準で用意されている metrics と同様に、ユーザー定義の metrics もある程度の手間で利用でき、用途によっては非常に便利に活用できます。 今回はそんな例をひとつつくり、可能性を探ってみたいと思います。
metrics 送信を実装する
今回は こちら の例をほとんどそのまま使います。わたしが慣れてて楽だからという理由で nodejs runtime を使います。
Monitoring 用の module を install して…
npm install --save @google-cloud/monitoring
以下ほとんど上記サンプルそのままですが一部だけ、label などをそれっぽく変えています。 後で使う https module も宣言しておきます。
const https = require('https');
const monitoring = require('@google-cloud/monitoring');
const client = new monitoring.MetricServiceClient();
async function writeTimeSeriesData(v) {
const dataPoint = {
interval: {
endTime: {
seconds: Date.now() / 1000,
},
},
value: {
doubleValue: v,
},
};
const timeSeriesData = {
metric: {
type: 'custom.googleapis.com/binance.api.v3/avgPrice',
labels: {
symbol: 'ETHUSDT',
},
},
resource: {
type: 'global',
labels: {
project_id: projectId,
},
},
points: [dataPoint],
};
const request = {
name: client.projectPath(projectId),
timeSeries: [timeSeriesData],
};
// Writes time series data
const result = await client.createTimeSeries(request);
console.log('Done writing time series data.', result);
}
今回利用する public REST API
今回例として使用するのに、せっかくなので、インターネットで得られる情報の中で、比較的短期間で値が上下する実用的なものがいいな… とすこし探しました。気温とかもいいかなと思ったのですがお手軽に使えそうな情報源がぱっと見つかりませんでした。
Binance が公開している public API に、Ether の価格を取得できるものがあります。 https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#current-average-price
すなわち、以下のような URL で
https://api.binance.com/api/v3/avgPrice?symbol=ETHUSDT
以下のような返答がもらえます。
{"mins":5,"price":"2946.90879817"}
これは便利。 時系列でリアルタイム変動する値として、今回のサンプルにちょうどよさそうです。
ということで、Cloud Function の entry point を以下のように実装しておきます。こちらも https module を使うときのテンプレのような内容で、特に触れる点も無いです。JavaScript だと JSON の扱いが楽でよいですよね。 結果を受け取ったら、custom metrics を送信するために上記で実装した function を呼んでいます。
exports.main = (message, context) => {
https.get('https://api.binance.com/api/v3/avgPrice?symbol=ETHUSDT',
(r) => {
let data = '';
r.on('data', (chunk) => {
data += chunk;
});
r.on('end', () => {
writeTimeSeriesData(parseFloat(JSON.parse(data).price));
});
}).on('error', (err) => {
console.log(`Error: ${err.message}`);
});
};
定期実行する
上記の API ではどうも、5 分間の平均値を出しているようなので、5 分以内で連続呼び出ししても意味は無さそうです。
5 分おきに呼び出す方法を調べると、GCP の Cloud Functions だと Cloud Scheduler -> Cloud Pub/Sub -> Cloud Functions とやる必要がある… ほんとう…? めんどくさ(略
Cloud Functions For Firebase であればかんたんに 5 分おき実行ができるようです。 こういった利便性は Firebase でうまく実装されている印象があります。GCP では拡張性が重視されている感はありますが、GCP でも便利になるとよいですね。残念ですが、今回は諸々の事情により GCP の枠を出ないことに決めていたので、GCP でがんばります。
Pub/Sub topic を作成して…
gcloud pubsub topics create demo-metrics
そこに message を送る Scheduler Job を作成、5 分おきに実行するようにします。
gcloud scheduler jobs create pubsub demo-metrics-5m \
--schedule="*/5 * * * *" --max-retry-attempts=0 \
--topic=demo-metrics --message-body="Hello"
Cloud Function を deploy する
ようやく、本体である Cloud Function を deploy します。
gcloud functions deploy demo-metrics \
--entry-point=main --region=us-central1 \
--runtime=nodejs16 --memory=128MB \
--service-account=demo-metrics@xxxx.iam.gserviceaccount.com \
--trigger-topic=demo-metrics
リージョンはなんとなく、リソースが豊富そうな場所を選択しています。 ここで使う service account には最小限 “Monitoring Metric Writer” role があればよいでしょう。
結果を見る
GCP web console に行き、Metrics Explorer で結果を見てみましょう。
いい感じです。 (最初の頃にちょっと途切れているのは単なるわたしのミスです)
普段見ている GCP console で Ether の価格が確認できるようになりました。これで仕事をしながら、トレーディングができ… じゃなくて、インターネットからの情報を metrics として取り込み、GCP 上で利用する準備ができました。
後片付け
満足したら、作成したリソースを削除しておきましょう。
gcloud functions delete demo-metrics \
--region=us-central1
gcloud scheduler jobs delete demo-metrics-5m
gcloud pubsub topics delete demo-metrics
GCS に gcf-
ではじまる名前の bucket ができてそこに build 用の object が保存されていたりもしますので、適宜掃除をしましょう。頻繁に deploy をする場合は lifecycle の設定をするのもよさそうです。
まとめ
custom metrics を定義し、利用する感覚を得ることができました。
以前に聞いた事例で、Twitter でのある単語のバズりようによってサービスを自動スケーリングするといったものがあったので、アイディア次第でいろいろと応用の幅が広がりそうです。