このガイドでは、Data Manager API がエラーを処理して通知する方法について説明します。API エラーの構造と意味を理解することは、無効な入力から一時的なサービス停止まで、問題を適切に処理できる堅牢なアプリケーションを構築するうえで非常に重要です。
Data Manager API は、gRPC ステータス コードに基づく標準の Google API エラーモデルに従います。エラーが発生した各 API レスポンスには、次の内容を含む Status オブジェクトが含まれます。
- 数値のエラーコード。
- エラー メッセージ。
- 省略可。エラーに関する追加の詳細。
標準的なエラーコード
Data Manager API は、gRPC と HTTP で定義された一連の正規のエラーコードを使用します。これらのコードは、エラーの種類を大まかに示します。このコードを最初に確認して、問題の根本的な性質を理解する必要があります。
これらのコードの詳細については、API 設計ガイド - エラーコードをご覧ください。
エラーを処理する
リクエストが失敗した場合は、次の手順を行います。
エラーコードを確認して、エラーの種類を特定します。
- gRPC を使用する場合、エラーコードは
Statusのcodeフィールドにあります。クライアント ライブラリを使用する場合、エラーコードに対応する特定のエラーがスローされることがあります。たとえば、エラーコードがINVALID_ARGUMENTの場合、Java 用クライアント ライブラリはcom.google.api.gax.rpc.InvalidArgumentExceptionをスローします。 - REST を使用する場合、エラーコードは
error.statusのエラー レスポンスにあり、対応する HTTP ステータスはerror.codeにあります。
- gRPC を使用する場合、エラーコードは
エラーコードの標準詳細ペイロードを確認します。標準の詳細ペイロードは、Google API からのエラーに関するメッセージのセットです。エラーの詳細を構造化された一貫性のある方法で提供します。Data Manager API の各エラーには、複数の標準詳細ペイロード メッセージが含まれている場合があります。Data Manager API クライアント ライブラリには、エラーから標準の詳細ペイロードを取得するヘルパー メソッドがあります。
エラーコードに関係なく、
ErrorInfo、RequestInfo、Help、LocalizedMessageのペイロードを確認してログに記録することをおすすめします。ErrorInfoには、他のペイロードに含まれていない情報が含まれている可能性があります。RequestInfoにはリクエスト ID が含まれています。これは、サポートに連絡する場合に役立ちます。HelpとLocalizedMessageには、エラーの解決に役立つリンクなどの詳細情報が含まれています。
また、
BadRequest、QuotaFailure、RetryInfoペイロードは、特定のエラーコードに役立ちます。- ステータス コードが
INVALID_ARGUMENTの場合は、BadRequestペイロードで、エラーの原因となったフィールドに関する情報を確認します。 - ステータス コードが
RESOURCE_EXHAUSTEDの場合は、QuotaFailureとRetryInfoのペイロードで割り当て情報と再試行遅延の推奨事項を確認します。
標準詳細ペイロード
Data Manager API の最も一般的な標準詳細ペイロードは次のとおりです。
BadRequest
リクエストが INVALID_ARGUMENT(HTTP ステータス コード 400)で失敗した場合は、BadRequest ペイロードを確認します。
BadRequest メッセージは、リクエストに無効な値のフィールドが含まれているか、必須フィールドの値が欠落していることを示します。BadRequest の field_violations リストで、エラーが発生しているフィールドを確認します。各 field_violations エントリには、エラーの修正に役立つ情報が含まれています。
fieldリクエスト内のフィールドの場所。キャメルケースのパス構文を使用します。
パスがリスト内のアイテム(
repeatedフィールド)を指している場合、そのインデックスはリスト名の後に角かっこ([...])で囲まれて表示されます。たとえば、
destinations[0].operating_account.account_idはdestinationsリストの最初のアイテムのoperating_accountのaccount_idです。description値がエラーの原因となった理由の説明。
reasonErrorReason列挙型(INVALID_HEX_ENCODING、INVALID_CURRENCY_CODEなど)。
「BadRequest」の例
BadRequest メッセージを含む INVALID_ARGUMENT エラーのレスポンスの例を次に示します。field_violations は、エラーが数値ではない accountId であることを示しています。field 値 destinations[0].login_account.account_id は、フィールド違反のある accountId が destinations リストの最初のアイテムの login_account にあることを示します。
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com",
"metadata": {
"requestId": "t-a8896317-069f-4198-afed-182a3872a660"
}
},
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-a8896317-069f-4198-afed-182a3872a660"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "destinations[0].login_account.account_id",
"description": "String is not a valid number.",
"reason": "INVALID_NUMBER_FORMAT"
}
]
}
]
}
}
BadRequest メッセージを含む INVALID_ARGUMENT エラーからのレスポンスの別の例を次に示します。この場合、field_violations リストには次の 2 つのエラーが表示されます。
最初の
eventの値は、イベントの 2 番目のユーザー識別子で 16 進数エンコードされていません。2 番目の
eventの値は、イベントの 3 番目のユーザー識別子で 16 進数エンコードされていません。
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com",
"metadata": {
"requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
}
},
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "events.events[0].user_data.user_identifiers[1]",
"description": "The HEX encoded value is malformed.",
"reason": "INVALID_HEX_ENCODING"
},
{
"field": "events.events[1].user_data.user_identifiers[2]",
"description": "The HEX encoded value is malformed.",
"reason": "INVALID_HEX_ENCODING"
}
]
}
]
}
}
QuotaFailure、RetryInfo
リクエストが RESOURCE_EXHAUSTED(HTTP ステータス コード 429)で失敗した場合は、QuotaFailure と RetryInfo のペイロードを確認します。
QuotaFailure メッセージは、リソースが枯渇した(割り当てを超過したなど)か、システムが過負荷になっていることを示します。violations のリストを調べて、どの割り当てが超過したかを特定します。
エラーには、リクエストの再試行に推奨される retry_delay を示す RetryInfo メッセージが含まれることもあります。
RequestInfo
リクエストが失敗した場合は、必ず RequestInfo ペイロードを確認してください。RequestInfo には、API リクエストを一意に識別する request_id が含まれます。
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}
エラーをログに記録したり、サポートに連絡したりする場合は、問題の診断に役立つように、リクエスト ID を必ず含めてください。
ErrorInfo
ErrorInfo メッセージを確認して、他の標準の詳細ペイロードでキャプチャされない可能性のある追加情報を取得します。ErrorInfo ペイロードには、エラーに関する情報を含む metadata マップが含まれています。
たとえば、Data Manager API が有効になっていない Google Cloud プロジェクトの認証情報を使用したことが原因で PERMISSION_DENIED エラーが発生した場合の ErrorInfo は次のようになります。ErrorInfo には、次のようなエラーに関する追加情報が提供されます。
- リクエストに関連付けられたプロジェクト(
metadata.consumer)。 metadata.serviceTitleの下のサービスの名前。metadata.activationUrlでサービスを有効にできる URL。
{
"error": {
"code": 403,
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SERVICE_DISABLED",
"domain": "googleapis.com",
"metadata": {
"consumer": "projects/PROJECT_NUMBER",
"service": "datamanager.googleapis.com",
"containerInfo": "PROJECT_NUMBER",
"serviceTitle": "Data Manager API",
"activationUrl": "https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
}
},
...
]
}
}
Help、LocalizedMessage
Help ペイロードと LocalizedMessage ペイロードを確認して、エラーの理解と修正に役立つドキュメントとローカライズされたエラー メッセージへのリンクを取得します。
たとえば、Data Manager API が有効になっていない Google Cloud プロジェクトの認証情報を使用したことが原因で PERMISSION_DENIED が失敗した場合の Help と LocalizedMessage は次のようになります。Help ペイロードには、サービスを有効にできる URL が表示されます。LocalizedMessage には、エラーの説明が表示されます。
{
"error": {
"code": 403,
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.LocalizedMessage",
"locale": "en-US",
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
},
{
"@type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developers console API activation",
"url": "https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
}
]
},
...
]
}
}
アクセス エラーの詳細
クライアント ライブラリのいずれかを使用している場合は、ヘルパー メソッドを使用して標準の詳細ペイロードを取得します。
.NET
try {
// Send API request
}
catch (Grpc.Core.RpcException rpcException)
{
Console.WriteLine($"Exception encountered: {rpcException.Message}");
var statusDetails =
Google.Api.Gax.Grpc.RpcExceptionExtensions.GetAllStatusDetails(
rpcException
);
foreach (var detail in statusDetails)
{
if (detail is Google.Rpc.BadRequest)
{
Google.Rpc.BadRequest badRequest = (Google.Rpc.BadRequest)detail;
foreach (
BadRequest.Types.FieldViolation? fieldViolation in badRequest.FieldViolations
)
{
// Access attributes such as fieldViolation!.Reason and fieldViolation!.Field
}
}
else if (detail is Google.Rpc.RequestInfo)
{
Google.Rpc.RequestInfo requestInfo = (Google.Rpc.RequestInfo)detail;
string requestId = requestInfo.RequestId;
// Log the requestId...
}
else if (detail is Google.Rpc.QuotaFailure)
{
Google.Rpc.QuotaFailure quotaFailure = (Google.Rpc.QuotaFailure)detail;
foreach (
Google.Rpc.QuotaFailure.Types.Violation violation in quotaFailure.Violations
)
{
// Access attributes such as violation.Subject and violation.QuotaId
}
}
else
{
// ...
}
}
}
Java
try {
// Send API request
} catch (com.google.api.gax.rpc.InvalidArgumentException invalidArgumentException) {
// Gets the standard BadRequest payload from the exception.
BadRequest badRequest = invalidArgumentException.getErrorDetails().getBadRequest();
for (int i = 0; i < badRequest.getFieldViolationsCount(); i++) {
FieldViolation fieldViolation = badRequest.getFieldViolations(i);
// Access attributes such as fieldViolation.getField() and fieldViolation.getReason()
}
// Gets the standard RequestInfo payload from the exception.
RequestInfo requestInfo = invalidArgumentException.getErrorDetails().getRequestInfo();
if (requestInfo != null) {
String requestId = requestInfo.getRequestId();
// Log the requestId...
}
} catch (com.google.api.gax.rpc.QuotaFailureException quotaFailureException) {
// Gets the standard QuotaFailure payload from the exception.
QuotaFailure quotaFailure = quotaFailureException.getErrorDetails().getQuotaFailure();
for (int i = 0; i < quotaFailure.getViolationsCount(); i++) {
QuotaFailure.Violation violation = quotaFailure.getViolations(i);
// Access attributes such as violation.getSubject() and violation.getQuotaId()
}
// Gets the standard RequestInfo payload from the exception.
RequestInfo requestInfo = quotaFailureException.getErrorDetails().getRequestInfo();
if (requestInfo != null) {
String requestId = requestInfo.getRequestId();
// Log the requestId...
}
} catch (com.google.api.gax.rpc.ApiException apiException) {
// Fallback exception handler for other types of ApiException.
...
}
エラー処理のベスト プラクティス
復元力のあるアプリケーションを構築するには、次のベスト プラクティスを実装します。
- エラーの詳細を確認する
- 常に
BadRequestなどの標準の詳細ペイロードを探します。各標準詳細ペイロードには、エラーの原因を把握するのに役立つ情報が含まれています。 - クライアント エラーとサーバーエラーを区別する
エラーの原因が実装(クライアント)の問題か、API(サーバー)の問題かを判断します。
- クライアント エラー:
INVALID_ARGUMENT、NOT_FOUND、PERMISSION_DENIED、FAILED_PRECONDITION、UNAUTHENTICATEDなどのコード。これらには、リクエストまたはアプリケーションの状態/認証情報の変更が必要です。問題を解決せずにリクエストを再試行しないでください。 - サーバーエラー:
UNAVAILABLE、INTERNAL、DEADLINE_EXCEEDED、UNKNOWNなどのコード。これは、API サービスの一時的な問題を示しています。
- クライアント エラー:
- 再試行戦略を実装する
エラーを再試行できるかどうかを判断し、再試行戦略を使用します。
UNAVAILABLE、DEADLINE_EXCEEDED、INTERNAL、UNKNOWN、ABORTEDなどの一時的なサーバーエラーの場合にのみ再試行します。- 指数バックオフのアルゴリズムを使用して、再試行間の待ち時間を増やします。これにより、すでに負荷がかかっているサービスにさらに負荷がかかるのを防ぐことができます。たとえば、1 秒待ってから 2 秒待ち、4 秒待つというように、再試行の最大回数または合計待機時間に達するまで続けます。
- バックオフ遅延に小さなランダムな「ジッター」を追加して、多数のクライアントが同時に再試行する「Thundering Herd」の問題を防ぎます。
- 徹底的にログを記録する
すべての標準詳細ペイロード(特にリクエスト ID)を含む完全なエラー レスポンスをログに記録します。この情報は、デバッグや、必要に応じて Google サポートに問題を報告する際に不可欠です。
- ユーザー フィードバックを提供する
標準の詳細ペイロードのコードとメッセージに基づいて、アプリのユーザーに明確で役立つフィードバックを提供します。たとえば、「エラーが発生しました」ではなく、「トランザクション ID がありませんでした」や「宛先のアカウント ID が見つかりませんでした」のようにします。
これらのガイドラインに沿って対応することで、Data Manager API から返されるエラーを効果的に診断して処理し、より安定したユーザー フレンドリーなアプリケーションを実現できます。