API-Fehler verstehen

In diesem Leitfaden wird beschrieben, wie die Data Manager API Fehler behandelt und kommuniziert. Die Struktur und Bedeutung von API-Fehlern zu verstehen, ist entscheidend für die Entwicklung robuster Anwendungen, die Probleme wie ungültige Eingaben oder vorübergehende Dienstausfälle problemlos bewältigen können.

Die Data Manager API folgt dem Standardfehlermodell von Google APIs, das auf gRPC-Statuscodes basiert. Jede API-Antwort, die zu einem Fehler führt, enthält ein Status-Objekt mit:

  • Ein numerischer Fehlercode.
  • Eine Fehlermeldung.
  • Optionale zusätzliche Fehlerdetails.

Kanonische Fehlercodes

Für die Data Manager API wird eine Reihe von kanonischen Fehlercodes verwendet, die von gRPC und HTTP definiert werden. Diese Codes geben einen allgemeinen Hinweis auf den Fehlertyp. Sie sollten diesen Code immer zuerst prüfen, um die grundlegende Art des Problems zu verstehen.

Weitere Informationen zu diesen Codes finden Sie im Leitfaden zum API-Design – Fehlercodes.

Fast-Fail-Modell

Die Data Manager API verwendet ein Fast-Fail-Modell. Wenn eine Anfrage Strukturfehler enthält oder ein Datensatz die Validierung für ein Pflichtfeld nicht besteht, schlägt die gesamte Anfrage fehl und die API verarbeitet keine der Daten in dieser Anfrage.

Das Fast-Fail-Modell unterscheidet sich von dem Modell für Teilausfälle in einigen anderen Google-APIs, z. B. der Google Ads API und der Campaign Manager 360 API. Im Modell mit Teilausfall ist eine Anfrage erfolgreich, auch wenn einige Datensätze Fehler enthalten. Die Antwort enthält Fehlerdetails für die fehlgeschlagenen Datensätze.

Ein teilweiser Fehler kann zwar praktisch sein, birgt aber erhebliche Risiken, da Sie beim Modell für teilweise Fehler nicht proaktiv auf Fehler aufmerksam gemacht werden. Sie müssen jede Antwort explizit auf Fehler prüfen. Dadurch können wichtige Probleme verschleiert werden, da eine Anfrage erfolgreich ist, auch wenn die API viele oder sogar alle Datensätze in der Anfrage ablehnt. Wenn ein erheblicher Teil der Datensätze in einer Anfrage Fehler enthält, Sie die Antwort aber nicht prüfen, bemerken Sie möglicherweise nicht, dass es weitverbreitete Probleme mit Ihren Daten gibt. Sie stellen diese Probleme erst Tage oder Wochen später fest, wenn die kumulativen Ergebnisse nicht Ihren Erwartungen entsprechen.

Mit dem Fast-Fail-Modell werden diese Probleme vermieden, da Sie sofort über Probleme mit Ihren Daten oder Ihrer Integration informiert werden und entsprechende Maßnahmen ergreifen können.

Fehler verarbeiten

Gehen Sie so vor, wenn eine Anfrage fehlschlägt:

  1. Sehen Sie sich den Fehlercode an, um den Fehlertyp zu ermitteln.

    • Wenn Sie gRPC verwenden, befindet sich der Fehlercode im Feld code des Status. Wenn Sie eine Clientbibliothek verwenden, wird möglicherweise ein bestimmter Ausnahmetyp ausgegeben, der dem Fehlercode entspricht. Die Clientbibliothek für Java löst beispielsweise eine com.google.api.gax.rpc.InvalidArgumentException aus, wenn der Fehlercode INVALID_ARGUMENT ist.
    • Wenn Sie REST verwenden, befindet sich der Fehlercode in der Fehlerantwort unter error.status und der entsprechende HTTP-Status unter error.code.
  2. Suchen Sie nach der Standard-Detailnutzlast für den Fehlercode. Die Standardnutzlasten für Details sind eine Reihe von Meldungen für Fehler von Google APIs. Sie enthalten Fehlerdetails in strukturierter und einheitlicher Form. Jeder Fehler aus der Data Manager API kann mehrere Standard-Detail-Nutzlastmeldungen haben. Die Data Manager API-Clientbibliotheken enthalten Hilfsmethoden, mit denen Sie die Standardnutzlasten für Fehlerdetails abrufen können.

    Unabhängig vom Fehlercode empfehlen wir, die Nutzlasten ErrorInfo, RequestInfo, Help und LocalizedMessage zu prüfen und zu protokollieren.

    • ErrorInfo enthält Informationen, die möglicherweise nicht in anderen Nutzlasten enthalten sind.
    • RequestInfo enthält die Anforderungs-ID, die hilfreich ist, wenn Sie den Support kontaktieren müssen.
    • Help und LocalizedMessage enthalten Links und andere Details, die Ihnen bei der Behebung des Fehlers helfen.

    Außerdem ist die BadRequest-Nutzlast bei INVALID_ARGUMENT-Fehlern hilfreich, da sie Informationen dazu enthält, welche Felder den Fehler verursacht haben.

Aufnahmewarnungen

Die Data Manager API akzeptiert so viel wie möglich von einer Erfassungsanfrage. Wenn Sie Daten angeben, die nicht erforderlich sind, führen Validierungsfehler für diese Felder nicht dazu, dass die Anfrage fehlschlägt. Wenn beispielsweise für einen Warenkorbartikel eine Händlerprodukt-ID fehlt, verarbeitet die API den Rest der Anfrage und gibt eine Warnung zurück.

Eine erfolgreiche Antwort auf die Aufnahme (HTTP-Statuscode 200) enthält diese Warnungen in einer field_warnings-Liste. Jeder Eintrag ist ein FieldWarning-Objekt mit den folgenden Feldern:

field

Die Position des Felds in der Anfrage in der Snake-Case-Pfadsyntax.

Wenn ein Pfad auf ein Element in einer Liste (ein repeated-Feld) verweist, wird sein Index in eckigen Klammern ([...]) nach dem Namen der Liste angezeigt.

Beispiel: events.events[0].cart_data.items[0].merchant_product_id gibt eine Warnung für den ersten Artikel in den Warenkorbdaten des ersten Ereignisses in der Anfrage an.

description

Eine Erklärung, warum der angegebene Wert eine Warnung ausgelöst hat.

reason

Der WarningReason-Enum-Wert, der den Warnungstyp angibt.

Beispiel mit FieldWarning

Hier ist eine Beispielantwort für eine erfolgreiche Erfassungsanfrage, die eine Warnung enthält, weil für einen der Warenkorbartikel eine Händlerprodukt-ID fehlt.

{
  "requestId": "126365e1-16d0-4c81-9de9-f362711e250a",
  "fieldWarnings": [
    {
      "field": "events.events[0].cart_data.items[0].merchant_product_id",
      "description": "The merchant product ID is missing in the cart item.",
      "reason": "WARNING_REASON_CART_DATA_ITEM_MERCHANT_PRODUCT_ID_MISSING"
    }
  ]
}

Standardnutzlasten für Details

Die häufigsten Standard-Detailnutzlasten für die Data Manager API sind:

BadRequest

Prüfen Sie, ob die Nutzlast BadRequest vorhanden ist, wenn eine Anfrage mit INVALID_ARGUMENT (HTTP-Statuscode 400) fehlschlägt.

Eine BadRequest-Meldung weist darauf hin, dass die Anfrage Felder mit ungültigen Werten enthielt oder ein Wert für ein erforderliches Feld fehlte. Sehen Sie sich die Liste field_violations im BadRequest an, um herauszufinden, in welchen Feldern Fehler auftreten. Jeder field_violations-Eintrag enthält Informationen, die Ihnen bei der Behebung des Fehlers helfen:

field

Die Position des Felds in der Anfrage in der Snake-Case-Pfadsyntax.

Wenn ein Pfad auf ein Element in einer Liste (ein repeated-Feld) verweist, wird sein Index in eckigen Klammern ([...]) nach dem Namen der Liste angezeigt.

destinations[0].operating_account.account_id ist beispielsweise die account_id im operating_account des ersten Elements in der Liste destinations.

description

Eine Erklärung, warum der Wert einen Fehler verursacht hat.

reason

Die ErrorReason-Enumeration, z. B. INVALID_HEX_ENCODING oder INVALID_CURRENCY_CODE.

Beispiele für BadRequest

Hier sehen Sie eine Beispielantwort für einen INVALID_ARGUMENT-Fehler mit einer BadRequest-Meldung. Die field_violations zeigen, dass der Fehler ein accountId ist, das keine Zahl ist. Der field-Wert destinations[0].login_account.account_id gibt an, dass die accountId mit einem Feldverstoß im login_account des ersten Elements in der destinations-Liste enthalten ist.

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

Hier sehen Sie ein weiteres Beispiel für eine Antwort auf einen INVALID_ARGUMENT-Fehler mit einer BadRequest-Nachricht. In diesem Fall enthält die Liste field_violations zwei Fehler:

  1. Die erste event hat einen Wert, der nicht hexadezimal codiert ist, und zwar in der zweiten Nutzer-ID des Ereignisses.

  2. Die zweite event hat einen Wert, der nicht hexadezimal codiert ist, für die dritte User-ID des Ereignisses.

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

RequestInfo

Prüfen Sie bei einem Fehler in einer Anfrage, ob die RequestInfo-Nutzlast vorhanden ist. Ein RequestInfo enthält die request_id, die Ihre API-Anfrage eindeutig identifiziert.

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

Wenn Sie Fehler protokollieren oder den Support kontaktieren, geben Sie unbedingt die Anfrage-ID an, damit Probleme leichter diagnostiziert werden können.

ErrorInfo

Suchen Sie nach der Meldung ErrorInfo, um zusätzliche Informationen abzurufen, die möglicherweise nicht in den anderen Standard-Detail-Payloads enthalten sind. Die ErrorInfo-Nutzlast enthält eine metadata-Karte mit Informationen zum Fehler.

Hier ist beispielsweise der ErrorInfo für einen PERMISSION_DENIED-Fehler, der durch die Verwendung von Anmeldedaten für ein Google Cloud-Projekt verursacht wird, in dem die Data Manager API nicht aktiviert ist. Der ErrorInfo enthält zusätzliche Informationen zum Fehler, z. B.:

  • Das mit der Anfrage verknüpfte Projekt unter metadata.consumer.
  • Der Name des Dienstes unter metadata.serviceTitle.
  • Die URL, unter der der Dienst unter metadata.activationUrl aktiviert werden kann.
{
  "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.cloud.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.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
        }
      },
      ...
    ]
  }
}

Help und LocalizedMessage

In den Nutzlasten Help und LocalizedMessage finden Sie Links zur Dokumentation und lokalisierte Fehlermeldungen, die Ihnen helfen, den Fehler zu verstehen und zu beheben.

Hier sind beispielsweise die Help und LocalizedMessage für einen PERMISSION_DENIED-Fehler, der durch die Verwendung von Anmeldedaten für ein Google Cloud-Projekt verursacht wird, in dem die Data Manager API nicht aktiviert ist. Die Help-Nutzlast enthält die URL, unter der der Dienst aktiviert werden kann, und die LocalizedMessage enthält eine Beschreibung des Fehlers.

{
  "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.cloud.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.cloud.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 API Console API activation",
            "url": "https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
          }
        ]
      },
      ...
    ]
  }
}

Auf Fehlerdetails zugreifen

Wenn Sie eine der Clientbibliotheken verwenden, können Sie die Standard-Detailnutzlasten mit den Hilfsmethoden abrufen.

.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.ErrorInfo)
        {
            Google.Rpc.ErrorInfo errorInfo = (Google.Rpc.ErrorInfo)detail;
            // Log the errorInfo.Reason and errorInfo.Metadata...

            // Log the details in the 'Metadata' map...
            foreach (
                KeyValuePair<String, String> metadataEntry in errorInfo.Metadata
            )
            {
                // Log the metadataEntry.Key and metadataEntry.Value...
            }
        }
        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.ApiException apiException) {
  // Fallback exception handler for other types of ApiException.

  // Gets the standard ErrorInfo payload from the exception.
  ErrorInfo errorInfo = apiException.getErrorDetails().getErrorInfo();
  // Log the 'reason' and 'domain'...

  // Log the details in the 'metadata' map...
  for (Entry<String, String> metadataEntry : errorInfo.getMetadataMap().entrySet()) {
    // Log the metadataEntry key and value...
  }

  // Gets the standard RequestInfo payload from the exception.
  RequestInfo requestInfo = invalidArgumentException.getErrorDetails().getRequestInfo();
  if (requestInfo != null) {
    String requestId = requestInfo.getRequestId();
    // Log the requestId...
  }
  ...
}

Best Practices für die Fehlerbehandlung

Wenn Sie robuste Anwendungen entwickeln möchten, sollten Sie die folgenden Best Practices umsetzen.

Fehlerdetails ansehen
Suchen Sie immer nach einer der Standard-Detailnutzlasten wie BadRequest. Jede Nutzlast mit Standarddetails enthält Informationen, die Ihnen helfen, die Ursache des Fehlers zu verstehen.
Client- und Serverfehler unterscheiden

Stellen Sie fest, ob der Fehler durch ein Problem mit Ihrer Implementierung (dem Client) oder mit der API (dem Server) verursacht wird.

  • Clientfehler: Codes wie INVALID_ARGUMENT, NOT_FOUND, PERMISSION_DENIED, FAILED_PRECONDITION, UNAUTHENTICATED. Dafür sind Änderungen am Antrag oder am Status/den Anmeldedaten Ihrer Anwendung erforderlich. Wiederholen Sie die Anfrage nicht, ohne das Problem zu beheben.
  • Serverfehler: Codes wie UNAVAILABLE, INTERNAL, DEADLINE_EXCEEDED, UNKNOWN. Diese deuten auf ein vorübergehendes Problem mit dem API-Dienst hin.
Wiederholungsstrategie implementieren

Stellen Sie fest, ob der Fehler wiederholt werden kann, und verwenden Sie eine Wiederholungsstrategie.

  • Wiederholen Sie den Vorgang nur bei vorübergehenden Serverfehlern wie UNAVAILABLE, DEADLINE_EXCEEDED, INTERNAL, UNKNOWN und ABORTED.
  • Verwenden Sie einen exponentiellen Backoff-Algorithmus, um zwischen Wiederholungsversuchen immer länger zu warten. So wird verhindert, dass ein bereits überlasteter Dienst überfordert wird. Warten Sie beispielsweise 1 Sekunde, dann 2 Sekunden, dann 4 Sekunden usw. bis zur maximalen Anzahl von Wiederholungen oder der maximalen Wartezeit.
  • Fügen Sie den Backoff-Verzögerungen eine kleine zufällige Menge an „Jitter“ hinzu, um das „Thundering-Herd-Problem“ zu vermeiden, bei dem viele Clients gleichzeitig Wiederholungsversuche starten.
Gründlich protokollieren

Protokollieren Sie die vollständige Fehlerantwort, einschließlich aller Standardnutzlasten mit Details, insbesondere der Anfrage-ID. Diese Informationen sind wichtig für die Fehlerbehebung und, falls erforderlich, für die Meldung von Problemen an den Google-Support.

Nutzerfeedback geben

Geben Sie den Nutzern Ihrer Anwendung anhand der Codes und Nachrichten in den Standard-Detail-Nutzlasten klares und hilfreiches Feedback. Sagen Sie beispielsweise anstelle von „Es ist ein Fehler aufgetreten“ lieber „Die Transaktions-ID fehlt“ oder „Die Konto-ID des Ziels wurde nicht gefunden“.

Wenn Sie diese Richtlinien befolgen, können Sie Fehler, die von der Data Manager API zurückgegeben werden, effektiv diagnostizieren und beheben. So erhalten Sie stabilere und benutzerfreundlichere Anwendungen.