הסבר על שגיאות 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 דוחה הרבה מהרשומות בבקשה, או אפילו את כולן. אם בחלק משמעותי מהרשומות בבקשה יש שגיאות אבל אתם לא בודקים את התגובה, יכול להיות שלא תהיו מודעים בכלל לבעיות נרחבות בנתונים, ותגלו את הבעיות האלה רק כמה ימים או שבועות לאחר מכן, כשהתוצאות המצטברות לא יתאימו לציפיות שלכם.

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

בדיקת שגיאות מסוג fast-fail באמצעות 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. בודקים את מטען הייעודי (payload) של הפרטים הסטנדרטיים של קוד השגיאה. מטעני הייעודיים הסטנדרטיים של הפרטים הם קבוצת הודעות לשגיאות מ-Google APIs. הן מספקות פרטים על השגיאה בצורה מובנית ועקבית. כל שגיאה מ-Data Manager API יכולה לכלול כמה הודעות מטען ייעודי (payload) סטנדרטיות עם פרטים. בספריות הלקוח של Data Manager API יש שיטות עזר לקבלת המטענים הייעודיים (payloads) הסטנדרטיים של פרטי השגיאה.

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

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

    בנוסף, המטען הייעודי (payload) של 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"
    }
  ]
}

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

מטענים ייעודיים (payloads) סטנדרטיים של פרטים

אלה המטענים הייעודיים (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 כדי לאחזר מידע נוסף שאולי לא נכלל בפירוט הסטנדרטי האחר. המטען הייעודי (payload) של ErrorInfo מכיל מפה של 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

חפשו את המטענים הייעודיים (payloads) 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"
          }
        ]
      },
      ...
    ]
  }
}

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

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

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

טיפול בשגיאות שקשורות לגודל הכותרת ב-gRPC

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

ב-gRPC, השירות מחזיר את פרטי השגיאה האלה בכותרות התגובה של HTTP/2 (מטא-נתונים). כברירת מחדל, ספריות הלקוח של gRPC מגבילות את הגודל המקסימלי של כותרות נכנסות (בדרך כלל 8-10KB). אם פרטי השגיאה חורגים מהמגבלה הזו, ההעברה של HTTP/2 בצד הלקוח נכשלת לפני ניתוח התגובה לשגיאה, ומופיעה חריגה כמו:

Http2Exception: Header size exceeded max allowed size (10240)

מכיוון שהלקוח לא יכול לעבד את כותרות התגובה, הוא מבטל את הסטרימינג (שמופיע כסטטוס HTTP 499 Client Closed Request ביומנים בצד השרת), ולאפליקציה אין גישה לפרטי השגיאה BadRequest.

כדי לפתור את הבעיה ולבדוק את רשימת השגיאות המלאה, צריך להגדיר את לקוח ה-gRPC עם גודל מקסימלי גדול יותר של מטא-נתונים נכנסים (למשל 16MB):

‎.NET

// Creates a client for the ingestion service. Increases the maximum metadata size to
// 16MB to prevent RESOURCE_EXHAUSTED errors when responses contain large error
// details.
IngestionServiceClient ingestionServiceClient = new IngestionServiceClientBuilder
{
    GrpcChannelOptions = GrpcChannelOptions.Empty.WithCustomOption(
        "grpc.max_metadata_size",
        16 * 1024 * 1024
    ),
}.Build();

Java

// Creates a client for the ingestion service. Increases the maximum metadata size to 16MB to
// prevent RESOURCE_EXHAUSTED errors when responses contain large error details.
InstantiatingGrpcChannelProvider provider =
    IngestionServiceSettings.defaultGrpcTransportProviderBuilder()
        .setMaxInboundMetadataSize(16 * 1024 * 1024)
        .build();
IngestionServiceSettings settings =
    IngestionServiceSettings.newBuilder().setTransportChannelProvider(provider).build();
try (IngestionServiceClient ingestionServiceClient = IngestionServiceClient.create(settings)) {
  // ...
}

צומת

// Creates a client for the ingestion service. Increases the maximum metadata
// size to 16MB to prevent RESOURCE_EXHAUSTED errors when responses contain
// large error details.
const client = new IngestionServiceClient({
  'grpc.max_metadata_size': 16 * 1024 * 1024,
});

PHP

// Creates a client for the ingestion service. Increases the maximum metadata size to 16MB to
// prevent RESOURCE_EXHAUSTED errors when responses contain large error details.
$client = new IngestionServiceClient([
    'transportConfig' => [
        'grpc' => [
            'stubOpts' => [
                'grpc.max_metadata_size' => 16 * 1024 * 1024,
            ],
        ],
    ],
]);

Python

# Creates a client for the ingestion service. Increases the maximum
# metadata size to 16MB to prevent RESOURCE_EXHAUSTED errors when responses
# contain large error details.
channel = datamanager_v1.services.ingestion_service.transports.IngestionServiceGrpcTransport.create_channel(
    options=[("grpc.max_metadata_size", 16 * 1024 * 1024)]
)
transport = datamanager_v1.services.ingestion_service.transports.IngestionServiceGrpcTransport(
    channel=channel
)
client: datamanager_v1.IngestionServiceClient = (
    datamanager_v1.IngestionServiceClient(transport=transport)
)

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

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

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

צריך לבדוק אם השגיאה נגרמת בגלל בעיה בהטמעה (הלקוח) או בגלל בעיה ב-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), צריך להשהות את הבקשות ולנסות שוב באמצעות השהיה מעריכית לפני ניסיון חוזר (exponential backoff) עם רעידות.

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

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

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

תיעוד מפורט

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

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

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

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