Lambda から Amazon Timestream を呼び出す

## はじめに
Amazon Timestream が 10 月に一般提供されました。Timestream の名の通り、時系列のデータを扱うデーターベースです。データを管理するときにありがちな、直近データはすぐに参照できるようにしておきたいといったことや、時間のたったデータは安いストレージに保存しておいて必要なときに取り出そう、といった仕組みがあらかじめ備わっていて魅力的です。
今回は Lambda から受け取ったデータを、この Amazon Timestream に保存してみたいと思います。 
執筆時点で Timestream を利用できるリージョンは、バージニア北部、オハイオ、オレゴン、アイルランドです。ここであげたいずれかのリージョンで以下の操作を行ってください。

## Timestream データベースの準備

* まず、データベースを作成します。
    * Timestream コンソールで Create database を選択します。
    * Database configuration 欄の configuration は ```Standard database``` を選択し、 Name を ```MyDatabase``` とします。
    * Encryption 欄、Tags Optional 欄はデフォルト ( Master Key はデフォルトの ```aws/timestream``` ）で、"Create database" を選択します。
* 次に、テーブルを作成します。
    * Databases ページで ```MyDatabase``` 作成した Database を選択し、"Create Table" を選択します。
    * Table Details 欄の Table Name には ```MyTable``` 、Data retention 欄の Memory store retention は ```1 Hour(s)``` を、Magnetic store retention には ```3 Year(s)``` を入力して "Create table" を選択します。

## 実行ロールの準備

* IAM コンソールで、ロールページを開き、"ロールの作成" を選択します。
* 次のプロパティでロールを作成します。
    * __信頼されたエンティティ__ - AWS サービス
    * __ユースケース__ - Lambda 
    * __Attach アクセス権限ポリシー__ - AmazonTimestreamFullAccess 
    * __ロール名__ - lambda-timestream-role
    * __ロールの説明__ - Allows Lambda functions to call AWS Timestream services.

## Lambda の準備

* Lambda コンソールで "関数の作成" を選択します。
* 次のプロパティで Lambda を作成します。
    * __関数の作成__ - 一から作成
    * __関数名__ - lambda_timestream
    * __ランタイム__ - Node.js 12.x
    * __デフォルトの実行ロールの変更__ - 実行ロール ```既存のロールを使用する``` で先ほど作成したロール、```lambda-timestream-role``` を選びます。

### 補足

"AWS SDK for JavaScript" は [2.763.0](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md#27630) で Timestream をサポートしました。 Lambda コンソールでサポートしている "AWS SDK for JavaScript" のバージョンは [こちら](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-nodejs.html) に記載があります。このバージョンが 2.763.0 よりも古い場合には、 ["Lambda コンソールで使う AWS SDK を最新にする"](https://qiita.com/azureus/items/385ab10b6d12de65ba1f) を参考に "AWS SDK for Javascript" の最新バージョンをレイヤーに追加してください。

* 関数コードペインの index.js を次のように変更し、"Deploy" を選択します。

```javascript

const AWS = require('aws-sdk');

exports.handler = async (event) => {
	const timestreamwrite = new AWS.TimestreamWrite();
	const addTime = parseInt(event.addMinutes, 10) * 60 * 1000; // 分をミリ秒にする。
	const currentTime = Date.now() + addTime; // 現在時刻に受け取った分を加算する。

	const dimensions = [
	    {'Name': 'country', 'Value': event.country},
	    {'Name': 'prefecture', 'Value': event.prefecture}
	];

	const cpuUtilization = {
	    'Dimensions': dimensions,
	    'MeasureName': 'cpu_utilization',
	    'MeasureValue': event.measureValue,
	    'MeasureValueType': 'DOUBLE',
	    'Time': currentTime.toString()
	};

	const params = {
	   DatabaseName: 'MyDatabase',
	   TableName: 'MyTable',
	   Records: [cpuUtilization]
	};
    const response = timestreamwrite.writeRecords(params).promise();
    return response;
};

```

## Lambda 関数を実行する

イベントを用意して、作成した Lambda 関数を呼び出します。

* Lambda コンソールの右上にある "テスト" をクリックします。
* "イベント名" に ```LambdaTimestreamEvent``` と名付け、JSON を以下のように入力し、"作成" をクリックします。

```
{
  "country": "japan",
  "prefecture": "tokyo",
  "measureValue": "12.3",
  "addMinutes": "0"
}
```

* もう一度 "テスト" をクリックすると先ほど作成した Lambda 関数が実行され、データが登録されます。数回実行して次で確認します。

## 登録したデータを確認する

* Timestream コンソールから "Tables" ページを開き、"MyTable" リンクを選択してください。
* "Query table" を選択します。
* "MyTable" から "Preview data" を選択すると、クエリが表示されます。

![console.aws.amazon.com_timestream_home_region=us-east-1 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743360/4e4a32bf-0525-3490-7ca1-e89192046868.png)

* クエリの表示後、"実行" を選択すると "Query results" タブで登録した内容を確認できます。

![console.aws.amazon.com_timestream_home_region=us-east-1 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743360/f919af8c-34ce-55ed-d1c3-92750a2e2e08.png)


## よりみち

テーブル作成時に "Memory store retention" に指定した ```1 Hour(s)``` より古いデータを登録してみます。

* "LambdaTimestreamEvent" のプルダウンから "テストイベントの設定" を選択します。
* JSON のフィールド名 "addMinutes" の値を ```-80``` に変更して "保存" を選択します。
* "テスト" を実施すると、エラーが発生します。何が起きたのでしょうか？

![console.aws.amazon.com_lambda_home_region=us-east-1 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743360/297780a2-f907-9cd2-f058-edaee6840036.png)

* Timestream にはデータを登録する際に、"Memory store retention" を超えて古い時間のデータは保存できない決まりがあります。エラーはこの決まりにより発生したのです。これと同様に未来時間についても保存できません。この辺は何らかの運用を最初に決めておかないといけませんね。

以上になります。