במדריך הזה מוסבר איך Data Manager API מטפל בשגיאות ואיך הוא מעביר אותן. הבנה של המבנה והמשמעות של שגיאות ב-API היא חיונית לבניית אפליקציות חזקות שיכולות לטפל בבעיות בצורה חלקה, החל מקלט לא תקין ועד לזמינות זמנית של השירות.
Data Manager API פועל לפי מודל השגיאות הרגיל של Google API, שמבוסס על קודי סטטוס של gRPC. כל תגובה מה-API שמובילה לשגיאה כוללת אובייקט Status עם:
- קוד שגיאה מספרי.
- הודעת שגיאה.
- פרטי שגיאה נוספים (אופציונלי).
קודי שגיאה קנוניים
ה-Data Manager API משתמש בקבוצה של קודי שגיאה קנוניים שמוגדרים על ידי gRPC ו-HTTP. הקודים האלה מציינים באופן כללי את סוג השגיאה. תמיד כדאי לבדוק קודם את הקוד הזה כדי להבין את המהות של הבעיה.
פרטים נוספים על הקודים האלה זמינים במאמר מדריך לעיצוב API – קודי שגיאה.
טיפול בשגיאות
אם בקשה נכשלת, צריך לבצע את הפעולות הבאות:
כדי לגלות את סוג השגיאה, בודקים את קוד השגיאה.
- אם משתמשים ב-gRPC, קוד השגיאה נמצא בשדה
codeשלStatus. אם משתמשים בספריית לקוח, יכול להיות שהיא תזרוק סוג ספציפי של חריגה שמתאים לקוד השגיאה. לדוגמה, ספריית הלקוח ל-Java יוצרתcom.google.api.gax.rpc.InvalidArgumentExceptionאם קוד השגיאה הואINVALID_ARGUMENT. - אם משתמשים ב-REST, קוד השגיאה נמצא בתגובת השגיאה ב-
error.status, וסטטוס ה-HTTP המתאים נמצא ב-error.code.
- אם משתמשים ב-gRPC, קוד השגיאה נמצא בשדה
בודקים את מטען הייעודי הסטנדרטי של הפרטים כדי למצוא את קוד השגיאה. מטעני הנתונים של הפרטים הרגילים הם קבוצה של הודעות שגיאה מ-Google APIs. הם מספקים פרטים על השגיאות בצורה מובנית ועקבית. כל שגיאה מ-Data Manager API עשויה לכלול כמה הודעות מטען ייעודי (payload) עם פרטים רגילים. בספריות הלקוח של Data Manager API יש שיטות עזר לקבלת מטען הייעודי (payload) של פרטים רגילים משגיאה.
לא משנה מה קוד השגיאה, מומלץ לבדוק ולתעד את מטען הנתונים (payload) של
ErrorInfo,RequestInfo,Helpו-LocalizedMessage.-
ErrorInfoמכיל מידע שאולי לא מופיע במטען ייעודי אחר. RequestInfoמכיל את מזהה הבקשה, שיכול לעזור לכם אם תצטרכו לפנות לתמיכה.-
Helpו-LocalizedMessageמכילים קישורים ופרטים אחרים שיעזרו לכם לפתור את השגיאה.
בנוסף, מטען הנתונים
BadRequestשימושי לשגיאותINVALID_ARGUMENTכי הוא מספק מידע על השדות שגרמו לשגיאה.-
מטען ייעודי (payload) של פרטים רגילים
אלה הם המטענים הייעודיים (payloads) הנפוצים ביותר של פרטים רגילים ב-Data Manager API:
BadRequest
בודקים את המטען הייעודי (payload) של BadRequest אם בקשה נכשלת עם INVALID_ARGUMENT (קוד סטטוס HTTP 400).
ההודעה BadRequest מציינת שבבקשה היו שדות עם ערכים לא תקינים, או שחסר ערך בשדה חובה. בודקים את field_violations הרשימה בBadRequest כדי לראות באילו שדות יש שגיאות. כל field_violations רשומה
כוללת מידע שיעזור לכם לתקן את השגיאה:
fieldהמיקום של השדה בבקשה, באמצעות תחביר של נתיב ב-camel case.
אם נתיב מצביע על פריט ברשימה (שדה
repeated), האינדקס שלו מוצג בסוגריים מרובעים ([...]) אחרי שם הרשימה.לדוגמה,
destinations[0].operating_account.account_idהואaccount_idב-operating_accountשל הפריט הראשון ברשימהdestinations.descriptionהסבר למה הערך גרם לשגיאה.
reasonהסוג enum
ErrorReason, לדוגמהINVALID_HEX_ENCODINGאוINVALID_CURRENCY_CODE.
דוגמאות של BadRequest
זוהי דוגמה לתשובה לשגיאה INVALID_ARGUMENT עם הודעה BadRequest
השגיאה field_violations מוצגת כי accountId הוא לא מספר. הערך field destinations[0].login_account.account_id מציג את accountId עם הפרה של כלל בשדה login_account של הפריט הראשון ברשימה 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"
}
]
}
]
}
}
דוגמה נוספת לתגובה משגיאת INVALID_ARGUMENT עם הודעה BadRequest. במקרה הזה, ברשימה field_violations מוצגות שתי שגיאות:
ל-
eventהראשון יש ערך שלא מקודד בפורמט הקסדצימלי במזהה המשתמש השני של האירוע.ל-
eventהשני יש ערך שלא מקודד בפורמט הקסדצימלי במזהה המשתמש השלישי של האירוע.
{
"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
בכל פעם שבקשה נכשלת, בודקים את מטען הנתונים RequestInfo. RequestInfo
מכיל את request_id שמזהה באופן ייחודי את בקשת ה-API.
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}
כשמתעדים שגיאות או פונים לתמיכה, חשוב לכלול את מזהה הבקשה כדי לעזור באבחון בעיות.
ErrorInfo
כדי לאחזר מידע נוסף שאולי לא נכלל במטענים הייעודיים (payloads) האחרים של הפרטים הרגילים, צריך לחפש את ההודעה ErrorInfo. המטען הייעודי (payload) מכיל מפה metadata עם מידע על השגיאה.ErrorInfo
לדוגמה, כאן מופיע ErrorInfo של כשל PERMISSION_DENIED שנגרם בגלל שימוש בפרטי כניסה לפרויקט ב-Google Cloud שבו Data Manager API לא מופעל. בErrorInfo מופיע מידע נוסף על השגיאה, כמו:
- הפרויקט שמשויך לבקשה, בקטע
metadata.consumer. - שם השירות, בקטע
metadata.serviceTitle. - כתובת ה-URL שבה אפשר להפעיל את השירות, בקטע
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 וגם LocalizedMessage
בודקים את מטען הנתונים Help ו-LocalizedMessage כדי לקבל קישורים למסמכים ולהודעות שגיאה בשפה המקומית שיעזרו לכם להבין את השגיאה ולתקן אותה.
לדוגמה, הנה Help ו-LocalizedMessage של PERMISSION_DENIED
שגיאה שנגרמה כתוצאה משימוש בפרטי כניסה לפרויקט ב-Google Cloud שבו Data Manager API לא מופעל. במטען הייעודי (payload) של Help מוצגת כתובת ה-URL שבה אפשר להפעיל את השירות, ובמטען הייעודי (payload) של LocalizedMessage יש תיאור של השגיאה.
{
"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"
}
]
},
...
]
}
}
גישה לפרטי השגיאה
אם אתם משתמשים באחת מספריות הלקוח, אתם יכולים להשתמש בשיטות העזר כדי לקבל את מטען הייעודי הסטנדרטי של הפרטים.
.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...
}
...
}
שיטות מומלצות לטיפול בשגיאות
כדי ליצור אפליקציות עמידות, כדאי להטמיע את השיטות המומלצות הבאות.
- בדיקת פרטי השגיאה
- תמיד כדאי לחפש את אחד ממטעני הנתונים של הפרטים הסטנדרטיים, כמו
BadRequest. כל מטען ייעודי (payload) של פרטים רגילים מכיל מידע שיעזור לכם להבין את הסיבה לשגיאה. - ההבדל בין שגיאות בצד הלקוח לבין שגיאות בצד השרת
בודקים אם השגיאה נגרמת בגלל בעיה בהטמעה (הלקוח) או ב-API (השרת).
- שגיאות בצד הלקוח: קודים כמו
INVALID_ARGUMENT,NOT_FOUND,PERMISSION_DENIED,FAILED_PRECONDITION,UNAUTHENTICATED. כדי לפתור את הבעיות האלה, צריך לשנות את הבקשה או את מצב האפליקציה או את פרטי הכניסה שלה. אל תנסו לשלוח את הבקשה שוב בלי לפתור את הבעיה. - שגיאות בשרת: קודים כמו
UNAVAILABLE,INTERNAL,DEADLINE_EXCEEDED,UNKNOWN. ההודעות האלה מצביעות על בעיה זמנית בשירות ה-API.
- שגיאות בצד הלקוח: קודים כמו
- הטמעה של אסטרטגיית ניסיון חוזר
בודקים אם אפשר לנסות שוב לבצע את הפעולה שגרמה לשגיאה, ומשתמשים באסטרטגיה לניסיונות חוזרים.
- מומלץ לנסות שוב רק במקרה של שגיאות שרת זמניות כמו
UNAVAILABLE, DEADLINE_EXCEEDED, INTERNAL, UNKNOWNו-ABORTED. - כדאי להשתמש באלגוריתם של השהיה מעריכית לפני ניסיון חוזר (exponential backoff) כדי להמתין פרקי זמן ארוכים יותר בין ניסיונות חוזרים. כך אפשר למנוע עומס על שירות שכבר נמצא במצב של לחץ. לדוגמה, מחכים שנייה אחת, אחר כך שתי שניות, אחר כך ארבע שניות, וממשיכים עד שמגיעים למספר המקסימלי של ניסיונות חוזרים או לזמן ההמתנה הכולל.
- כדי למנוע את בעיית "העדר הרועם" שבה לקוחות רבים מנסים שוב בו-זמנית, מוסיפים להשהיות של ה-backoff כמות קטנה ואקראית של "תנודות".
- מומלץ לנסות שוב רק במקרה של שגיאות שרת זמניות כמו
- תיעוד מפורט
מתעדים את תגובת השגיאה המלאה, כולל כל מטעני הנתונים של הפרטים הרגילים, במיוחד מזהה הבקשה. המידע הזה חיוני לניפוי באגים ולדיווח על בעיות לתמיכה של Google במקרה הצורך.
- שליחת משוב ממשתמשים
בהתבסס על הקודים וההודעות במטענים של פרטים רגילים, צריך לספק משוב ברור ומועיל למשתמשים באפליקציה. לדוגמה, במקום "An error occurred" (אירעה שגיאה), אפשר לומר "Transaction ID was missing" (מזהה העסקה היה חסר) או "The account ID of the destination was not found" (מזהה החשבון של היעד לא נמצא).
אם תפעלו לפי ההנחיות האלה, תוכלו לאבחן ולטפל ביעילות בשגיאות שמוחזרות על ידי Data Manager API, וכך ליצור אפליקציות יציבות וידידותיות יותר למשתמשים.