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:
Sprawdź kod błędu, aby dowiedzieć się, jaki to typ błędu.
- Jeśli używasz gRPC, kod błędu znajduje się w polu
codewStatus. 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ątekcom.google.api.gax.rpc.InvalidArgumentException, jeśli kod błędu toINVALID_ARGUMENT. - Jeśli używasz REST, kod błędu znajduje się w odpowiedzi na błąd w
error.status, a odpowiedni stan HTTP werror.code.
- Jeśli używasz gRPC, kod błędu znajduje się w polu
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,HelpiLocalizedMessage.ErrorInfozawiera informacje, których może nie być w innych ładunkach.RequestInfozawiera identyfikator żądania, który jest przydatny, jeśli chcesz skontaktować się z zespołem pomocy.HelpiLocalizedMessagezawierają linki i inne szczegóły, które pomogą Ci rozwiązać problem.
Dodatkowo ładunki
BadRequest,QuotaFailureiRetryInfosą przydatne w przypadku określonych kodów błędów:- Jeśli kod stanu to
INVALID_ARGUMENT, sprawdź ładunekBadRequest, aby dowiedzieć się, które pola spowodowały błąd. - Jeśli kod stanu to
RESOURCE_EXHAUSTED, sprawdź ładunkiQuotaFailureiRetryInfopod 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_violations w BadRequest, 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:
fieldLokalizacja 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_idtoaccount_idwoperating_accountpierwszego elementu na liściedestinations.descriptionWyjaśnienie, dlaczego wartość spowodowała błąd.
reasonWyliczenie
ErrorReason, np.INVALID_HEX_ENCODINGlubINVALID_CURRENCY_CODE.
Przykłady: BadRequest
Oto przykładowa odpowiedź na błąd INVALID_ARGUMENT z BadRequest
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:
Pierwszy znak
eventma wartość, która nie jest zakodowana w formacie szesnastkowym w drugim identyfikatorze użytkownika zdarzenia.Drugi znak
eventma 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"
}
]
}
]
}
}
QuotaFailure i RetryInfo
Sprawdź ładunki QuotaFailure i RetryInfo, 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"
}
},
...
]
}
}
Help i LocalizedMessage
Sprawdź ładunki Help i LocalizedMessage, 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 Help i LocalizedMessage 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.
- Błędy klienta: kody takie jak
- 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,UNKNOWNiABORTED. - 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.
- Ponów próbę tylko w przypadku przejściowych błędów serwera, takich jak
- 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.