ログの構成

完了

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 クラスの新しいインスタンスを作成できますが、本番環境ではマネージドアイデンティティを使用することをお勧めします。 この例では、マネージド ID を使用して Azure Cosmos DB で認証を行います。

// Using DefaultAzureCredential
TokenCredential defaultCredential = new DefaultAzureCredentialBuilder().build();
CosmosClientBuilder builder = new CosmosClientBuilder()
    .endpoint("<your-cosmos-endpoint>")
    .credential(defaultCredential)
    .consistencyLevel(ConsistencyLevel.EVENTUAL);

// Using ManagedIdentityCredential
TokenCredential managedIdentityCredential = new ManagedIdentityCredentialBuilder()
    .clientId("<your-managed-identity-client-id>")
    .build();
CosmosClientBuilder builder = new CosmosClientBuilder()
    .endpoint("<your-cosmos-endpoint>")
    .credential(managedIdentityCredential)
    .consistencyLevel(ConsistencyLevel.EVENTUAL);

この時点で、任意の 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());

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

// Using ManagedIdentityCredential
TokenCredential managedIdentityCredential = new ManagedIdentityCredentialBuilder()
    .clientId("<your-managed-identity-client-id>")
    .build();
CosmosClientBuilder builder = new CosmosClientBuilder()
    .endpoint("<your-cosmos-endpoint>")
    .credential(managedIdentityCredential)
    .consistencyLevel(ConsistencyLevel.EVENTUAL);

builder.AddCustomHandlers(new LogHandler());

CosmosClient client = builder.Build();

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

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

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

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

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

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

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

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

Azure Cosmos DB アプリケーションの監視とデバッグには、適切なログ記録が不可欠です。 Python SDK には、ログ記録を有効にし、診断をキャプチャし、ログに記録される情報の量を微調整するための複数のメカニズムが用意されています。

ログ機能の概要

Azure Cosmos DB Python SDK は、Python の標準 logging モジュールと統合されています。 既定の設定:

  • 基本的な HTTP セッション情報 (URL やヘッダーなど) は、#D0 レベルでログに記録されます。
  • 本文や非編集のヘッダーを含む詳細な要求と応答の記録は、DEBUG レベルで利用可能です。

主な機能

  1. グローバル ログ記録: クライアント単位でログを有効にし、すべての操作に関する診断情報を収集します。
  2. 個別操作のログ記録: 各操作ごとの詳細なログ記録を有効にします。
  3. 拡張診断機能: CosmosHttpLoggingPolicy を使用して Cosmos DB のデバッグ情報をさらに多くキャプチャします。

基本的なログ記録の有効化

Python SDK では、診断に logging モジュールが使用されます。 まず、HTTP セッションの詳細をキャプチャするための基本的なログ記録を構成できます。

例: 基本的なログ記録の構成

import sys
import logging
from azure.cosmos import CosmosClient

# Create a logger for the Azure SDK
logger = logging.getLogger("azure")
logger.setLevel(logging.DEBUG)  # Set log level to DEBUG for detailed output

# Configure console output
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

# Initialize the CosmosClient with global logging enabled
client = CosmosClient("<cosmos-endpoint>", "<cosmos-key>", logging_enable=True)

# Perform an operation to observe logs
database = client.create_database_if_not_exists("cosmicworks")
print(f"Database created or retrieved: {database.id}")

logging_enable=True は、クライアント レベルで詳細なログ記録を可能にし、すべての HTTP 要求と応答をキャプチャします。 このセットアップは、開発中のデバッグに最適です。

操作ごとのログの有効化

特定の操作に対して詳細なログ記録が必要な場合は、クライアントに対してグローバルにログ記録しない場合は、操作ごとに有効にすることができます。

例: 操作レベルのログ記録

# Perform an operation with logging enabled specifically for this request
database = client.create_database("cosmicworks", logging_enable=True)
print(f"Database created: {database.id}")

この方法では、ログ記録を個々の操作に制限し、運用環境のログ ノイズを減らします。

CosmosHttpLoggingPolicy を使用した拡張診断

SDK には、Azure の CosmosHttpLoggingPolicy に基づいて拡張されたログ ポリシー HttpLoggingPolicy が用意されています。 このポリシーは、要求時間の経過やエラー メッセージなど、Cosmos DB に固有の診断情報をキャプチャします。

例: CosmosHttpLoggingPolicy の使用

import logging
from azure.cosmos import CosmosClient

# Create a logger for the Azure SDK
logger = logging.getLogger("azure")
logger.setLevel(logging.DEBUG)

# Configure file output for logs
handler = logging.FileHandler(filename="cosmos_logs.txt")
logger.addHandler(handler)

# Initialize the CosmosClient with enhanced diagnostics logging
client = CosmosClient(
    "<cosmos-endpoint>", 
    "<cosmos-key>", 
    logger=logger, 
    enable_diagnostics_logging=True
)

# Perform an operation to observe enhanced diagnostics
database = client.create_database_if_not_exists("cosmicworks")
print(f"Database created or retrieved: {database.id}")

クライアントに enable_diagnostics_logging=True を渡すと、 CosmosHttpLoggingPolicyが有効になります。 ログには、応答のタイミングや診断ヘッダーなど、Cosmos DB に関連する詳細が含まれます。

グローバルログと Operation-Level ログの組み合わせ

グローバル ログと操作ごとのログ記録を組み合わせて、ログに記録される内容をきめ細かく制御できます。

例:ログ レベルの組み合わせ

# Initialize the CosmosClient with enhanced diagnostics
client = CosmosClient(
    "<cosmos-endpoint>", 
    "<cosmos-key>", 
    enable_diagnostics_logging=True
)

# Perform an operation with a custom logger
logger = logging.getLogger("azure.operation")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

# Use the custom logger for a specific operation
database = client.create_database("cosmicworks", logger=logger)
print(f"Database created: {database.id}")

この方法では、特定の操作のログ記録を微調整しながら、クライアント レベルで診断を強化できます。

Azure Cosmos DB アプリケーションの監視、デバッグ、最適化には、適切なログ記録と診断が不可欠です。 JavaScript SDK には、HTTP 要求/応答の詳細をログに記録し、詳細な診断を適用してプログラムで操作を分析するための組み込みのメカニズムが用意されています。

ログ機能の概要

Azure Cosmos DB JavaScript SDK では、ログ記録に @azure/logger パッケージが使用されます。 出力の詳細度を制御するための構成可能なログ レベルがサポートされています。 ログは、操作、障害、およびパフォーマンスのボトルネックに関する貴重な情報を明らかにできます。

ログ記録の有効化

ログ記録は、環境変数を介して、または実行時にプログラムによって有効にすることができます。

例 1: 環境変数を使用したログ記録の有効化

アプリケーションを開始する前に、#D0 環境変数を設定します。

macOS/Linux の場合

export AZURE_LOG_LEVEL=info
node your-app.js

Windows の場合

set AZURE_LOG_LEVEL=info
node your-app.js

例 2: プログラムによるログ記録の有効化

@azure/logger パッケージをインポートして構成することで、実行時にログ記録を有効にすることもできます。

const { setLogLevel } = require("@azure/logger");
setLogLevel("info");

info ログ レベルは、過度な詳細なしで不可欠な診断を提供するため、プロダクションシステムに適しています。 レベルを error または warningに設定して、ログをフィルター処理することもできます。

開発中のデバッグでは、verbose を使用してより詳細な出力を行います。

Cosmos Diagnostics の活用

Cosmos Diagnostics は、SDK を使用して実行された操作に関する詳細な分析情報を提供します。 CosmosDiagnostics オブジェクトは、すべての操作の応答に含まれ、ペイロード サイズ、再試行、アクセスされたエンドポイントなどのメトリックをキャプチャします。

診断レベルの構成

診断レベルは、収集される診断情報の粒度を制御します。 次のレベルがサポートされています。

  • info:運用システムに適した最小限の診断。
  • debug:デバッグとパフォーマンス分析の詳細な診断。
  • debug-unsafe:機密性の高い要求と応答のペイロードが含まれます。 運用環境にはお勧めしません

例 1: プログラムによる診断レベルの設定

const { CosmosClient, CosmosDbDiagnosticLevel } = require("@azure/cosmos");

const client = new CosmosClient({
    endpoint: "<cosmos-endpoint>",
    key: "<cosmos-key>",
    diagnosticLevel: CosmosDbDiagnosticLevel.debug
});

例 2: 環境変数を使用した診断レベルの設定

export AZURE_COSMOSDB_DIAGNOSTICS_LEVEL=debug

プログラムによる診断の活用

CosmosDiagnostic オブジェクトはレスポンスオブジェクトでアクセス可能で、多様な側面の分析に使用できます。

例:一般的な操作の診断へのアクセス

// For creating a container
const { container, diagnostics: containerDiagnostics } = await database.containers.createIfNotExists({
    id: "sample-container",
    partitionKey: { paths: ["/key1"] }
});
console.log("Container diagnostics:", containerDiagnostics);

// For querying items
const queryIterator = container.items.query("SELECT * FROM c");
const { resources, diagnostics: queryDiagnostics } = await queryIterator.fetchAll();
console.log("Query diagnostics:", queryDiagnostics);

// For batch operations
const partitionKey = "partition1";
const operations = [
    { operationType: "Create", resourceBody: { id: "item1", key: partitionKey } }
];
const batchResponse = await container.items
    .bulk(operations, { partitionKey });
console.log("Batch diagnostics:", batchResponse.diagnostics);

diagnostics オブジェクトには、要求の継続時間、再試行回数、ペイロードサイズなどのメトリックが含まれます。 診断情報は、非効率的なクエリや高い再試行率などの問題を特定して解決するのに役立ちます。

拡張診断を使用したデバッグ

例: @Azure/logger を使用した診断ログの記録

診断を自動的にログに記録するには、診断レベルを debug または debug-unsafe に設定し、詳細出力用にロガーを構成します。

const { CosmosClient, CosmosDbDiagnosticLevel } = require("@azure/cosmos");
const { setLogLevel } = require("@azure/logger");

setLogLevel("verbose"); // Log detailed diagnostics

const client = new CosmosClient({
    endpoint: "<cosmos-endpoint>",
    key: "<cosmos-key>",
    diagnosticLevel: CosmosDbDiagnosticLevel.debugUnsafe
});

// Perform an operation
const { database } = await client.databases.createIfNotExists({ id: "sample-database" });
const { container } = await database.containers.createIfNotExists({ id: "sample-container" });
const { diagnostics } = await container.items.create({ id: "item1", key: "partition1" });
console.log("Diagnostics logged at verbose level:", diagnostics);

非運用環境でのパフォーマンスを分析するには、debugレベルの診断を使用します。 機密性の高いペイロードが含まれるため、運用環境では debug-unsafe を使用しないでください。