エラー レスポンス

このページでは、User Deletion API から発生する可能性のあるエラーの一覧を示し、500 エラーの処理方法と指数バックオフの実装方法について説明します。

標準エラー レスポンス

User Deletion API リクエストが成功すると、API はステータス コード 200 を返します。リクエストでエラーが発生した場合、API はエラーの種類に基づいて、レスポンスで HTTP ステータス コード、ステータス、理由を返します。また、レスポンス本文にエラーの原因についての詳しい説明が記述されます。エラー レスポンスの例を次に示します。

 { "error": { "errors": [ { "domain": "global", "reason": "invalidParameter",
"message": "Invalid value '-1' for max-results. Value must be within the range:
[1, 1000]", "locationType": "parameter", "location": "max-results" } ], "code":
400, "message": "Invalid value '-1' for max-results. Value must be within the
range: [1, 1000]" } }

エラーの表

コード 理由 説明 推奨される対処方法
400 invalidParameter リクエストのパラメータに無効な値があることを示します。エラー レスポンスの locationType フィールドと location フィールドで、無効であった値を特定する情報が提供されます。 問題を解決してから再試行してください。エラー レスポンスで指定されたパラメータに有効な値を指定する必要があります。
400 badRequest クエリが無効であることを示します。たとえば、「親 ID がない」、「リクエストされたディメンションや指標の組み合わせが無効」などの理由が考えられます。 問題を解決してから再試行してください。API クエリが正常に動作するには、クエリに変更を加える必要があります。
401 invalidCredentials 認証トークンが無効であるか、期限切れであることを示します。 問題を解決してから再試行してください。新しい認証トークンを入手する必要があります。
403 insufficientPermissions クエリで指定されたエンティティに対する十分な権限がないことを示します。 問題を解決してから再試行してください。指定したエンティティに対する操作を行える権限を取得する必要があります。
403 dailyLimitExceeded ユーザーが、(プロジェクトあたり、またはビュー(旧プロファイル)あたりの)1 日の割り当てを超えたことを示します。 問題を解決してから再試行してください。1 日の割り当ての上限に達しました。API の制限と割り当てをご覧ください。
403 userRateLimitExceeded ユーザーごとの 100 秒あたりのクエリ数の上限を超過したことを示します。Google API Console で設定されているデフォルト値は、各ユーザー 100 秒あたり 100 クエリです。この上限は、Google API Console で 1,000 件まで増やすことができます。 指数バックオフを使用して再試行します。リクエストを送信する速度を下げる必要があります。
403 rateLimitExceeded プロジェクトの 100 秒あたりのクエリ数が上限を超えたことを示します。 指数バックオフを使用して再試行します。リクエストを送信する速度を下げる必要があります。
403 quotaExceeded Core Reporting API でビュー(旧プロファイル)あたりの同時リクエスト数が 10 件に達したことを示します。 指数バックオフを使用して再試行します。このビュー(旧プロファイル)に対する処理中のリクエストが 1 つ以上完了するまで待つ必要があります。
500 internalServerError 予期しない内部サーバーエラーが発生しました。 このクエリを 2 回以上再試行しないでください。
503 backendError サーバーからエラーが返されました。 このクエリを 2 回以上再試行しないでください。

500 または 503 レスポンスの処理

負荷が高い場合や、より大規模で複雑なリクエストの場合、500 エラーまたは 503 エラーが発生することがあります。リクエストが大きい場合は、期間を短くしてデータをリクエストすることを検討してください。また、指数バックオフの実装を検討してください。これらのエラーの発生頻度は、ビュー(プロファイル)とそのビューに関連付けられているレポートデータの量によって異なります。あるビュー(プロファイル)で 500 エラーまたは 503 エラーが発生するクエリでも、別のビュー(プロファイル)で同じクエリを実行してもエラーが発生しない場合があります。

指数バックオフを実装する

指数バックオフは、失敗したリクエストをクライアントが再試行する際、失敗するごとに次の再試行までの待ち時間を増やしていく処理です。これは、ネットワーク アプリケーションに使われる標準的なエラー処理方法です。User Deletion API は、クライアントが失敗したリクエストを再試行する際に、指数バックオフが使われることを前提に設計されています。指数バックオフの使用は、「必須」で あるということに加え、帯域利用の効率を高め、レスポンスを 正しく取得するために必要なリクエストの数を減らし、同時実行環境におけるリクエストのスループットを最大化する効果もあります。

指数バックオフを実装する方法は次のとおりです。

  1. API にリクエストを送ります。
  2. 再試行可能なエラーコードを含むエラー レスポンスを受け取ります。
  3. 1 秒 + random_number_milliseconds 秒待ちます。
  4. リクエストを再試行します。
  5. 再試行可能なエラーコードを含むエラー レスポンスを受け取ります。
  6. 2 秒 + random_number_milliseconds 秒待ちます。
  7. リクエストを再試行します。
  8. 再試行可能なエラーコードを含むエラー レスポンスを受信する。
  9. 4 秒 + random_number_milliseconds 秒待ちます。
  10. リクエストを再試行します。
  11. 再試行可能なエラーコードを含むエラー レスポンスを受け取ります。
  12. 8 秒 + random_number_milliseconds 秒待ちます。
  13. リクエストを再試行します。
  14. 再試行可能なエラーコードを含むエラー レスポンスを受け取ります。
  15. 16 秒 + random_number_milliseconds 秒待ちます。
  16. リクエストを再試行します。
  17. まだエラーが発生する場合は、停止してエラーを記録します。

上記のフローで、random_number_milliseconds は、1, 000 ミリ秒以下の乱数です。これは、一部の同時実装で特定のロックエラーを回避するために必要です。random_number_milliseconds は、待機するたびに再定義する必要があります。

このアルゴリズムは、n が 5 になると終了するように設定されています。この上限値は、クライアントによる無制限の再試行を防ぐことが目的です。合計遅延時間が約 32 秒に達すると、リクエストは「修復不可能なエラー」と見なされます。

次の Python コードは、makeRequest メソッドで発生したエラーから回復するために、上記のフローを実装したものです。

import random
import time
from apiclient.errors import HttpError

def makeRequestWithExponentialBackoff(analytics):
  """Wrapper to request Google Analytics data with exponential backoff.

  The makeRequest method accepts the analytics service object, makes API
  requests and returns the response. If any error occurs, the makeRequest
  method is retried using exponential backoff.

  Args:
    analytics: The analytics service object

  Returns:
    The API response from the makeRequest method.
  """
  for n in range(0, 5):
    try:
      return makeRequest(analytics)

    except HttpError, error:
      if error.resp.reason in ['userRateLimitExceeded', 'quotaExceeded',
                               'internalServerError', 'backendError']:
        time.sleep((2 ** n) + random.random())
      else:
        break

  print "There has been an error, the request never succeeded."