Amazon TimestreamのデータをGrafanaで可視化してみた
こんにちは、CX事業本部のうらわです。
今回はAmazon Timestream(以下、Timestream)のデータをGrafanaで可視化してみました。
検証環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.6 BuildVersion: 19G2021 $ docker --version Docker version 20.10.0, build 7287ab3 $ aws --version aws-cli/2.1.4 Python/3.7.4 Darwin/19.6.0 exe/x86_64 $ node -v v12.18.3 $ npm -v 6.14.6
GrafanaをDockerで起動する
Grafanaが用意しているDockerfileを用いて、あらかじめTimestream用のプラグインをインストールしたイメージをビルドします。こちらの手順は下記に記載があります。
$ docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_PLUGINS=grafana-timestream-datasource" -t grafana-custom -f Dockerfile .
ビルドできたらコンテナを起動します。
$ docker run -it -d -p 3000:3000 --name=grafana grafana-custom
ブラウザでlocalhost:3000にアクセスするとGrafanaのログイン画面が表示されます。初期設定ではユーザー名/パスワードともにadmin/adminです。
Timestreamを設定する
GrafanaでTimestreamからデータを取得するための設定をします。
Configuration > Data Sources > Add data source で Amazon Timestream を選択します。
Timestremaの接続設定です。今回は以下の通り設定しました。
項目 | 値 |
---|---|
Authentication Provider | Access & secret key |
Access Key ID | 新規作成したIAMユーザーのアクセスキーID |
Secret Access Key | 新規作成したIAMユーザーのシークレットアクセスキー |
Assume Role ARN | 未設定 |
External ID | 未設定 |
Default Region | us-east-1 |
Endpoint | CLIで確認したqueryエンドポイント |
Access Key ID & Secret Access Key
今回はローカルかつ検証目的のため、IAMロールは使用せず専用のIAMユーザーを作成しアクセスキーIDとシークレットキーを使用してTimestreamにアクセスします。
このIAMユーザーには以下のようなTimestreamのデータを取得できるIAMポリシーをアタッチします。本来はActionやResourceを最低限に絞るべきですが、検証目的なのでワイルドカードで指定しています。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "timestream:*", "Resource": "*" } ] }
Default Region
今回はus-east-1リージョンにTimestreamのデータベース等を作成するため、us-east-1を指定します。
Endpoint
以下のCLIでquery用のエンドポイントを確認しGrafanaに設定します。
$ aws timestream-query describe-endpoints --region us-east-1 { "Endpoints": [ { "Address": "query-{cell}.timestream.us-east-1.amazonaws.com", "CachePeriodInMinutes": 1440 } ] }
ここまで設定したら、Save & Testで接続テストを実施し、「Connection Success」と表示されるか確認します。
以上でTimestreamへの接続設定は完了です。
Timestreamにデータを書き込む
GitHubに公開されているサンプルコードを参考にデータベース・テーブル作成、データ書き込みのためのスクリプトを作成します。
https://github.com/awslabs/amazon-timestream-tools/tree/master/sample_apps/js
今回はTypeScriptを使用します。TypeScriptでコードを書くための細かな設定は割愛します。
以下のスクリプトは、無限ループで1秒おきにランダムなCPU利用率とメモリー使用率の値を書き込みます。
import AWS from 'aws-sdk'; AWS.config.update({ region: 'us-east-1' }); const DATABASE_NAME = 'mySampleDB'; const TABLE_NAME = 'mySampleTable'; const HT_TTL_HOURS = 24; const CT_TTL_DAYS = 7; const writeClient = new AWS.TimestreamWrite(); const createDatabase = async () => { console.log('Creating Database'); const params = { DatabaseName: DATABASE_NAME, }; try { await writeClient.createDatabase(params).promise(); console.log('Database created successfully'); } catch (e) { console.log('Error creating database', e.toString()); } }; const createTable = async () => { console.log('Creating Table'); const params = { DatabaseName: DATABASE_NAME, TableName: TABLE_NAME, RetentionProperties: { MemoryStoreRetentionPeriodInHours: HT_TTL_HOURS, MagneticStoreRetentionPeriodInDays: CT_TTL_DAYS, }, }; try { await writeClient.createTable(params).promise(); console.log('Table created successfully'); } catch (e) { console.log('Error creating table', e.toString()); } }; const writeRecords = async () => { console.log('Writing records'); const currentTime = Date.now().toString(); const dimensions = [ { Name: 'region', Value: 'us-east-1' }, { Name: 'az', Value: 'az1' }, { Name: 'hostname', Value: 'host1' }, ]; const cpuValue = Math.round((Math.random() * (200 - 20) + 20) * 1000000) / 1000000; const cpuUtilization = { Dimensions: dimensions, MeasureName: 'cpu_utilization', MeasureValue: cpuValue.toString(), MeasureValueType: 'DOUBLE', Time: currentTime.toString(), }; const memValue = Math.round((Math.random() * (100 - 10) + 10) * 1000000) / 1000000; const memoryUtilization = { Dimensions: dimensions, MeasureName: 'memory_utilization', MeasureValue: memValue.toString(), MeasureValueType: 'DOUBLE', Time: currentTime.toString(), }; const records = [cpuUtilization, memoryUtilization]; const params = { DatabaseName: DATABASE_NAME, TableName: TABLE_NAME, Records: records, }; try { await writeClient.writeRecords(params).promise(); console.log(records); } catch (e) { console.log('Error writing records:', e); } }; const sleep = () => new Promise((resolve) => setTimeout(resolve, 1000)); (async () => { await createDatabase(); await createTable(); const loop = true; while (loop) { await writeRecords(); await sleep(); } })();
こちらをts-node
で実行し放置します。
$ npx ts-node index.ts
Grafanaでダッシュボード作成
Create > Dashboard で新規ダッシュボードを作成し、 Add new panel でTimestreamのデータを表示するパネルを作成します。
データソースはdefaultがTimestreamに設定されているため、defaultのままでOKです。下部にTimestreamからデータを取得するためのクエリーエディターが表示されます。
今回は現在から2時間前までのデータを取得してtimeでソートします。
以下はcpu_utilizationを取得するクエリーです。memory_utilizationについてはこのクエリーのSELECT句のASとWHERE区のmeasure_nameを変更するだけでOKです。
SELECT measure_name, measure_value::double AS cpu, time FROM "mySampleDB".mySampleTable WHERE measure_name = 'cpu_utilization' AND time > ago(2h) ORDER BY time
クエリーにエラーがなければ以下のようにグラフが表示されます。右上で自動更新のオンオフと間隔を設定できます。
最後に、Save で保存します。ダッシュボードでは以下のように表示されます。
まとめ
GrafanaのTimestream用プラグインを使用すると簡単にデータの可視化を始めることができます。今回は単純なクエリーで簡単なグラフを作成しましたが、組み込み関数を使用するともっと複雑なデータの可視化ができそうです。
AWS Black Belt Online Seminarの資料をみつつ、色々試してみたいと思います。
参考
https://docs.aws.amazon.com/timestream/latest/developerguide/Grafana.html