ログの構成

完了

Azure Cosmos DB for NoSQL SDK が "見えないところで" 実行する HTTP 要求をログしたいことがよくあります。この SDK には、カスタム ハンドラーを HTTP の要求と応答に簡単に挿入できる便利なクライアント ビルダー クラスが含まれています。 この機能を利用して、単純なログ記録メカニズムを構築できます。

クライアント ビルダー

Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder クラスは、新しいクライアント インスタンスをスムーズに構成するビルダー クラスです。 CosmosClientOptions クラスの代わりに使用される複数のメソッド含まれていますが、これだけに限られません。

方法 説明
WithApplicationRegion または WithApplicationPreferredRegions 優先リージョンを構成します
WithConnectionModeDirectWithConnectionModeGateway 接続モードを設定します。
WithConsistencyLevel 整合性レベルをオーバーライドします。

ビルダーを使用するには、まず using ディレクティブを Microsoft.Azure.Cosmos.Fluent 名前空間に追加する必要があります。

using Microsoft.Azure.Cosmos.Fluent;

これで、接続文字列またはエンドポイントとキーのペアをコンストラクター パラメーターとして渡す CosmosClientBuilder クラスの新しいインスタンスを作成できます。

CosmosClientBuilder builder = new (connectionString);

CosmosClientBuilder builder = new (endpoint, key);

この時点で、任意の Fluent メソッドを追加してクライアントを構成できます。 Fluent メソッドを実行したら、Build メソッドを呼び出して、CosmosClient 型のインスタンスを作成できます。

CosmosClient client = builder.Build();

カスタム ログ ハンドラーを作成する

HTTP 要求をログに記録するには、抽象 RequestHandler クラスから継承する新しいクラスを作成する必要があります。 ハンドラーでは、HTTP 要求の送信前と送信後にロジックを追加できます。 この例では、HTTP 要求の送信時に次のワークフローを実行するハンドラーを作成します。

  1. 元の要求の HTTP メソッドと URI をコンソールに書き込む
  2. 基本の実装に要求を送信し、応答を変数に格納する
  3. HTTP 状態コード番号と説明をコンソールに書き込む
  4. 応答を返す

カスタム RequestHandler 実装を作成する

これを実装するには、RequestHandler から継承する新しいクラスを作成する必要があります。

public class LogHandler : RequestHandler
{   
}

抽象クラスには、要求に関する新しいロジックを挿入するためにオーバーライドする必要がある SendAsync メソッドが含まれています。

public override async Task<ResponseMessage> SendAsync(RequestMessage request, CancellationToken cancellationToken)
{
}

SendAsync メソッド内では、RequestMessageパラメーターの RequestUri および Methodプロパティがコンソールに出力されます。 次に、基本メソッド SendAsync が呼び出され、実際の要求が送信され、応答がローカル変数に格納されます。

Console.WriteLine($"[{request.Method.Method}]\t{request.RequestUri}");

ResponseMessage response = await base.SendAsync(request, cancellationToken);

応答がローカル変数に格納されると、応答の StatusCode が数値および文字列形式の両方で出力されます。 その後、非同期メソッドの結果として応答が返されます。

Console.WriteLine($"[{Convert.ToInt32(response.StatusCode)}]\t{response.StatusCode}");

return response;

このクラスのコード全体を次に示します。

public class LogHandler : RequestHandler
{    
    public override async Task<ResponseMessage> SendAsync(RequestMessage request, CancellationToken cancellationToken)
    {
        Console.WriteLine($"[{request.Method.Method}]\t{request.RequestUri}");

        ResponseMessage response = await base.SendAsync(request, cancellationToken);
        
        Console.WriteLine($"[{Convert.ToInt32(response.StatusCode)}]\t{response.StatusCode}");
        
        return response;
    }
}

クライアント ビルダーでカスタム RequestHandler 実装を使用する

要求ハンドラーの実装の準備ができたら、カスタム要求ハンドラーの新しいインスタンスを渡すCosmosClientBuilder インスタンスのAddCustomHandler メソッドを呼び出します。

builder.AddCustomHandlers(new LogHandler());

ビルダーを使用してクライアントを完全に作成するコードを次に示します。

CosmosClientBuilder builder = new (endpoint, key);

builder.AddCustomHandlers(new LogHandler());

CosmosClient client = builder.Build();

カスタム ロガーをテストする

クライアント インスタンスを使用して CreateDatabaseIfNotExistsAsync メソッドを呼び出す架空のシナリオを想定します。 クライアント インスタンスでは、最初にデータベースの存在を確認する必要があります。データベースが見つからない場合は、指定した名前を使用して新しいデータベースが作成されます。

この架空のシナリオでは、このコード行の例を使用して、CreateDatabaseIfNotExistsAsync メソッドを呼び出します。

Database result = await client.CreateDatabaseIfNotExistsAsync("cosmicworks");

アプリケーションを初めて実行すると、次のアクションを実行したことがロガーで出力されます。

  1. dbs/<database-name> エンドポイントで特定のデータベースに対してクエリを実行する HTTP GET要求を送信しました。
  2. データベースが見つからなかったことを示す 404応答を受信しました。
  3. データベースの詳細が要求の本文に含まれる HTTP POST要求dbs/ エンドポイントに送信しました。
  4. データベースの詳細が応答の本文含まれるデータベースが作成されたことを示す 201応答を受信しました。
[GET]   dbs/cosmicworks
[404]   NotFound
[POST]  dbs/
[201]   Created

アプリケーションを再度実行した場合、はるかに短いワークフローがロガーで出力されます。

  1. dbs/<database-name> エンドポイントで特定のデータベースに対してクエリを実行する HTTP GET要求を送信しました。
  2. データベースの詳細が応答の本文含まれるデータベースが見つかったことを示す 200応答を受信しました。
[GET]   dbs/cosmicworks
[200]   OK