Informacje o błędach interfejsu API

Z tego przewodnika dowiesz się, jak interfejs Data Manager API obsługuje błędy i jak o nich informuje. Zrozumienie struktury i znaczenia błędów interfejsu API jest kluczowe do tworzenia niezawodnych aplikacji, które mogą sobie poradzić z problemami, od nieprawidłowych danych wejściowych po tymczasową niedostępność usługi.

Interfejs Data Manager API jest zgodny ze standardowym modelem błędów interfejsów API Google, który jest oparty na kodach stanu gRPC. Każda odpowiedź interfejsu API, która powoduje błąd, zawiera obiekt Status z tymi informacjami:

  • Kod błędu w postaci liczby.
  • komunikat o błędzie,
  • Opcjonalne dodatkowe szczegóły błędu.

Kody błędów kanonicznych

Interfejs Data Manager API używa zestawu kanonicznych kodów błędów zdefiniowanych przez gRPC i HTTP. Kody te wskazują ogólny typ błędu. Zawsze najpierw sprawdzaj ten kod, aby zrozumieć podstawową naturę problemu.

Więcej informacji o tych kodach znajdziesz w przewodniku API Design Guide – kody błędów.

Obsługuj błędy

Jeśli żądanie się nie powiedzie, wykonaj te czynności:

  1. Sprawdź kod błędu, aby dowiedzieć się, jaki to typ błędu.

    • Jeśli używasz gRPC, kod błędu znajduje się w polu codeStatus. Jeśli używasz biblioteki klienta, może ona zgłosić określony typ wyjątku odpowiadający kodowi błędu. Na przykład biblioteka klienta Java zgłasza wyjątek com.google.api.gax.rpc.InvalidArgumentException, jeśli kod błędu to INVALID_ARGUMENT.
    • Jeśli używasz REST, kod błędu znajduje się w odpowiedzi na błąd w error.status, a odpowiedni stan HTTP w error.code.
  2. Sprawdź standardowy ładunek szczegółowy pod kątem kodu błędu. Standardowe ładunki szczegółowe to zestaw komunikatów o błędach z interfejsów API Google. Zawierają one szczegółowe informacje o błędach w uporządkowany i spójny sposób. Każdy błąd interfejsu Data Manager API może zawierać wiele standardowych komunikatów z ładunkiem szczegółów. Biblioteki klienta interfejsu Data Manager API mają metody pomocnicze, które umożliwiają pobieranie standardowych ładunków szczegółów z błędu.

    Niezależnie od kodu błędu zalecamy sprawdzenie i zarejestrowanie ładunków ErrorInfo, RequestInfo, HelpLocalizedMessage.

    • ErrorInfo zawiera informacje, których może nie być w innych ładunkach.
    • RequestInfo zawiera identyfikator żądania, który jest przydatny, jeśli chcesz skontaktować się z zespołem pomocy.
    • HelpLocalizedMessage zawierają linki i inne szczegóły, które pomogą Ci rozwiązać problem.

    Dodatkowo ładunki BadRequest, QuotaFailureRetryInfo są przydatne w przypadku określonych kodów błędów:

    • Jeśli kod stanu to INVALID_ARGUMENT, sprawdź ładunek BadRequest, aby dowiedzieć się, które pola spowodowały błąd.
    • Jeśli kod stanu to RESOURCE_EXHAUSTED, sprawdź ładunki QuotaFailureRetryInfo pod kątem informacji o limicie i rekomendacji dotyczącej opóźnienia ponownej próby.

Standardowe ładunki szczegółowe

Najczęstsze standardowe ładunki szczegółów w przypadku interfejsu Data Manager API to:

BadRequest

Sprawdź ładunek BadRequest, gdy żądanie zakończy się niepowodzeniem z błędem INVALID_ARGUMENT (kod stanu HTTP 400).

Komunikat BadRequest oznacza, że żądanie zawierało pola z nieprawidłowymi wartościami lub brakowało w nim wartości w polu wymaganym. Sprawdź listę field_violationsBadRequest, aby dowiedzieć się, w których polach występują błędy. Każdy wpis field_violations zawiera informacje, które pomogą Ci naprawić błąd:

field

Lokalizacja pola w żądaniu, w składni ścieżki camel case.

Jeśli ścieżka wskazuje element na liście (pole repeated), jego indeks jest wyświetlany w nawiasach kwadratowych ([...]) po nazwie listy.

Na przykład destinations[0].operating_account.account_id to account_id w operating_account pierwszego elementu na liście destinations.

description

Wyjaśnienie, dlaczego wartość spowodowała błąd.

reason

Wyliczenie ErrorReason, np. INVALID_HEX_ENCODING lub INVALID_CURRENCY_CODE.

Przykłady: BadRequest

Oto przykładowa odpowiedź na błąd INVALID_ARGUMENTBadRequest komunikatem. W field_violations występuje błąd, ponieważ accountId nie jest liczbą. Wartość fielddestinations[0].login_account.account_id wskazuje, że accountId z naruszeniem pola znajduje się w login_account pierwszego elementu na liście destinations.

{
  "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"
          }
        ]
      }
    ]
  }
}

Oto kolejna przykładowa odpowiedź z błędem INVALID_ARGUMENT i komunikatem BadRequest. W takim przypadku na liście field_violations pojawią się 2 błędy:

  1. Pierwszy znak event ma wartość, która nie jest zakodowana w formacie szesnastkowym w drugim identyfikatorze użytkownika zdarzenia.

  2. Drugi znak event ma wartość, która nie jest zakodowana w formacie szesnastkowym w trzecim identyfikatorze użytkownika zdarzenia.

{
  "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"
          }
        ]
      }
    ]
  }
}

QuotaFailureRetryInfo

Sprawdź ładunki QuotaFailureRetryInfo, gdy żądanie zakończy się niepowodzeniem z błędem RESOURCE_EXHAUSTED (kod stanu HTTP 429).

Komunikat QuotaFailure oznacza, że zasób został wyczerpany (np. przekroczono limit) lub system jest przeciążony. Sprawdź listę violations, aby ustalić, które limity zostały przekroczone.

Błąd może też zawierać komunikat RetryInfo, który wskazuje zalecany retry_delay do ponowienia próby wysłania żądania.

RequestInfo

Gdy żądanie się nie powiedzie, sprawdź ładunek RequestInfo. Element RequestInfo zawiera request_id, który jednoznacznie identyfikuje żądanie do interfejsu API.

{
  "@type": "type.googleapis.com/google.rpc.RequestInfo",
  "requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}

Podczas rejestrowania błędów lub kontaktowania się z zespołem pomocy pamiętaj, aby podać identyfikator żądania, co ułatwi diagnozowanie problemów.

ErrorInfo

Sprawdź komunikat ErrorInfo, aby uzyskać dodatkowe informacje, które mogą nie być uwzględnione w innych standardowych ładunkach szczegółowych. Ładunek ErrorInfo zawiera mapę metadata z informacjami o błędzie.

Oto np. ErrorInfo w przypadku PERMISSION_DENIED błędu spowodowanego użyciem danych logowania do projektu Google Cloud, w którym interfejs Data Manager API nie jest włączony. ErrorInfo zawiera dodatkowe informacje o błędzie, takie jak:

  • Projekt powiązany z żądaniem w ramach metadata.consumer.
  • Nazwa usługi w sekcji metadata.serviceTitle.
  • Adres URL, pod którym można włączyć usługę, w sekcji metadata.activationUrl.
{
  "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"
        }
      },
      ...
    ]
  }
}

HelpLocalizedMessage

Sprawdź ładunki HelpLocalizedMessage, aby uzyskać linki do dokumentacji i zlokalizowanych komunikatów o błędach, które pomogą Ci zrozumieć i naprawić błąd.

Oto na przykład kody HelpLocalizedMessage w przypadku PERMISSION_DENIEDbłędu spowodowanego użyciem danych logowania do projektu Google Cloud, w którym interfejs Data Manager API nie jest włączony. Ładunek Help zawiera adres URL, pod którym można włączyć usługę, a LocalizedMessage zawiera opis błędu.

{
  "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"
          }
        ]
      },
      ...
    ]
  }
}

Szczegóły błędu dostępu

Jeśli używasz jednej z bibliotek klienta, użyj metod pomocniczych, aby uzyskać standardowe ładunki szczegółów.

.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.
  ...
}

Sprawdzone metody obsługi błędów

Aby tworzyć odporne aplikacje, stosuj te sprawdzone metody.

Sprawdzanie szczegółów błędu
Zawsze szukaj jednego ze standardowych ładunków szczegółowych, np. BadRequest. Każdy standardowy pakiet danych szczegółowych zawiera informacje, które pomogą Ci zrozumieć przyczynę błędu.
Odróżnianie błędów klienta od błędów serwera

Sprawdź, czy błąd jest spowodowany problemem z implementacją (klientem) czy z interfejsem API (serwerem).

  • Błędy klienta: kody takie jak INVALID_ARGUMENT, NOT_FOUND, PERMISSION_DENIED, FAILED_PRECONDITION, UNAUTHENTICATED. Wymagają one zmian w żądaniu lub w stanie/danych logowania aplikacji. Nie ponawiaj żądania bez rozwiązania problemu.
  • Błędy serwera: kody takie jak UNAVAILABLE, INTERNAL, DEADLINE_EXCEEDED, UNKNOWN. Wskazują one na tymczasowy problem z usługą API.
Wdrażanie strategii ponawiania

Sprawdź, czy można ponowić próbę wykonania działania, i zastosuj strategię ponawiania.

  • Ponów próbę tylko w przypadku przejściowych błędów serwera, takich jak UNAVAILABLE, DEADLINE_EXCEEDED, INTERNAL, UNKNOWNABORTED.
  • Używaj algorytmu wzrastającego czasu do ponowienia, aby czekać coraz dłużej między ponownymi próbami. Pomaga to uniknąć przeciążenia już i tak obciążonej usługi. Na przykład odczekaj 1 sekundę, potem 2 sekundy, a następnie 4 sekundy, aż osiągniesz maksymalną liczbę ponownych prób lub łączny czas oczekiwania.
  • Dodaj niewielką losową wartość „jitter” do opóźnień wycofywania, aby zapobiec problemowi „thundering herd”, w którym wielu klientów ponawia próbę jednocześnie.
Dokładne rejestrowanie

Zapisz pełną odpowiedź o błędzie, w tym wszystkie standardowe ładunki szczegółowe, a zwłaszcza identyfikator żądania. Te informacje są niezbędne do debugowania i zgłaszania problemów zespołowi pomocy Google w razie potrzeby.

Przesyłanie opinii użytkownika

Na podstawie kodów i wiadomości w standardowych ładunkach szczegółowych przekazuj użytkownikom aplikacji jasne i przydatne informacje zwrotne. Na przykład zamiast „Wystąpił błąd” możesz powiedzieć „Brak identyfikatora transakcji” lub „Nie znaleziono identyfikatora konta docelowego”.

Przestrzegając tych wytycznych, możesz skutecznie diagnozować i obsługiwać błędy zwracane przez interfejs Data Manager API, co pozwoli Ci tworzyć bardziej stabilne i przyjazne dla użytkownika aplikacje.