Michaelです。
「雑コラBOT」の作成の過程からAzure Functionsの設定方法を紹介する「雑コラBotを作ろう」の4回目です。
今回は、Azure Functions のTable Storageバインドを設定して、画像処理用Functionの実行履歴をTable Storageに書き込む仕組みを作成します。ついでに、処理結果をSlackに投稿するための関数を起動するキューメッセージをQueue Storageに出力する構成も追加します。
追加する構成
Azure Functionsで画像処理した結果のステータスをTable Storageに出力します。
ついでに、処理結果をSlackに投稿するための関数を起動するキューをQueue Storageに出力する構成も追加します。
バインドの設定
実行結果のステータスを出力するためのバインドを設定します。
関数の「統合」メニューで「+新しい出力」をクリックし、「Azure Table Storage」のバインドを選択します。
「Azure Table Storage output」の設定でステータスを出力するStorage Accountとテーブルを設定し、保存をクリックします。
続けて、メッセージ投稿用の関数を起動するためのQueue Storageバインドも設定します。
スクリプト
スクリプトは以下のように作成しました。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# coding: utf-8 # 1. ライブラリの読み込み import os, json import imghdr import urllib.parse import urllib.request import hashlib # 2. バインド設定の読み込み with open(os.path.dirname(__file__) + "/function.json", "r") as f: bindings = json.load(f) bindings = {bind["name"]: bind for bind in bindings["bindings"]} print("Function Start. ID:" + os.environ["INVOCATIONID"]) def handler(): # メッセージ読み込み with open(os.environ["inputMessage"], "r") as f: input_msg = json.load(f) # コンテンツのダウンロード print("Downloading input image") dl_url = input_msg["img_url"] req = urllib.request.Request(dl_url) with urllib.request.urlopen(req) as res: img_bytes = res.read() # 3. 出力メッセージ用データ作成 output_path = bindings["outputBlob"]["path"].format(blob_path=input_msg["blob_path"]).split("/") container = output_path[0] blob_path = "/".join(output_path[1:]) img_name = output_path[-1] img_md5 = hashlib.md5(img_bytes).hexdigest() # 画像フォーマット判定 print("Checking input image format") img_format = imghdr.what(None, h=img_bytes) if img_format in ["jpeg", "png", "bmp", "gif"]: if img_format == "jpeg": img_format = "jpg" # 画像の出力 with open(os.environ["outputBlob"], "wb") as fw: fw.write(img_bytes) # 4. 出力メッセージの設定 result = { "status": "ok", "message": "Image is uplaoded.", "container": container, "blob_path": blob_path, "filename": img_name, "content_md5": img_md5, "input": input_msg } else: # 4. 出力メッセージの設定 result = { "status": "error", "filename": img_name, "content_md5": img_md5, "input": input_msg, } if img_format is None: result["message"] = "Input file is not image." else: result["message"] = "Unsupported image format." # 5. キューメッセージの出力 print("Output Queue Message") with open(os.environ["outputQueueItem"], "w") as fw: json.dump(result, fw) # 6. 実行履歴の書き込み print("Insert Log to Table") insert_entity = {key: val for key, val in result.items()} insert_entity.update({ "PartitionKey": "results", "RowKey": os.environ["INVOCATIONID"] }) with open(os.environ["outputTable"], "w") as fw: json.dump(insert_entity, fw) return if __name__ == "__main__": handler() |
スクリプトの説明
- ライブラリの読み込み
必要なライブラリを読み込みます。
実行履歴としてダウンロードしたコンテンツのMD5値を書き出すため、「hashlib」を追加しています。 - バインド設定の読み込み
関数に設定しているバインドの設定値を読み込みます。 - 出力メッセージ用データ作成
Queue Storage、Table Storageに出力するデータを作成します。
キューメッセージ、実行履歴に書き込むBlob Storageの出力パスとコンテンツのMD5値をここで生成します。 - 出力メッセージの設定
Queue Storageに出力するメッセージを設定します。
後にSlack投稿用関数で使用するための必要な値を含めます。 - キューメッセージの出力
メッセージをQueue Storageに出力します。
Blob Storageと同様に、環境変数で指定されるパスにファイルとして保存することで書き出すことができます。 - 実行履歴の書き込み
Table Storageに実行履歴を書き込みます。
Table Storageでは「PartitonKey」、「RowKey」を設定する必要があるため、Queue Storageに出力したメッセージに「PartitonKey」、「RowKey」を追加してTable Storageに書き込みます。
実行結果
Slackの設定したチャンネルにメッセージを投稿すると、Azure Functionsにログが表示され、4秒ほどで関数が終了していることがわかります。
Table Storageを見ると、設定した名称のテーブルが作成されており、関数の終了と同時刻にテーブルにデータが書き込まれていることが確認できました。
同様に、Queue Storageでも関数の終了と同時刻にメッセージが書き込まれていました。
注意点
Table Storageの出力バインドは、データの更新に対応しておらず、PartitionKey、RowKeyの組がすでにテーブルに存在する場合には、「EntityAlreadyExists」の関数エラーが発生します。
ここで注意すべき点は、出力バインドによるデータの追加は関数の実行完了時に行われるため、出力バインドに関わるエラーを関数の例外処理で対処できないことです。出力バインドにTable Storageを使用する場合は、PartitionKey、RowKeyの組がユニークとなるように設定する必要があります。
まとめ
今回は、Azure FunctionsのTable Storageバインドを設定しました。サーバーレスとNo SQL DBは、ログ保存等によく用いられる組み合わせで、Table Storageであれば予約スループットの課金がなく安価に構成できます。
次回は、Blob Storageに保存した画像のSAS URLを発行してSlackに投稿する関数を作成し、今回作成したQueue Storageのメッセージで連携させます。