Google BigQuery

GCP: 今月のGCP課金額をslackに自動的に書き込む

こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。

今回はGCPの課金額をslackに自動的に書き込むプログラムを作って見ます。

GCPは低コストでクラウド環境を構築できるのでとても良いのですが、うっかりテスト用の設定を作ったまま放置してしまって課金されてたり、なんてことありませんか?
毎日slackに今月の課金額をポストしてくれると、少しはダメージが少なくなるかも知れません。

やることは以下のとおりです。
1. GCPのBillingレポートをBigQueryにエクスポートする
2. BigQueryのBilligテーブルにクエリを投げて、レポートを抽出する
3. slackのwebhookを使って、レポートをslackのチャネルにポストする

1. GCPのBillingレポートをBigQueryにエクスポートする

まずはBigQueryにBillingエクスポート用のデータセットを作ります。
わかりやすく billing という名前にでもしておきます。

次にGCPのBillingメニューの中の、Billing Exportを開きます。
そして、先ほど作ったbillingデータセットを指定して、Enable Billing Exportボタンをクリックします。

BigQuery billing export has been successfully enabled というメッセージが表示されればOKです。
次は、このテーブルに対してクエリを投げて見ます。

2. BigQueryのBilligテーブルにクエリを投げて、レポートを抽出する

Billing Export設定をしてから小一時間ほどすると、billingデータセットの中に2つのテーブルが出て来ます。

gcp_billing_export_* というテーブルと、 gcp_billing_export_v1_* というテーブルです。

v1の方が今月発表された新しいスキーマのテーブルなので、新しいv1テーブルでクエリを書いて見ます。
今月の現時点の、プロジェクト名と製品名ごとに0.01ドル以上の課金額を表示します。

#standardSQL
select format_timestamp('%Y/%m', usage_start_time, 'Asia/Tokyo') as mon,
project.name as project,
service.description as service, 
round(sum(cost * 100)) / 100 as cost
from billing.gcp_billing_export_v1_008EC3_C14E1F_66E889
where format_timestamp('%Y/%m', usage_start_time, 'Asia/Tokyo') = format_timestamp('%Y/%m', current_timestamp, 'Asia/Tokyo')
and cost >= 0.01
group by mon, project, service
order by project

結果はこうなります。

次は、このデータをSlackのチャネルに定期的に投稿するプログラムを書いて見ます。

3. slackのwebhookを使って、レポートをslackのチャネルにポストする

SlackのIncoming Webhookという機能を使って、メッセージをSlackの特定のチャネルにポストします。

Slackのアカウントを持っている前提で、以下のURLからWebhook URLを取得します。

Incoming Webhook Integration

メッセージを書き込みたいチャネルを選んで、緑色のAdd Incoming Webhook integrationボタンをクリックすればOKです。

Webhook URLが表示されるので、これをメモしておきます。

そして、Webhook URLにBillingテーブルに対するクエリ結果をポストすればSlackにメッセージが表示されます。
Node.jsで書いて見ます。

var Slack = require('slack-node');
require('date-utils');

//webhook url
webhookUri = "https://hooks.slack.com/services/foo/bar/baz"; 
slack = new Slack();
slack.setWebhook(webhookUri);

var BigQuery = require('@google-cloud/bigquery');
var projectId = 'myprojectid'; // gcp project id
var bigquery = BigQuery({
    projectId: projectId
});
var datasetName = 'billing';
var dataset = bigquery.dataset(datasetName);
var table = dataset.table('gcp_billing_export_v1_hoge'); //billing table

//query
var query = 'SELECT format_timestamp(\'%Y/%m\', usage_start_time, \'Asia/Tokyo\') as mon, ' +
'project.name as project, service.description as service, round(sum(cost * 100)) / 100 as cost ' +
'FROM billing.gcp_billing_export_v1_hoge ' +
'where format_timestamp(\'%Y/%m\', usage_start_time, \'Asia/Tokyo\') = format_timestamp(\'%Y/%m\', current_timestamp, \'Asia/Tokyo\') ' +
'AND cost >= 0.01 ' +
'GROUP BY mon, project, service order by project';

var options = {
    query: query,
    useLegacySql: false
};

var bqresult = "";
var project_name = "";
var cnt = 0;
var subtotal = 0;
var total = 0;

//query結果をproject毎にまとめる
bigquery.query(options, function(err, rows) {
    if (!err) { 
        for (var i=0; i<rows.length; i++) {
            var row = rows[i];
            if (cnt == 0) {
                project_name = row["project"];
                cnt = 1;
            }
            //projectとprojectの間には罫線を入れる
            if (project_name != row["project"]) {
                bqresult += "----------\n";
                bqresult += "小計 $" + (Math.floor(subtotal * Math.pow(10, 2)) / Math.pow(10, 2)) + "\n\n";
                subtotal = 0;
            }
            bqresult += row["project"] + "\t" + row["service"] + "\t$" + row["cost"] + "\n";
            subtotal += row["cost"];
            total += row["cost"];
            project_name = row["project"];
        }
        bqresult += "----------\n";
        bqresult += "小計 $" + (Math.floor(subtotal * Math.pow(10, 2)) / Math.pow(10, 2)) + "\n\n";
        bqresult += "合計 $" + (Math.floor(total * Math.pow(10, 2)) / Math.pow(10, 2)) + "\n"; 
        
        var dt = new Date();
        var fd = dt.toFormat("YYYY-MM-DD");
        //slackに投稿        
        slack.webhook({
          channel: "#alert",
          username: "ctobot",
          icon_emoji: ":dollar:",
          text: "今月のGCPコスト (as of " + fd + ")\n" + bqresult
        }, function(err, response) {
          console.log(response);
        });
    }
});

実行すると、Slackのチャネルにメッセージが表示されます。

モザイクだらけでアレなのと、通貨設定がドルなのですが、そこはスルーしてください。

注意点として、GCPの課金エクスポートは、エクスポート設定をしたタイミングからの課金額しか反映されません。
月の途中でエクスポート設定をしても月初の金額は分からないので気をつけてください。

あとは、このプログラムをGCE上のLinuxインスタンスで毎日cronすれば良いですね。

以上、今回はGCP課金額をslackに自動投稿する方法についてでした。
弊社ではGCPを利用した分析基盤の構築支援などを行なっております。
お問い合わせはこちらからどうぞ。

ブログへの記事リクエストはこちらまで

ピックアップ記事

  1. 最速で理解したい人のためのIT用語集

関連記事

  1. Google BigQuery

    BigQuery BI Engine解説

    こんにちは、エクスチュア渡部です。2019/4/9-4/11に行わ…

  2. Google Cloud Platform

    GoogleNext 2019レポート:初日目

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

  3. Adobe Analytics

    Adobe Analyticsに入り切らないデータをBigQueryに投入する

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

  4. Adobe Analytics

    Adobe Analytics: BigQueryにロードしたデータフィードをDataStudioで…

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

  5. Adobe Analytics

    Adobe Analytics: DWHレポートの日付列をBigQueryのDate型として扱う

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

  6. Enterprise Data Warehouse

    爆速データウェアハウスなApache Druidを試す

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

最近の記事

  1. 忘年会シーズンに「DCRごっこ」のご提案
  2. タグ監査ツールとは? 〜〜出来ることと導入のメリット〜〜
  3. 実はSEO以上の効果がある!?Webサイトの「監査」とは?
  4. Vertex AIのベクトル検索によってブログの検索エンジン…
  5. Google Cloud iPaaS 「Applicatio…
  1. Google Tag Manager

    GTMの検証でプレビューのSummaryを上手く使う
  2. IT用語集

    データセット(Dataset)、データソース(Data Source)って何?
  3. IT用語集

    Java(ジャバ)って何?
  4. Tableau

    Tableauのリレーションシップを理解して過剰結合を防ぐ
  5. IT用語集

    クラス(Class)って何?
PAGE TOP