API-Fehler verstehen

In diesem Leitfaden wird erläutert, wie Fehler in der Data Manager API behandelt und kommuniziert werden. Es ist wichtig, die Struktur und Bedeutung von API-Fehlern zu verstehen, um robuste Anwendungen zu entwickeln, die Probleme wie ungültige Eingaben oder vorübergehende Dienstausfälle problemlos bewältigen können.

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

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

Kanonische Fehlercodes

Die Data Manager API verwendet eine Reihe kanonischer Fehlercodes, 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 unter Fehler codes.

Fehler verarbeiten

Führen Sie die folgenden Schritte aus, wenn eine Anfrage fehlschlägt:

  1. Prüfen Sie den Fehlercode, um den Fehlertyp zu ermitteln.

    • Wenn Sie gRPC verwenden, befindet sich der Fehlercode im code Feld des Status. Wenn Sie eine Clientbibliothek verwenden, wird möglicherweise ein bestimmter Ausnahmetyp ausgelöst, 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. Prüfen Sie, ob die Standardnutzlast für Details für den Fehlercode vorhanden ist. Die Standardnutzlasten für Details sind eine Reihe von Nachrichten für Fehler von Google APIs. Sie enthalten Fehlerdetails auf strukturierte und konsistente Weise. Jeder Fehler der Data Manager API kann mehrere Standardnutzlasten für Details enthalten. Die Clientbibliotheken der Data Manager API enthalten Hilfsmethoden, um die Standardnutzlasten für Details aus einem Fehler abzurufen.

    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 Anfrage-ID, die hilfreich ist, wenn Sie sich an den Support wenden müssen.
    • Help und LocalizedMessage enthalten Links und andere Details, die Ihnen helfen, den Fehler zu beheben.

    Außerdem ist die Nutzlast BadRequest für INVALID_ARGUMENT-Fehler nützlich, da sie Informationen dazu enthält, welche Felder den Fehler verursacht haben.

Standardnutzlasten für Details

Die häufigsten Standardnutzlasten für Details für die Data Manager API sind:

BadRequest

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

Eine BadRequest-Nachricht zeigt an, dass die Anfrage Felder mit ungültigen Werten enthielt oder ein Wert für ein Pflichtfeld fehlte. Prüfen Sie die Liste field_violations in der BadRequest-Nutzlast, um herauszufinden, in welchen Feldern Fehler aufgetreten sind. Jeder Eintrag in field_violations enthält Informationen, die Ihnen helfen, den Fehler zu beheben:

field

Die Position des Felds in der Anfrage mit einer Pfadsyntax in Camel-Case-Schreibweise.

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

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

description

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

reason

Die ErrorReason-Enum, 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-Nachricht. Die field_violations zeigen, dass der Fehler in einer accountId liegt, die keine Zahl ist. Der Wert field destinations[0].login_account.account_id zeigt, dass sich die accountId mit einem Feldfehler im login_account des ersten Elements in der Liste destinations befindet.

{
  "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 ist eine weitere Beispielantwort für einen INVALID_ARGUMENT-Fehler mit einer BadRequest-Nachricht. In diesem Fall enthält die Liste field_violations zwei Fehler:

  1. Das erste event hat einen Wert, der nicht hexadezimal codiert ist, und zwar für die zweite Nutzer-ID des Ereignisses.

  2. Das zweite event hat einen Wert, der nicht hexadezimal codiert ist, und zwar für die dritte Nutzer-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 die RequestInfo Nutzlast, wenn eine Anfrage fehlschlägt. Eine 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 sich an den Support wenden, geben Sie die Anfrage-ID an, um die Diagnose von Problemen zu erleichtern.

ErrorInfo

Prüfen Sie die ErrorInfo Nachricht, um zusätzliche Informationen abzurufen, die möglicherweise nicht in den anderen Standardnutzlasten für Details erfasst werden. Die Nutzlast ErrorInfo enthält eine metadata-Map mit Informationen zum Fehler.

Hier sehen Sie beispielsweise die ErrorInfo für einen PERMISSION_DENIED-Fehler, der durch die Verwendung von Anmeldedaten für ein Google Cloud-Projekt verursacht wurde, in dem die Data Manager API nicht aktiviert ist. Die 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 aktiviert werden kann, unter 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.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

Prüfen Sie die Nutzlasten Help und LocalizedMessage, um Links zu Dokumentation und lokalisierte Fehlermeldungen zu erhalten, die Ihnen helfen, den Fehler zu verstehen und zu beheben.

Hier sehen Sie beispielsweise die Nutzlasten Help und LocalizedMessage für einen PERMISSION_DENIED-Fehler, der durch die Verwendung von Anmeldedaten für ein Google Cloud-Projekt verursacht wurde, in dem die Data Manager API nicht aktiviert ist. Die Nutzlast Help enthält die URL, unter der der Dienst aktiviert werden kann, und die Nutzlast 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"
          }
        ]
      },
      ...
    ]
  }
}

Fehlerdetails aufrufen

Wenn Sie eine der Clientbibliotheken verwenden, verwenden Sie die Hilfsmethoden, um die Standardnutzlasten für Details abzurufen.

.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

Implementieren Sie die folgenden Best Practices, um robuste Anwendungen zu entwickeln.

Fehlerdetails prüfen
Suchen Sie immer nach einer der Standardnutzlasten für Details wie BadRequest. Jede Standardnutzlast für Details enthält Informationen, die Ihnen helfen, die Ursache des Fehlers zu verstehen.
Zwischen Client- und Serverfehlern unterscheiden

Ermitteln Sie, 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. Diese erfordern Änderungen an der Anfrage oder am Status/den Anmeldedaten Ihrer Anwendung. 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

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

  • Wiederholen Sie die Anfrage nur bei vorübergehenden Serverfehlern wie UNAVAILABLE, DEADLINE_EXCEEDED, INTERNAL, UNKNOWN und ABORTED.
  • Verwenden Sie einen exponentiellen Backoff-Algorithmus, um die Wartezeiten zwischen den Wiederholungen zu verlängern. So vermeiden Sie, dass ein bereits überlasteter Dienst überfordert wird. Warten Sie beispielsweise 1 Sekunde, dann 2 Sekunden, dann 4 Sekunden usw., bis eine maximale Anzahl von Wiederholungen oder eine maximale Wartezeit erreicht ist.
  • Fügen Sie den Backoff-Verzögerungen eine kleine zufällige Menge „Jitter“ hinzu, um das „Thundering Herd“-Problem zu vermeiden, bei dem viele Clients gleichzeitig Wiederholungsversuche durchführen.
Gründlich protokollieren

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

Nutzerfeedback geben

Geben Sie den Nutzern Ihrer Anwendung anhand der Codes und Nachrichten in den Standardnutzlasten für Details klares und hilfreiches Feedback. Anstatt nur „Ein Fehler ist aufgetreten“ können Sie beispielsweise „Transaktions-ID fehlt“ oder „Die Konto-ID des Ziels wurde nicht gefunden“ angeben.

Wenn Sie diese Richtlinien befolgen, können Sie von der Data Manager API zurückgegebene Fehler effektiv diagnostizieren und beheben und so stabilere und benutzerfreundlichere Anwendungen entwickeln.