Risposte di errore

Risposte di errore standard

Se una richiesta dell'API di reporting ha esito positivo, l'API restituisce un 200. Se si verifica un errore con una richiesta, l'API restituisce un codice di stato HTTP, lo stato e il motivo della risposta in base al tipo di errore. Inoltre, il corpo della risposta contiene una descrizione dettagliata di ciò che ha causato l'errore. Ecco un esempio di risposta di errore:

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

Tabella degli errori

Codice Stato Descrizione Azione consigliata
400 INVALID_ARGUMENT La richiesta non è valida. Un argomento richiesto potrebbe mancare, superare i limiti o presentare un valore non valido. Esamina il messaggio di errore per i dettagli. Questo errore non riuscirà di nuovo se il client proverà di nuovo a risolverlo.
401 UNAUTHENTICATED Il client non è autenticato correttamente. Non riprovare senza risolvere il problema. Devi ottenere un nuovo token di autenticazione.
403 PERMISSION_DENIED Indica la richiesta di dati a cui l'utente non ha accesso. Non riprovare senza risolvere il problema. Devi ottenere autorizzazioni sufficienti per eseguire l'operazione sull'entità specificata.
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupCLIENT_PROJECT-1d Indica che sono state esaurite le richieste al giorno per quota di progetto. Non riprovare senza risolvere il problema. Hai esaurito la quota giornaliera.
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupCLIENT_PROJECT-100s Indica che la quota di richieste per 100 secondi per progetto è stata esaurita. Riprova utilizzando il backoff esponenziale. Devi rallentare la frequenza con cui invii le richieste.
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupUSER-100s Indica che è stata esaurita la quota di richieste per 100 secondi per utente per progetto. Riprova utilizzando il backoff esponenziale. Devi rallentare la frequenza con cui invii le richieste.
429 RESOURCE_EXHAUSTED DiscoveryGroupCLIENT_PROJECT-100s Indica che la quota di richieste per 100 secondi di rilevamento è stata esaurita. La risposta del rilevamento non cambia di frequente; memorizza nella cache la risposta del rilevamento localmente oppure riprova utilizzando il backoff esponenziale. Devi rallentare la frequenza con cui invii le richieste.
500 INTERNAL Si è verificato un errore interno imprevisto del server. Non riprovare questa query più di una volta.
503 BACKEND_ERROR Il server ha restituito un errore. Non riprovare questa query più di una volta.
503 UNAVAILABLE Il servizio non è riuscito a elaborare la richiesta. Molto probabilmente si tratta di una condizione temporanea che può essere corretta eseguendo un nuovo tentativo con un backoff esponenziale.

Implementazione del backoff esponenziale

Il backoff esponenziale è il processo con cui un client proverà periodicamente a inviare una richiesta non riuscita in un periodo di tempo crescente. È una strategia standard di gestione degli errori per le applicazioni di rete. L'API di reporting è progettata in modo che i client che scelgono di riprovare le richieste non riuscite lo facciano utilizzando il backoff esponenziale. Oltre a essere "obbligatorio", il backoff esponenziale aumenta l'efficienza dell'utilizzo della larghezza di banda, riduce il numero di richieste necessarie per ottenere una risposta positiva e massimizza la velocità effettiva delle richieste in ambienti simultanei.

Il flusso per l'implementazione del backoff esponenziale semplice è il seguente.

  1. Effettua una richiesta all'API
  2. Ricevi una risposta di errore con un codice di errore che è possibile riprovare
  3. Attendi 1 s + random_number_milliseconds secondi
  4. Riprova richiesta
  5. Ricevi una risposta di errore con un codice di errore che è possibile riprovare
  6. Attendi 2 s + random_number_milliseconds secondi
  7. Riprova richiesta
  8. Ricevi una risposta di errore con un codice di errore che è possibile riprovare
  9. Attendi 4 s + random_number_milliseconds secondi
  10. Riprova richiesta
  11. Ricevi una risposta di errore con un codice di errore che è possibile riprovare
  12. Attendi 8 s + random_number_milliseconds secondi
  13. Riprova richiesta
  14. Ricevi una risposta di errore con un codice di errore che è possibile riprovare
  15. Attendi 16 s + random_number_milliseconds secondi
  16. Riprova richiesta
  17. Se continui a ricevere un errore, interrompi e registra l'errore.

Nel flusso precedente, random_number_milliseconds è un numero casuale di millisecondi inferiore o uguale a 1000. Questa operazione è necessaria per evitare determinati errori di blocco in alcune implementazioni simultanee. random_number_milliseconds deve essere ridefinito dopo ogni attesa.

Nota: l'attesa è sempre (2 ^ n) + random_number_milliseconds, dove n è un numero intero monotonico che aumenta inizialmente, definito inizialmente come 0. n viene incrementato di 1 per ogni iterazione (ogni richiesta).

L'algoritmo è impostato per terminare quando n è 5. Questo limite è stato stabilito solo per impedire ai client di riprovare all'infinito e determina un ritardo totale di circa 32 secondi prima che una richiesta venga considerata "un errore irreversibile".

Il seguente codice Python è un'implementazione del flusso riportato sopra per il ripristino dagli errori che si verificano in un metodo chiamato 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."