この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、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利用率とメモリー使用率の値を書き込みます。
index.ts
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