Azure Functionsを使ってDocumentDBのコレクション情報を取得する

DocumentDBのデータの格納状況やRUの消費状況などのメトリクスは、基本的にポータルで確認することができますが、グラフでざっと全体感を見るよりも、特定のコレクションについての正確な情報が知りたい局面などもあると思います。

そのような時は、公式ドキュメントにも述べられているように、DocumentDBのAPI群を使ってコレクションのより詳細な使用状況データを取得するのが一般的です。

DocumentDB APIにはRESTを使ってアクセスする方法がありますが、さすがデータベースのマネージドサービスというだけあって、他のサービスのRESTよりもアクセス方法が厳しく、キーさえあれば良いというわけにはいかないとても複雑な手続きが必要です(ハッシュの生成に結局コードを書かなきゃいけない等、個人的には二度とやりたくない系)。

なので特に事情がなければ、REST APIではなく、DocumentDB .NET SDKを使って実装するのがオススメです。この記事では、せっかくなのでGAしたばかりのAzure Functions上に実装して、HTTPトリガーから気軽にDocumentDB APIを呼び出せるように実装してみたいと思います。

Function Appの準備

Visual Studio Tools for Azure Functionsのセットアップ

ポータル上の簡易エディタを使っても良いですが、インテリセンスが効いてローカル環境でデバッグもできる「Visual Studio Tools for Azure Functions」を使って、Visual Studio 2015で開発できるようにします。

公式Blogの通りにプラグインをインストールすると、プロジェクトの新規作成時に以下のようにAzure Functionsのテンプレートを選択できるようになります。

新規関数の作成

個別の関数はFunction Appプロジェクト配下で、[New Azure Function]メニューから作成することができます。

言語やトリガーを選択することができます。ここではC#でHttpTriggerを選びます。

DocumentDB接続情報のセット

今回はDocumentDBのAPIにカスタムアクセスするので、function.jsonのバインディング設定は使わず、AppService全体の設定を入れるappsettings.jsonにDocumentDBの接続情報を設定します。
その際、DocumentDB APIアクセスに必要となる、[ServiceEndpoint]と[DocumentAuthKey]を忘れないように追加しておきます。

appsettings.json

{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "{ストレージアカウント接続文字列}",
"AzureWebJobsDashboard": "{ストレージアカウント接続文字列}",
"ServiceEndpoint": "{DocumentDBのURL}",
"DocumentAuthKey": "{DocumentDBアカウントへのアクセスキー}"
}
}

DocumentDB .NET SDK nugetパッケージの取得

Azure Functionでのnugetパッケージの追加方法は、project.jsonに必要なパッケージを記述します(npmのpackage.jsonと同じような仕組み)。
ここでは、DocumentDB の.NET SDKである「Microsoft.Azure.DocumentDB」を追加します。

project.json

{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.Azure.DocumentDB": "1.10.0"
}
}
}
}

特にnugetを実行するコマンド等は不要で、DocumentDB SDKパッケージを追加すると、初回に実行した時点で自動的にパッケージのリストアが走り、関数ディレクトリの配下に必要なパッケージが保存されるようになっています。

project.jsonで登録したパッケージは、関数本体で直接usingを使ってアセンブリを呼出すことができます( #r “AssemblyName” 方式の参照は不要です)。

Functionsの実装

DocumentDB SDKを使った関数の実装

今回run..csxの実装は以下のようになりました(エラー処理とか入れてません)。

DocumentDB の.NET SDKでコレクション情報を取得するにはDocumentClient.ReadDocumentCollectionAsyncメソッドを使用します(20行目)。

「Visual Studio Tools for Azure Functions」を使って実装した場合のメリットとして、Azureにデプロイする前にローカルで実行することができる点があります。みんなだいすきインテリセンスが使えたり(一部制限はあります)、デバッグはもちろんステップ実行も可能です。

Functionの実行

run.csxをVSでデバッグ実行すると、Functionsのローカルエミュレータが起動してトリガーの待機状態になります。

今回作った関数はHTTPトリガーなので、PostmanなどのRESTクライアントツールを使って、コンソールに表示されているホスト名にアクセスすれば、DocumentDBからレスポンスを得ることができます。

なお、VSからAzureへのデプロイも実行できるはずですが、多分うまくいきません(私だけかも)。公式ブログによれば、執筆時点(2016年12月)では一部制約事項があり、一部手動で対応しなければ動かない部分があるようです。このあたりはプラグインの更新に期待しましょう。

結果の分析

DocumentClient.ReadDocumentCollectionAsyncから返ってくる結果は、以下のようにポータルでは表示されないような多くの情報を返してくれます。

{
"DatabaseQuota": 0,
"DatabaseUsage": 0,
"CollectionQuota": 0,
"CollectionUsage": 0,
"UserQuota": 0,
"UserUsage": 0,
"PermissionQuota": 0,
"PermissionUsage": 0,
"CollectionSizeQuota": 10485760,
"CollectionSizeUsage": 427,
"DocumentQuota": 10485760,
"DocumentUsage": 288,
"StoredProceduresQuota": 25,
"StoredProceduresUsage": 0,
"TriggersQuota": 25,
"TriggersUsage": 0,
"UserDefinedFunctionsQuota": 25,
"UserDefinedFunctionsUsage": 0,
"ActivityId": {一部省略},
"SessionToken": "0:8993",
"StatusCode": 200,
"MaxResourceQuota": "functions=25;storedProcedures=25;triggers=25;documentSize=10240;documentsSize=10485760;documentsCount=-1;collectionSize=10485760;",
"CurrentResourceQuotaUsage": "functions=0;storedProcedures=0;triggers=0;documentSize=0;documentsSize=288;documentsCount=528;collectionSize=427;",
{以下省略}
}

中でもよく使いそうなメトリクスは、CurrentResourceQuotaUsageあたりではないしょうか。この中にはポータルではもちろんSQLでも一発で取れないドキュメント数(documentsCount)などのメトリクスが含まれており、DocumentDBコレクションのパフォーマンス調整には欠かせない情報が含まれています。

希望を言えば、もう少し簡単に個別のメトリクスが取れる(参照できる)ようになって欲しいですが、これはこれで汎用的なので、いろいろなメトリクスから総合的に判断してコレクションのスケール調整を行いたいといったニーズにはぴったりでしょう。