エラー レスポンス

標準エラー レスポンス

Reporting API のリクエストに成功すると、API は 200 を返します。リクエストでエラーが発生すると、API はエラーの種類に基づいて、レスポンスで HTTP ステータス コード、ステータス、理由を返します。また、レスポンスの本文にはエラーの原因の詳細な説明が含まれます。以下に、エラー レスポンスの例を示します。

{
 "error": {
  "code": 403,
  "message": "User does not have sufficient permissions for this profile.",
  "status": "PERMISSION_DENIED"
 }
}

エラーの表

コード ステータス 説明 推奨される対処方法
400 INVALID_ARGUMENT リクエストが無効です。必要な引数が欠落しているか、制限を超えているか、または無効な値が含まれている可能性があります。 詳細については、エラー メッセージを確認してください。クライアントが操作を再試行すると、このエラーで再び失敗します。
401 UNAUTHENTICATED クライアントが適切に認証されていません。 問題を解決してから再試行してください。新しい認証トークンを入手する必要があります。
403 PERMISSION_DENIED リクエストしたデータにアクセスできる権限がないことを示します。 問題を解決してから再試行してください。指定したエンティティに対する操作を行える権限を取得する必要があります。
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupCLIENT_PROJECT-1d プロジェクトごとの 1 日あたりのリクエスト数割り当てを使い切ったことを示します。 問題を解決してから再試行してください。1 日の割り当ての上限に達しました。
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupCLIENT_PROJECT-100s プロジェクトごとの 100 秒あたりのリクエスト数割り当てを使い切ったことを示します。 指数バックオフを使用して再試行します。リクエストの送信レートを下げる必要があります。
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupUSER-100s プロジェクトごとのユーザーあたりの 100 秒ごとのリクエスト数割り当てを使い切ったことを示します。 指数バックオフを使用して再試行します。リクエストの送信レートを下げる必要があります。
429 RESOURCE_EXHAUSTED DiscoveryGroupCLIENT_PROJECT-100s 100 秒あたりのディスカバリー リクエスト数割り当てを使い切ったことを示します。 検出レスポンスは頻繁には変更されません。検出レスポンスをローカルにキャッシュするか、指数バックオフを使用して再試行します。リクエストの送信レートを下げる必要があります。
500 INTERNAL 予期しない内部サーバーエラーが発生しました。 このクエリを 2 回以上再試行しないでください。
503 BACKEND_ERROR サーバーからエラーが返されました。 このクエリを 2 回以上再試行しないでください。
503 UNAVAILABLE サービスでリクエストを処理することができませんでした。 一時的な状態である可能性が最も高く、指数バックオフで再試行することで修正できる可能性があります。

指数バックオフの実装

指数バックオフは、失敗したリクエストをクライアントが再試行する際、失敗するごとに次の再試行までの待ち時間を増やしていく処理です。これは、ネットワーク アプリケーションに使われる標準的な エラー処理方法です。Reporting 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 は、待機するたびに再定義する必要があります。

: 待機時間は常に (2 ^ n) + random_number_milliseconds です。n は、最初は 0 として定義され、単調に増加する整数です。n は、反復(リクエストごとに)のたびに 1 ずつ増加します。

上記のアルゴリズムは、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."