Ce guide explique comment l'API Data Manager gère et communique les erreurs. Il est essentiel de comprendre la structure et la signification des erreurs d'API pour créer des applications robustes capables de gérer correctement les problèmes, qu'il s'agisse d'entrées non valides ou d'une indisponibilité temporaire du service.
L'API Data Manager suit le modèle d'erreur standard des API Google, qui est basé
sur les codes d'état gRPC. Chaque réponse d'API qui génère une erreur inclut un objet Status avec les éléments suivants :
- Un code d'erreur numérique.
- Un message d'erreur.
- Des informations supplémentaires facultatives sur l'erreur.
Codes d'erreur canoniques
L'API Data Manager utilise un ensemble de codes d'erreur canoniques définis par gRPC et HTTP. Ces codes fournissent une indication générale du type d'erreur. Vous devez toujours vérifier ce code en premier pour comprendre la nature fondamentale du problème.
Pour en savoir plus sur ces codes, consultez le Guide de conception d'API – Codes d'erreur.
Gérer les erreurs
Procédez comme suit lorsqu'une requête échoue :
Vérifiez le code d'erreur pour identifier le type d'erreur.
- Si vous utilisez gRPC, le code d'erreur se trouve dans le
codechamp de laStatus. Si vous utilisez une bibliothèque cliente, elle peut générer un type d'exception spécifique correspondant au code d'erreur. Par exemple, la bibliothèque cliente pour Java génère une exceptioncom.google.api.gax.rpc.InvalidArgumentExceptionsi le code d'erreur estINVALID_ARGUMENT. - Si vous utilisez REST, le code d'erreur se trouve dans la réponse d'erreur à
error.status, et l'état HTTP correspondant se trouve àerror.code.
- Si vous utilisez gRPC, le code d'erreur se trouve dans le
Recherchez la charge utile de détail standard pour le code d'erreur. Les charges utiles de détail standards sont un ensemble de messages pour les erreurs provenant des API Google. Elles vous fournissent des informations détaillées sur les erreurs de manière structurée et cohérente. Chaque erreur de l'API Data Manager peut comporter plusieurs messages de charge utile de détail standards. Les bibliothèques clientes de l'API Data Manager disposent de méthodes d'assistance pour obtenir les charges utiles de détail standards à partir d'une erreur.
Quel que soit le code d'erreur, nous vous recommandons de vérifier et d'enregistrer les charges utiles
ErrorInfo,RequestInfo,Help, etLocalizedMessage.ErrorInfocontient des informations qui ne figurent peut-être pas dans d'autres charges utiles.RequestInfocontient l'ID de requête, ce qui est utile si vous devez contacter l'assistance.HelpetLocalizedMessagecontiennent des liens et d'autres informations pour vous aider à résoudre l'erreur.
De plus, la charge utile
BadRequestest utile pour les erreursINVALID_ARGUMENT, car elle fournit des informations sur les champs qui ont causé l'erreur.
Charges utiles de détail standards
Les charges utiles de détail standards les plus courantes pour l'API Data Manager sont les suivantes :
BadRequest
Recherchez la charge utile BadRequest lorsqu'une requête échoue avec
INVALID_ARGUMENT (code d'état HTTP 400).
Un message BadRequest indique que la requête comportait des champs avec des valeurs incorrectes ou qu'une valeur manquait pour un champ obligatoire. Consultez la liste field_violations dans BadRequest pour identifier les champs qui comportent des erreurs. Chaque entrée field_violations contient des informations pour vous aider à corriger l'erreur :
fieldEmplacement du champ dans la requête, à l'aide d'une syntaxe de chemin d'accès en camel case.
Si un chemin d'accès pointe vers un élément d'une liste (champ
repeated), son index s'affiche entre crochets ([...]) après le nom de la liste.Par exemple,
destinations[0].operating_account.account_idcorrespond auaccount_iddans leoperating_accountdu premier élément de la listedestinations.descriptionExplication de la raison pour laquelle la valeur a généré une erreur.
reasonÉnumération
ErrorReason, telle queINVALID_HEX_ENCODINGouINVALID_CURRENCY_CODE.
Exemples de BadRequest
Voici un exemple de réponse pour une erreur INVALID_ARGUMENT avec un message BadRequest. Les field_violations indiquent que l'erreur est un accountId qui n'est pas un nombre. La valeur field destinations[0].login_account.account_id indique que le
accountId avec une violation de champ se trouve dans le login_account du premier élément
de la liste 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"
}
]
}
]
}
}
Voici un autre exemple de réponse à une erreur INVALID_ARGUMENT avec un message BadRequest. Dans ce cas, la liste field_violations affiche deux erreurs :
La première
eventcomporte une valeur qui n'est pas encodée en hexadécimal sur le deuxième identifiant utilisateur de l'événement.La deuxième
eventcomporte une valeur qui n'est pas encodée en hexadécimal sur le troisième identifiant utilisateur de l'événement.
{
"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
Recherchez la RequestInfo charge utile chaque fois qu'une requête échoue. Un RequestInfo contient le request_id qui identifie de manière unique votre requête API.
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}
Lorsque vous enregistrez des erreurs ou contactez l'assistance, veillez à inclure l'ID de requête pour faciliter le diagnostic des problèmes.
ErrorInfo
Recherchez le message ErrorInfo pour récupérer des informations supplémentaires qui
ne sont peut-être pas capturées dans les autres charges utiles de détail standards. La charge utile ErrorInfo contient une carte metadata avec des informations sur l'erreur.
Voici, par exemple, l'ErrorInfo pour un échec PERMISSION_DENIED causé par l'utilisation d'identifiants pour un projet Google Cloud dans lequel l'API Data Manager n'est pas activée. L'ErrorInfo fournit des informations supplémentaires sur l'erreur, telles que :
- Le projet associé à la requête, sous
metadata.consumer. - Le nom du service, sous
metadata.serviceTitle. - L'URL où le service peut être activé, sous
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 et LocalizedMessage
Recherchez les charges utiles Help et LocalizedMessage pour obtenir des liens vers
la documentation et des messages d’erreur localisés qui vous aident à comprendre et à corriger l’
erreur.
Voici, par exemple, les charges utiles Help et LocalizedMessage pour un échec PERMISSION_DENIED causé par l'utilisation d'identifiants pour un projet Google Cloud dans lequel l'API Data Manager n'est pas activée. La charge utile Help affiche l'URL où le service peut être activé, et la charge utile LocalizedMessage contient une description de l'erreur.
{
"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"
}
]
},
...
]
}
}
Accéder aux détails des erreurs
Si vous utilisez l'une des bibliothèques clientes, utilisez les méthodes d'assistance pour obtenir les charges utiles de détail standards.
.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...
}
...
}
Bonnes pratiques pour la gestion des erreurs
Pour créer des applications résilientes, mettez en œuvre les bonnes pratiques suivantes.
- Inspecter les détails des erreurs
- Recherchez toujours l'une des charges utiles de détail standards, comme
BadRequest. Chaque charge utile de détail standard contient des informations pour vous aider à comprendre la cause de l'erreur. - Distinguer les erreurs client des erreurs serveur
Déterminez si l'erreur est due à un problème lié à votre implémentation (le client) ou à un problème lié à l'API (le serveur).
- Erreurs client : codes tels que
INVALID_ARGUMENT,NOT_FOUND,PERMISSION_DENIED,FAILED_PRECONDITION,UNAUTHENTICATED. Ces erreurs nécessitent des modifications de la requête ou de l'état/des identifiants de votre application. Ne relancez pas la requête sans résoudre le problème. - Erreurs serveur : codes tels que
UNAVAILABLE,INTERNAL,DEADLINE_EXCEEDED,UNKNOWN. Ces erreurs suggèrent un problème temporaire avec le service API.
- Erreurs client : codes tels que
- Mettre en œuvre une stratégie de nouvelles tentatives
Déterminez si l'erreur peut être relancée et utilisez une stratégie de nouvelles tentatives.
- Effectuez une nouvelle tentative uniquement en cas d'erreurs serveur temporaires telles que
UNAVAILABLE,DEADLINE_EXCEEDED,INTERNAL,UNKNOWNetABORTED. - Utilisez un algorithme d'intervalle exponentiel entre les tentatives pour attendre des périodes de plus en plus longues entre les tentatives. Cela permet d'éviter de surcharger un service déjà sollicité. Par exemple, attendez 1 seconde, puis 2 secondes, puis 4 secondes, et ainsi de suite jusqu'à atteindre un nombre maximal de tentatives ou un temps d'attente total.
- Ajoutez une petite quantité aléatoire de "gigue" aux délais d'intervalle entre les tentatives pour éviter le problème de "tonnerre de troupeau", où de nombreux clients effectuent une nouvelle tentative simultanément.
- Effectuez une nouvelle tentative uniquement en cas d'erreurs serveur temporaires telles que
- Enregistrer de manière approfondie
Enregistrez la réponse d'erreur complète, y compris toutes les charges utiles de détail standards, en particulier l'ID de requête. Ces informations sont essentielles pour le débogage et le signalement des problèmes à l'assistance Google si nécessaire.
- Fournir des commentaires aux utilisateurs
En fonction des codes et des messages des charges utiles de détail standards, fournissez des commentaires clairs et utiles aux utilisateurs de votre application. Par exemple, au lieu de simplement "Une erreur s'est produite", vous pouvez indiquer "L'ID de transaction est manquant" ou "L'ID de compte de la destination n'a pas été trouvé".
En suivant ces consignes, vous pouvez diagnostiquer et gérer efficacement les erreurs renvoyées par l'API Data Manager, ce qui vous permet de créer des applications plus stables et plus conviviales.