4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

StackDriver Monitoring APIを使ってGCPのメトリックの値を取得する

Posted at

概要

GCPの監視を行うため、StackDriver から値を取得し
しきい値を超えていないかチェックする Nagios 用のプラグインをGolnag で作成しました。
https://github.com/yuukichi-nankou/check-stackdriver-go

その際、苦戦したので GolangStackDriver Monitoring APIから値を取得する方法をまとめます。

つい先日、StackDriverが管理コンソールに統合されました。
https://cloud.google.com/blog/products/management-tools/cloud-monitoring-dashboards-using-an-api
それに伴い、管理画面では単に Monitoring という名称になっていますが、
本記事では StackDriver Monitoring と記載しています。

StackDriverからSDKを使って値を取得する

StackDriver は、GCPコンソール上で収集したメトリックやログの閲覧
しきい値を指定したアラート通知が可能な監視サービスです。
※ AWSのCloudWatchのようなイメージです。

今回はStackDriver Monitoringのデータを取得しました。
StackDriver Monitoringには GCP上のインスタンス数や、CPU使用率などの
リソース状態が自動で収集されています。

メトリックの一覧

取得できるメトリックの一覧が公式ドキュメントに公開されています。
https://cloud.google.com/monitoring/api/metrics_gcp?hl=ja

今回はCloud Storageバケット内の、ファイル数を取得します。

StackDriver SDK

他のGCPのサービスと同様に、StackDriverもAPIとそれをプログラムから呼び出すSDKが公開されています。
Golang用のSDKも公開されているので、これを利用します。

データの取得処理

メトリックを指定し、一覧を取得する

以下は、SDKを利用し、Cloud Storageのメトリックを取得したサンプルです。
フィルタの指定で、メトリックを指定します。
metric.type = storage.googleapis.com/storage/object_count

メトリックデータを取得するサンプル
sample.go

package main

import (
	"fmt"
	"os"
	monitoring "cloud.google.com/go/monitoring/apiv3"
	googlepb "github.com/golang/protobuf/ptypes/timestamp"
	"golang.org/x/net/context"
	"google.golang.org/api/iterator"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)

func main() {
	// StackDriverAPIに接続する際の認証鍵ファイルを指定する
	key_path := "./path/to/auth-key.json"
	os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", key_path)

	// GCPのプロジェクト名を指定する
	priject_id := "your-project-id"
	// フィルタを指定し、取得するデータを絞る
	filter_query := "metric.type = storage.googleapis.com/storage/object_count AND resource.type = gcs_bucket "
	
	// 取得期間をunixtimeで指定する
	var end_time int64 = 1583766000
	var start_time int64 = 1583809200

	// リクエストデータを作成する
	req := &monitoringpb.ListTimeSeriesRequest{
		Name:   "projects/" + priject_id,
		Filter: filter_query,
		Interval: &monitoringpb.TimeInterval{
			EndTime: &googlepb.Timestamp{
				Seconds: end_time,
			},
			StartTime: &googlepb.Timestamp{
				Seconds: start_time,
			},
		},
	}

	ctx := context.Background()
	client, _ := monitoring.NewMetricClient(ctx)
	it := client.ListTimeSeries(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			break
		}

		fmt.Println(resp)
	}
}

また以下が、実際にサンプルコードを実行した結果です。

サンプルの実行結果
$ go run sample/sample.go 
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"MULTI_REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"asia.artifacts.hogehoge-bucket.appspot.com" > labels:<key:"location" value:"asia" > labels:<key:"project_id" value:"hogehoge-bucket" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:76 > >
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"hogehoge-bucket" > labels:<key:"location" value:"asia-northeast2" > labels:<key:"project_id" value:"hogehoge-bucket" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:43 > >
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"hogehoge-bucket-frontend" > labels:<key:"location" value:"asia-northeast2" > labels:<key:"project_id" value:"hogehoge-bucket" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:575 > >
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"hogehoge-bucket-frontend-staging" > labels:<key:"location" value:"asia-northeast2" > labels:<key:"project_id" value:"hogehoge-bucket" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:568 > >

フィルタを使い取得するメトリックを制限する

ListTimeSeries の結果はイテレータ形式で取得でき、サンプルのように複数件返ることがあります。
返る件数はメトリックによって変わります。
サンプルコードでは各バケット単位で取得していますが、
GCEのCPU使用率を取得するとインスタンス単位で値が返ります。

取得する件数を絞りたい場合は、フィルタを追加します。
例えば、サンプルコードで特定のバケットのみの値を取得したい場合
フィルタを以下のように追加すると

sample.go
	filter_query := "metric.type = \"storage.googleapis.com/storage/object_count\" AND resource.type = \"gcs_bucket\" "
	// フィルタを追加する
	filter_query += "AND resource.labels.bucket_name = \"xtrans-friends-frontend-staging\" "

取得する値を絞ることが可能です。

$ go run sample/sample.go 
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"xtrans-friends-frontend-staging" > labels:<key:"location" value:"asia-northeast2" > labels:<key:"project_id" value:"xtrans-friends" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:568 > > points:<interval:<end_time:<seconds:1583841300 > start_time:<seconds:1583841300 > > value:<int64_value:568 > >

取得したメトリックから値を取り出す

メトリックの値はサンプルコードの resp.Points に配列として格納されています。
この値も取得期間に応じ複数取得することがあります。

また、値の取り出しは、メトリックのデータ型に応じて呼び出す関数が異なります。
メトリックのデータ型は resp.ValueType.String() で確認が可能です。

サンプルコードを一部修正すると、値を確認できます。

sample.go
		fmt.Println(resp)
		// 追加
		fmt.Println(resp.ValueType.String())
		fmt.Println(resp.Points)

storage/object_count メトリックは INT64 型で値が格納されていることが分かります。

$ go run sample/sample.go 
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"xtrans-friends-frontend-staging" > labels:<key:"location" value:"asia-northeast2" > labels:<key:"project_id" value:"xtrans-friends" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:568 > > points:<interval:<end_time:<seconds:1583841300 > start_time:<seconds:1583841300 > > value:<int64_value:568 > >
INT64
[interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:568 >  interval:<end_time:<seconds:1583841300 > start_time:<seconds:1583841300 > > value:<int64_value:568 > ]

INT64型の値を取り出す際は GetInt64Value() 関数を利用しますが、DOUBLE型の値を取り出す際は GetDoubleValue() 関数を利用します。
詳しくはSDKのドキュメントを参照してください。

サンプルコードを変更し値を取得します。

sample.go
		fmt.Println(resp)
		// 追加
		fmt.Println(resp.ValueType.String())
		fmt.Println(resp.Points)
		// 先頭の値を取得する
		fmt.Println(resp.Points[0].GetValue().GetInt64Value())

メトリックの値を取得できました。

$ go run sample/sample.go 
metric:<type:"storage.googleapis.com/storage/object_count" labels:<key:"storage_class" value:"REGIONAL" > > resource:<type:"gcs_bucket" labels:<key:"bucket_name" value:"xtrans-friends-frontend-staging" > labels:<key:"location" value:"asia-northeast2" > labels:<key:"project_id" value:"xtrans-friends" > > metric_kind:GAUGE value_type:INT64 points:<interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:568 > > points:<interval:<end_time:<seconds:1583841300 > start_time:<seconds:1583841300 > > value:<int64_value:568 > >
INT64
[interval:<end_time:<seconds:1583841600 > start_time:<seconds:1583841600 > > value:<int64_value:568 >  interval:<end_time:<seconds:1583841300 > start_time:<seconds:1583841300 > > value:<int64_value:568 > ]
568

まとめ

Golangで StackDriver Monitoring APIから値を取得することができました。
フィルタの指定方法や、値の取得など、ドキュメントに詳しく載っておらず苦労したので
StackDriver の値を Golangで取得したい 奇特な 方の助けになれば幸いです。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?