הסבר על שגיאות API

במדריך הזה מוסבר איך Data Manager API מטפל בשגיאות ואיך הוא מעביר אותן. הבנה של המבנה והמשמעות של שגיאות ב-API היא חיונית לבניית אפליקציות חזקות שיכולות לטפל בבעיות בצורה חלקה, החל מקלט לא תקין ועד לזמינות זמנית של השירות.

‫Data Manager API פועל לפי מודל השגיאות הרגיל של Google API, שמבוסס על קודי סטטוס של gRPC. כל תגובה מה-API שמובילה לשגיאה כוללת אובייקט Status עם:

  • קוד שגיאה מספרי.
  • הודעת שגיאה.
  • אופציונלי, פרטים נוספים על השגיאה.

קודי שגיאה קנוניים

ב-Data Manager API נעשה שימוש בקבוצה של קודי שגיאה קנוניים שמוגדרים על ידי gRPC ו-HTTP. הקודים האלה מציינים באופן כללי את סוג השגיאה. תמיד כדאי לבדוק קודם את הקוד הזה כדי להבין את מהות הבעיה.

פרטים נוספים על הקודים האלה זמינים במאמר מדריך לעיצוב API – קודי שגיאה.

מודל של כשל מהיר

ה-Data Manager API משתמש במודל של כשל מהיר. אם בקשה מכילה שגיאות מבניות או אם אימות של רשומה כלשהי נכשל בגלל שדה חובה, הבקשה כולה נכשלת וה-API לא מעבד אף אחד מהנתונים בבקשה.

השוואה למודל של כשל חלקי

מודל הכשל המהיר שונה ממודל הכשל החלקי בממשקי API אחרים של Google, כמו Google Ads API ו-Campaign Manager 360 API. במודל של כשל חלקי, הבקשה מצליחה גם אם יש שגיאות בחלק מהרשומות, והתשובה מכילה פרטים על השגיאות ברשומות שנכשלו.

למרות שהמודל של כשל חלקי יכול להיות נוח, הוא כרוך בסיכונים משמעותיים כי הוא לא מתריע באופן יזום על שגיאות – אתם צריכים לבדוק במפורש אם יש שגיאות בכל תשובה. הדבר עלול להסתיר בעיות חשובות, כי הבקשה מצליחה גם אם ה-API דוחה הרבה רשומות בבקשה, או אפילו את כולן. אם חלק משמעותי מהרשומות בבקשה מכיל שגיאות, אבל אתם לא בודקים את התגובה, יכול להיות שלא תדעו על בעיות נרחבות בנתונים שלכם, ותגלו אותן רק ימים או שבועות לאחר מכן, כשהתוצאות המצטברות לא יתאימו לציפיות שלכם.

מודל הכשל המהיר מאפשר לכם להימנע מהבעיות האלה, כי הוא מתריע על בעיות בנתונים או בשילוב באופן מיידי, כדי שתוכלו לפעול בהתאם.

בדיקה אם יש שגיאות שגורמות לכשל מהיר באמצעות validateOnly

רוב הבקשות להטמעת נתונים ובקשות להסרת תוכן תומכות בשדה validateOnly. כשמגדירים את validateOnly ל-true, מערכת Data Manager API מריצה את אותן בדיקות אימות בסיסיות כמו בבקשה רגילה, אבל לא מבצעת המרה או הסרה של נתונים.

  • אם יש שגיאות בבקשה, היא תיכשל ותוצג אותה תשובת שגיאה שמתקבלת מבקשה רגילה.
  • אם הבקשה עוברת את האימות, היא מצליחה. התשובה כוללת את fieldWarnings של שדות אופציונליים, בדיוק כמו בבקשה רגילה.

אפשר להשתמש בvalidateOnly כדי:

  • לבצע בדיקה של שילוב חדש או מעודכן בלי להשפיע על הנתונים הפעילים.
  • לפני ששולחים מחדש את הבקשה, צריך לוודא שהתיקון פותר את השגיאה.

טיפול בשגיאות

אם הבקשה נכשלת, פועלים לפי השלבים הבאים:

  1. כדאי לבדוק את קוד השגיאה כדי לגלות את סוג השגיאה.

    • אם משתמשים ב-gRPC, קוד השגיאה נמצא בשדה code של Status. אם משתמשים בספריית לקוח, יכול להיות שהיא תזרוק סוג ספציפי של חריגה שמתאים לקוד השגיאה. לדוגמה, ספריית הלקוח ל-Java מחזירה את השגיאה com.google.api.gax.rpc.InvalidArgumentException אם קוד השגיאה הוא INVALID_ARGUMENT.
    • אם משתמשים ב-REST, קוד השגיאה מופיע בתגובת השגיאה בכתובת error.status, וסטטוס ה-HTTP המתאים מופיע בכתובת error.code.
  2. בודקים את מטען הנתונים של הפרטים הרגילים כדי למצוא את קוד השגיאה. מטעני הנתונים של הפרטים הרגילים הם קבוצה של הודעות לגבי שגיאות מ-Google APIs. הן מספקות פרטים על השגיאות בצורה מובנית ועקבית. לכל שגיאה מ-Data Manager API יכולות להיות כמה הודעות מטען ייעודי (payload) עם פרטים רגילים. בספריות הלקוח של Data Manager API יש שיטות עזר לקבלת מטען ייעודי (payload) של פרטים רגילים משגיאה.

    לא משנה מה קוד השגיאה, מומלץ לבדוק את מטען הנתונים (payload) של ErrorInfo,‏ RequestInfo,‏ Help ושל LocalizedMessage ולתעד אותו.

    • ‫ErrorInfo מכיל מידע שאולי לא מופיע במטען ייעודי אחר.
    • RequestInfo מכיל את מזהה הבקשה, שיכול לעזור לכם אם תצטרכו לפנות לתמיכה.
    • ‫Help ו-LocalizedMessage מכילים קישורים ופרטים אחרים שיעזרו לך לפתור את השגיאה.

    בנוסף, מטען הנתונים BadRequest שימושי לשגיאות INVALID_ARGUMENT כי הוא מספק מידע על השדות שגרמו לשגיאה.

אזהרות לגבי הטמעה

‫Data Manager API מקבל כמה שיותר בקשות להטמעת נתונים. אם תכללו נתונים שלא נדרשים, בקשת האימות של השדות האלה לא תיכשל. לדוגמה, אם פריט בעגלת הקניות לא כולל מזהה מוצר של המוכר, ה-API מעבד את שאר הבקשה ומחזיר אזהרה.

תשובה מוצלחת על הטמעה (קוד סטטוס של HTTP‏ 200) כוללת את האזהרות האלה ברשימה fieldWarnings. כל רשומה היא אובייקט FieldWarning עם השדות הבאים:

field

המיקום של השדה בבקשה, בתחביר של נתיב בפורמט קו תחתון בין המילים.

אם נתיב מצביע על פריט ברשימה (שדה repeated), האינדקס שלו מוצג בסוגריים מרובעים ([...]) אחרי שם הרשימה.

לדוגמה, events.events[0].cart_data.items[0].merchant_product_id מציין אזהרה שקשורה לפריט הראשון בנתוני עגלת הקניות של האירוע הראשון בבקשה.

description

הסבר למה הערך שצוין גרם להצגת אזהרה.

reason

ערך ה-enum‏ WarningReason שמזהה את סוג האזהרה.

דוגמה עם FieldWarning

זו דוגמה לתגובה לבקשת הטמעה מוצלחת שמכילה אזהרה כי חסר מזהה מוצר של מוֹכר לאחד מהפריטים בעגלת הקניות.

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

מטענים סטנדרטיים של פרטים

אלה המטענים הייעודיים (payloads) הנפוצים ביותר של פרטים סטנדרטיים ב-Data Manager API:

BadRequest

בודקים את המטען הייעודי (payload) של BadRequest כשבקשה נכשלת עם INVALID_ARGUMENT (קוד סטטוס של HTTP ‏400).

ההודעה BadRequest מציינת שבבקשה היו שדות עם ערכים שגויים, או שחסר ערך בשדה חובה. בודקים את הרשימה field_violations בBadRequest כדי לראות באילו שדות יש שגיאות. כל רשומה field_violations כוללת מידע שיעזור לכם לתקן את השגיאה:

field

המיקום של השדה בבקשה, בתחביר של נתיב בפורמט קו תחתון בין המילים.

אם נתיב מצביע על פריט ברשימה (שדה repeated), האינדקס שלו מוצג בסוגריים מרובעים ([...]) אחרי שם הרשימה.

לדוגמה, destinations[0].operating_account.account_id הוא account_id ב-operating_account של הפריט הראשון ברשימה destinations.

description

הסבר למה הערך גרם לשגיאה.

reason

הספירה 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 מוצגות שתי שגיאות:

  1. לפרמטר הראשון event יש ערך שלא מקודד בפורמט הקסדצימלי במזהה המשתמש השני של האירוע.

  2. ל-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

בכל פעם שבקשה נכשלת, בודקים את מטען הייעודי (payload) של RequestInfo. RequestInfo מכיל את request_id שמזהה באופן ייחודי את בקשת ה-API.

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

כשרושמים שגיאות ביומן או פונים לתמיכה, חשוב לכלול את מזהה הבקשה כדי לאבחן בעיות.

ErrorInfo

כדאי לבדוק אם מופיעה ההודעה ErrorInfo כדי לאחזר מידע נוסף שאולי לא נכלל במטענים הייעודיים (payloads) האחרים של הפרטים הסטנדרטיים. המטען הייעודי ErrorInfo(Payload) מכיל מפת metadata עם מידע על השגיאה.

לדוגמה, כאן מופיע 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"
        }
      },
      ...
    ]
  }
}

שגיאות שקשורות למכסות ולהגבלות על קצב הבקשות

אם בקשה חורגת ממגבלה של פרויקט, ה-API מחזיר RESOURCE_EXHAUSTEDשגיאה (קוד סטטוס של HTTP‏ 429). מטען הייעודי (payload) של ErrorInfo מספק פרטים על המגבלה שנחצתה במפה metadata שלו:

consumer
הפרויקט בענן של Google שמשויך לבקשה, בפורמט projects/PROJECT_NUMBER.
quota_limit
‫
: השם של מכסת החריגה, למשל IngestionMutateRequestsPerMinutePerProject או IngestionMutateRequestsPerDayPerProject. אפשר להשתמש בערך הזה כדי לקבוע אם האפליקציה חרגה ממגבלה לדקה או ממגבלה יומית. רשימה מלאה של שמות המגבלות זמינה במאמר בנושא מגבלות לפרויקטים.
quota_location
‫
המיקום שבו נאכפת המכסה. ב-Data Manager API, הערך הזה הוא תמיד global.
quota_metric
המדד שמשויך למגבלה, כמו datamanager.googleapis.com/ingestion_mutate_requests.
service
השם של השירות, datamanager.googleapis.com.

דוגמה לתגובת שגיאה של RESOURCE_EXHAUSTED כשבקשה חורגת מהמגבלה לדקה של בקשות שינוי להוספת נתונים:

{
  "error": {
    "code": 429,
    "message": "Quota exceeded for quota metric 'Ingestion mutate requests' and limit 'Ingestion mutate requests per minute' of service 'datamanager.googleapis.com' for consumer 'project_number:PROJECT_NUMBER'.",
    "status": "RESOURCE_EXHAUSTED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "RATE_LIMIT_EXCEEDED",
        "domain": "googleapis.com",
        "metadata": {
          "consumer": "projects/PROJECT_NUMBER",
          "quota_limit": "IngestionMutateRequestsPerMinutePerProject",
          "quota_location": "global",
          "quota_metric": "datamanager.googleapis.com/ingestion_mutate_requests",
          "service": "datamanager.googleapis.com"
        }
      }
    ]
  }
}

Help וגם LocalizedMessage

כדאי לבדוק את מטען הנתונים Help ו-LocalizedMessage כדי לקבל קישורים למסמכים ולהודעות שגיאה בשפה המקומית, שיעזרו לכם להבין את השגיאה ולתקן אותה.

לדוגמה, הנה Help ו-LocalizedMessage של PERMISSION_DENIEDשגיאה שנגרמת כתוצאה משימוש בפרטי כניסה לפרויקט בענן ב-Google Cloud שבו לא מופעל Data Manager API. מטען הייעודי (payload) של Help מציג את כתובת ה-URL שבה אפשר להפעיל את השירות, וב-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"
          }
        ]
      },
      ...
    ]
  }
}

גישה לפרטי השגיאה

אם אתם משתמשים באחת מספריות הלקוח, תוכלו להשתמש בשיטות העזר כדי לקבל את מטען הייעודי (payload) של הפרטים הרגילים.

‎.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...

            // If handling a rate limit error, check the exceeded quota limit:
            if (errorInfo.Reason == "RATE_LIMIT_EXCEEDED" &&
                errorInfo.Metadata.TryGetValue("quota_limit", out string quotaLimit))
            {
                // Inspect quotaLimit to determine whether it is a per-minute
                // or daily limit (for example,
                // IngestionMutateRequestsPerMinutePerProject).
            }

            // 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'...

  // If handling a rate limit error, check the exceeded quota limit:
  if (errorInfo != null && "RATE_LIMIT_EXCEEDED".equals(errorInfo.getReason())) {
    String quotaLimit = errorInfo.getMetadataMap().get("quota_limit");
    // Inspect quotaLimit to determine whether it is a per-minute
    // or daily limit (for example,
    // IngestionMutateRequestsPerMinutePerProject).
  }

  // 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 = apiException.getErrorDetails().getRequestInfo();
  if (requestInfo != null) {
    String requestId = requestInfo.getRequestId();
    // Log the requestId...
  }
  ...
}

שיטות מומלצות לטיפול בשגיאות

כדי ליצור אפליקציות עמידות, כדאי להטמיע את השיטות המומלצות הבאות.

אימות לפני השליחה
כשיוצרים שילוב או משנים אותו, שולחים בקשות עם validateOnly שמוגדר ל-true כדי לזהות שגיאות של כשל מהיר לפני שמבצעים הטמעה של נתונים.
בדיקת פרטי השגיאה
תמיד כדאי לחפש אחת ממטען הנתונים של הפרטים הרגילים, כמו BadRequest. כל מטען ייעודי סטנדרטי של פרטים מכיל מידע שיעזור לכם להבין את הסיבה לשגיאה.
הבחנה בין שגיאות בצד הלקוח לבין שגיאות בחיבור לשרת

בודקים אם השגיאה נגרמת בגלל בעיה בהטמעה (הלקוח) או ב-API (השרת).

  • שגיאות בצד הלקוח: קודים כמו INVALID_ARGUMENT, ‏ NOT_FOUND,‏ PERMISSION_DENIED, ‏ FAILED_PRECONDITION, ‏ UNAUTHENTICATED. כדי לפתור את הבעיות האלה, צריך לשנות את הבקשה או את מצב האפליקציה או את פרטי הכניסה שלה. אל תנסו לשלוח את הבקשה שוב בלי לפתור את הבעיה.
  • שגיאות בחיבור לשרת: קודים כמו UNAVAILABLE, INTERNAL, DEADLINE_EXCEEDED, UNKNOWN. ההודעות האלה מצביעות על בעיה זמנית בשירות ה-API.
הטמעה של אסטרטגיה של ניסיון חוזר

בודקים אם אפשר לנסות שוב לבצע את הפעולה שגרמה לשגיאה, ומשתמשים באסטרטגיית ניסיון חוזר.

  • כדאי לנסות שוב רק במקרה של שגיאות בחיבור לשרת זמניות (כמו UNAVAILABLE,‏ DEADLINE_EXCEEDED,‏ INTERNAL,‏ UNKNOWN ו-ABORTED) והגבלות קצב של יצירת בקשות לדקה (RESOURCE_EXHAUSTED עם RATE_LIMIT_EXCEEDED).

  • כדי לבדוק את מגבלות הקצב, בודקים את quota_limit ב-ErrorInfo:

    • אם המגבלה היא לדקה (למשל IngestionMutateRequestsPerMinutePerProject), צריך להשהות את הבקשות ולנסות שוב באמצעות השהיה מעריכית לפני ניסיון חוזר עם רעידות.

    • אם המגבלה היא יומית (למשל IngestionMutateRequestsPerDayPerProject), אל תנסו שוב מיד. השהיית העיבוד עד שהמכסה היומית תתאפס בחצות לפי שעון החוף המערבי.

  • כדאי להשתמש באלגוריתם של השהיה מעריכית לפני ניסיון חוזר כדי להמתין פרקי זמן ארוכים יותר בין ניסיונות חוזרים. כך אפשר להימנע מעומס יתר על שירות שכבר נמצא במצב של עומס. לדוגמה, צריך להמתין שנייה אחת, אחר כך שתי שניות, אחר כך ארבע שניות, ולהמשיך עד למספר המקסימלי של ניסיונות חוזרים או עד לזמן ההמתנה הכולל.

  • מוסיפים כמות קטנה ואקראית של "תנודות" להשהיות של ה-backoff כדי למנוע את בעיית "העדר הרועם", שבה לקוחות רבים מנסים שוב בו-זמנית.

רישום מפורט ביומן

רישום ביומן של תגובת השגיאה המלאה, כולל כל מטען הפרטים הסטנדרטי, במיוחד מזהה הבקשה. המידע הזה חיוני לניפוי באגים ולדיווח על בעיות לתמיכה של Google במקרה הצורך.

שליחת משוב מהמשתמשים

בהתבסס על הקודים וההודעות במטענים של פרטים רגילים, צריך לספק משוב ברור ומועיל למשתמשים באפליקציה. לדוגמה, במקום "An error occurred" (אירעה שגיאה), אפשר להגיד "Transaction ID was missing" (מזהה העסקה היה חסר) או "The account ID of the destination was not found" (מזהה החשבון של היעד לא נמצא).

אם תפעלו לפי ההנחיות האלה, תוכלו לאבחן ולטפל ביעילות בשגיאות שמוחזרות על ידי Data Manager API, וכך ליצור אפליקציות יציבות וידידותיות למשתמשים.