Trying out golang BigQuery client library

GCPのbillingをbigqueryにエクスポートしてre:dashで可視化してみました。

次はmackerelにbillingの情報を送ってメトリクスとして記録してみたいので、まずはgolangからbigqueryに対し何かしらのクエリを叩くところまでやってみます。

以下のドキュメントを見ながら試してみます。

準備

ライブラリのインストール。

go get cloud.google.com/go/bigquery
go get google.golang.org/api/iterator
  • cloud.google.com/go/bigqueryはbigqueryのapiを叩くライブラリ
    • ちなみにこのライブラリはまだβ版なので注意
  • google.golang.org/api/iteratorはgoogle apiが返してきた配列なりなんなりの構造に対し繰り返し処理をするためのライブラリ?

今回はローカルでのみ動かすので、Google Cloudへの認証を済ませておきます。

gcloud beta auth application-default login

※ サーバ上で実行したい場合は明示的に作成したアカウントでアプリケーションのデフォルト認証情報を使用する必要がある(認証情報JSONの設置と、そのJSONへのpathをGOOGLE_APPLICATION_CREDENTIALS環境変数に設定する)。

コードを書く

書くと言ってもほとんどドキュメント通り。googleのドキュメントはわかりづらっ というものも多いですがこのドキュメントはわかりやすくて良いですね。

月ごとのbillingデータを集計するクエリを実行してみます。プロジェクトIDデータセット名gcp_billing_exportテーブル名だけ修正すれば動く(と思う)。

package main

import (
	"fmt"
	"golang.org/x/net/context"
	"log"

	"cloud.google.com/go/bigquery"
	"google.golang.org/api/iterator"
)

func main() {
	ctx := context.Background()

	projectID := "プロジェクトID"

	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	q := client.Query(`
	  SELECT SUM(cost) AS sum_cost, product,
	  LEFT (FORMAT_UTC_USEC(
	    UTC_USEC_TO_MONTH(TIMESTAMP_TO_USEC(start_time))), 7)
	    AS month
	  FROM
	    データセット名.gcp_billing_exportテーブル名
	  GROUP BY month, product
	`)

	it, err := q.Read(ctx)
	if err != nil {
		log.Fatalf("Failed to querying: %v", err)
	}

	for {
		var values []bigquery.Value
		err := it.Next(&values)
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Fatalf("Failed to iterator: %v", err)
		}
		fmt.Println(values)
	}
}

実行してみる

良さそう。

$ go run golang-bq.go
[0.002567 BigQuery 2017-01]

感想

思ったよりあっさりやりたいことが実現できた。ライブラリ便利だ...。

bigqueryへアクセスするための認証の手順でもっと時間がかかるかもと身構えていたが、ローカルで試す分にはgcloudコマンドがいい感じに認証の部分を吸収してくれた。

次やること

go-mackerel-plugin-helperを利用してmackerelへメトリクスを送れる形でデータ出力を行えるようにする。その際プロジェクトIDやデータセット、テーブル名は引数で渡せるようにする。

参考