Lambda(Python3.6)でDynamoDBに登録された項目が日付型であるかチェックしてみる
どうも!大阪オフィスの西村祐二です。
DynamoDBで提供されている属性の型は大きく分けて
スカラー型、ドキュメント型、セット型となっています。
そのため、下記画像のように日付と時刻を登録するときは文字列データ型(String型)を使用するのがほとんどだと思います。
ただ、こちらが想定するフォーマット以外でも登録することができてしまい、
登録された時刻をみて、ある処理を実行するときなど
処理が失敗してしまう可能性があります。
今回はLambdaを使って登録されている項目のフォーマットが正しいかチェックしてみたいと思います。
DynamoDBのテーブル作成
今回はCloudFormationを使ってDynamoDBのテーブルを作成します。
テンプレートファイルを作成します。
今回作成するテーブルはプライマリーキー「Date」、ソートキー「Time」とし、
属性のデータ型を文字列データの「S」として設定しています。
1 | $ vi dynamodb.yml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | --- AWSTemplateFormatVersion: "2010-09-09" Resources: myDynamoDBTable: Type: "AWS::DynamoDB::Table" Properties: TableName: "dynamo-test" AttributeDefinitions: - AttributeName : Date AttributeType: S - AttributeName : Time AttributeType: S KeySchema: - AttributeName : Date KeyType: HASH - AttributeName : Time KeyType: RANGE ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 |
下記コマンドにてテーブルを作成します。
1 2 | $ aws cloudformation validate-template --template-body file://dynamodb.yml $ aws cloudformation create-stack dynamodb-test --template-body file://dynamodb.yml |
成功したら下記画像のように作成されているはずです。
Lambda関数の作成
AWS Management Consoleにログインして、AWS Lambda Dashboardを開きます。
Lambda関数一覧の画面で、[関数の作成]ボタンをクリックします。
[一から作成]ボタンをクリックします。
名前を[dynamodb-check]とし、
ロールにはDynamoDBのテーブルをスキャンするので
"dynamodb:Scan"
を付与しておいてください。
[関数の作成]ボタンをクリックします。
移動した画面で、ランタイムのドロップダウンリストからPython 3.6を選択します。
下記、プログラムをコピペし、保存ボタンをクリックします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import boto3 import logging from datetime import datetime # dynamodb DYNAMO_TABLE_NAME = 'dynamodb-test' dynamodb = boto3.resource( 'dynamodb' ) table = dynamodb.Table(DYNAMO_TABLE_NAME) def format_check(data): try : for i in range ( len (data)): dynamo_datetime = str (data[i][ 'Date' ]) + " " + str (data[i][ 'Time' ]) ## 日時フォーマットに変換 (ex:2017-10-19 01:01) get_datetime = datetime.strptime(dynamo_datetime, '%Y-%m-%d %H:%M' ) print (get_datetime) print ( 'ok' ) except Exception as e: logger.exception( "{}" . format (e)) return "ERROR End" def handler(event, context): try : response = table.scan() data = response[ 'Items' ] format_check(data) except Exception as e: logger.exception( "{}" . format (e)) return "ERROR End" |
簡単に解説します。
ポイントは15行目です。
1 | get_datetime = datetime.strptime(dynamo_datetime, '%Y-%m-%d %H:%M') |
pythonのdatetime.strptime
はかなり便利で、
日付や時刻に対応する書式文字列から datetime オブジェクトに変換してくれます。
また、strptimeの第二引数は第一引数のフォーマットを渡すため、
これにマッチしないとエラーとなります。
ここでエラーになるということは、つまり、想定しないフォーマットで入力されていることになります。
今回の場合は
Date:2017-10-19
のような日付
Time:01:01
のような時刻が
入力されている想定です。
また、入力してほしいフォーマットが
Date:2017/10/19
のような日付の場合は
第二引数を%Y/%m/%d
のように対応する形に変更すれば、OKです。
1 | get_datetime = datetime.strptime(dynamo_datetime, '%Y/%m/%d %H:%M') |
動作確認
DynamoDBにいろいろなデータをいれて、
動作を確認してみたいと思います。
正しいフォーマットでいれてみる
[項目の作成]をクリックして、
Date:2017-10-20
Time:20:20
を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され問題なく、変換できていることがわかります。
時刻を一桁のままでいれてみる
[項目の作成]をクリックして、
Date:2017-10-20
Time:1:1
を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され問題なく、変換できていることがわかります。
全角を入れてみる
[項目の作成]をクリックして、
Date:2017−10−20
Time:20:20
を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され想定どおり、エラー出力ができていることがわかります。
ありえない日程をいれてみる
[項目の作成]をクリックして、
Date:2017-15-10
Time:20:20
を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され想定どおり、エラー出力ができていることがわかります。
ありえない時刻をいれてみる
[項目の作成]をクリックして、
Date:2017-10-20
Time:25:20
を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され想定どおり、エラー出力ができていることがわかります。
追加で、
Date:2017-10-20
Time:20:80
を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され
今回はなぜかunconverted data
というようなエラーが出力されました。
さいごに
いかがだったでしょうか。
Lambdaをつかって
DynamoDBに登録された項目が日付型であるかチェックしてみました。
あとは、Lambdaで定期的に確認しエラーが出力されれば
ユーザにメールを送信すればとりあえずは良いかと思います。
もっといいやり方があれば教えてください。
誰かのためになれば幸いです。