Azure SDK for C++ でのエラー処理

Azure SDK for C++ でのエラー処理は、主に C++ 例外によって実装されます。 このアプローチは、標準的な C++ プラクティスに沿っており、SDK 全体で明確なエラー報告と処理が可能になります。 C++ アプリケーションが Azure サービスと対話すると、認証の問題、サービスの利用不可、無効な要求、リソースの制約など、さまざまな理由で操作が失敗する可能性があります。 SDK は、エラーに関する詳細情報を提供する例外としてこれらのエラーをキャプチャします。

例外階層

コア例外の種類

Azure SDK for C++ では、例外クラスの階層が使用され、最も重要なものは次のとおりです。

  1. std::runtime_error - Azure 固有の例外が継承されるベース C++ 標準例外。

  2. Azure::Core::RequestFailedException - std::runtime_errorから派生した、これはすべての Azure サービス要求エラーの基本例外です。 azure/core/exception.hppで定義されているこの例外は、Azure サービスへの要求が失敗したときにスローされます。 次の機能を提供します。

    • HTTP 状態コード
    • サービスからのエラー コード
    • エラー メッセージ
    • トラブルシューティングのために ID を要求する
    • 生の HTTP 応答
  3. Azure::Core::OperationCancelledException - std::runtime_errorから派生したこの例外は、通常、コンテキストオブジェクトを介して操作が取り消されると、投げられます。

  4. Azure::Core::Http::TransportException - Azure::Core::RequestFailedExceptionから派生したこの例外は、接続エラーなどの HTTP トランスポート層でエラーが発生するとスローされます。

  5. Azure::Core::Credentials::AuthenticationException - std::exception から派生した例外は、Azure サービスでの認証が失敗したときにスローされます。

サービス固有の例外の種類

さまざまな Azure サービスによって、基本例外の種類が拡張され、サービス固有のエラー情報が提供されます。

  1. Azure::Storage::StorageException - RequestFailedException を他のストレージ固有の情報と共に拡張します。 この例外には次のものが含まれます。

    • ストレージ固有のエラー コード
    • 応答本文に含まれる追加情報
    • 失敗したストレージ操作の詳細
  2. Azure::Messaging::EventHubs::EventHubsException - Event Hubs 操作に固有の例外。 内容は以下のとおりです。

    • エラー状態 (Advanced Message Queuing Protocol (AMQP) からのシンボリック値)
    • エラーの説明
    • 状態コード
    • エラーが一時的かどうかに関する情報

例外のエラー情報

RequestFailedException クラスには、サービスエラーに関する豊富な情報が含まれています。

class RequestFailedException : public std::runtime_error {
public:
    // The entire HTTP raw response
    std::unique_ptr<Azure::Core::Http::RawResponse> RawResponse;
    
    // The HTTP response code
    Azure::Core::Http::HttpStatusCode StatusCode;
    
    // The HTTP reason phrase from the response
    std::string ReasonPhrase;
    
    // The client request header (x-ms-client-request-id) from the HTTP response
    std::string ClientRequestId;
    
    // The request ID header (x-ms-request-id) from the HTTP response
    std::string RequestId;
    
    // The error code from service returned in the HTTP response
    std::string ErrorCode;
    
    // The error message from the service returned in the HTTP response
    std::string Message;
    
    /* ... constructors and other methods ... */
};

サービス固有の例外では、追加のフィールドを追加できます。 たとえば、StorageExceptionがAdditionalInformationを追加します。

struct StorageException final : public Azure::Core::RequestFailedException {
    // Some storage-specific information in response body
    std::map<std::string, std::string> AdditionalInformation;
    
    /* ... constructors and other methods ... */
};

例外処理のパターンと例

エラー コードの使用

サービス例外には、エラーの処理方法を決定するために使用できる ErrorCode 値が含まれています。 Storage サービスの例を次に示します。

try {
    containerClient.Delete();
}
catch (Azure::Storage::StorageException& e) {
    if (e.ErrorCode == "ContainerNotFound") {
        // Ignore the error if the container does not exist
    }
    else {
        // Handle other errors here
    }
}

基本的な例外の処理

Azure SDK で例外を処理するための基本的なパターン:

try {
    // Perform an Azure SDK operation
    result = client.SomeOperation();
}
catch (Azure::Core::RequestFailedException const& e) {
    std::cout << "Request Failed Exception happened:" << std::endl << e.what() << std::endl;
    if (e.RawResponse) {
        std::cout << "Error Code: " << e.ErrorCode << std::endl;
        std::cout << "Error Message: " << e.Message << std::endl;
    }
    // Handle or rethrow as appropriate
}
catch (std::exception const& e) {
    std::cout << "Other exception: " << e.what() << std::endl;
    // Handle general exceptions
}

一時的エラーの処理

Event Hubs などの一部のサービスでは、エラーが一時的なものであるかどうかに関する情報が提供され、再試行ロジックが可能になります。

try {
    // EventHubs operation
}
catch (Azure::Messaging::EventHubs::EventHubsException& e) {
    if (e.IsTransient) {
        // Retry the operation after a delay
    }
    else {
        // Handle permanent failure
    }
}

SDK は、一時的な障害に対する内部再試行ポリシーを実装しますが、アプリケーション コード内の特定のケースを処理することが必要な場合があります。

サービス固有のエラー処理

BLOB、ファイル、キューなどのストレージ サービスでは、エラー コードと HTTP 状態コードの両方に基づいてエラーを処理できます。

try {
    shareClient.Delete();
}
catch (Azure::Storage::StorageException& e) {
    if (e.ErrorCode == "ShareNotFound") {
        // Ignore the error if the file share does not exist
    }
    else if (e.StatusCode == Azure::Core::Http::HttpStatusCode::Conflict) {
        // Handle conflict error (e.g., resource in use)
        std::cout << "Conflict error: " << e.Message << std::endl;
        
        // Check additional information
        for (auto const& info : e.AdditionalInformation) {
            std::cout << info.first << ": " << info.second << std::endl;
        }
    }
    else {
        // Handle other errors based on status code or error code
        std::cout << "Error: " << e.Message << " (Code: " << e.ErrorCode << ")" << std::endl;
    }
}

Key Vault の操作では、認証例外を個別に処理することが必要になる場合があります。

try {
    // Key Vault operation
}
catch (Azure::Core::Credentials::AuthenticationException const& e) {
    std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
    // Handle authentication failure (e.g., invalid credentials)
}
catch (Azure::Core::RequestFailedException const& e) {
    std::cout << "Key Vault Client Exception happened:" << std::endl << e.Message << std::endl;
    // Handle Key Vault specific errors
}

スレッドの安全性に関する考慮事項

Azure SDK for C++ は、クライアント インスタンス メソッドがスレッド セーフであり、相互に独立していることを保証します。 つまり、同期なしで複数のスレッドにわたってクライアント インスタンスを安全に使用できます。

スレッド間で例外を処理する場合は、次の点に注意してください。

  1. 例外オブジェクトは、適切に同期されない限り、スレッド間で共有しないでください
  2. RequestFailedExceptionには、ディープ コピーを作成するコピー コンストラクターが含まれています。これは、スレッド間で例外情報を渡す必要がある場合に使用できます。