ทำความเข้าใจข้อผิดพลาดของ API

คู่มือนี้จะอธิบายวิธีที่ Data Manager API จัดการและสื่อสารข้อผิดพลาด การทำความเข้าใจโครงสร้างและความหมายของข้อผิดพลาด API เป็นสิ่งสำคัญอย่างยิ่งในการสร้างแอปพลิเคชันที่มีประสิทธิภาพซึ่งสามารถจัดการปัญหาได้อย่างราบรื่น ตั้งแต่อินพุตที่ไม่ถูกต้องไปจนถึงบริการที่ไม่พร้อมใช้งานชั่วคราว

Data Manager API เป็นไปตามโมเดลข้อผิดพลาดของ Google API มาตรฐาน ซึ่งอิงตามรหัสสถานะ gRPC การตอบกลับจาก API แต่ละรายการที่ทำให้เกิดข้อผิดพลาดจะมีออบเจ็กต์ Status ที่มีข้อมูลต่อไปนี้

  • รหัสข้อผิดพลาดที่เป็นตัวเลข
  • ข้อความแสดงข้อผิดพลาด
  • รายละเอียดข้อผิดพลาดเพิ่มเติม (ไม่บังคับ)

รหัสข้อผิดพลาด Canonical

Data Manager API ใช้ชุดรหัสข้อผิดพลาด Canonical ที่กำหนดโดย gRPC และ HTTP รหัสเหล่านี้จะระบุประเภทข้อผิดพลาดในระดับสูง คุณควรตรวจสอบรหัสนี้ก่อนเสมอเพื่อทำความเข้าใจลักษณะพื้นฐานของปัญหา

ดูรายละเอียดเพิ่มเติมเกี่ยวกับรหัสเหล่านี้ได้ที่คู่มือการออกแบบ API - รหัสข้อผิดพลาด

โมเดลการลองผิดลองถูก

Data Manager API ใช้โมเดล Fast-Fail หากคำขอมีข้อผิดพลาดด้านโครงสร้างหรือหากระเบียนใดๆ ไม่ผ่านการตรวจสอบความถูกต้องสำหรับช่องที่ต้องกรอก คำขอทั้งหมดจะล้มเหลว และ API จะไม่ประมวลผลข้อมูลใดๆ ในคำขอนั้น

การเปรียบเทียบกับโมเดลความล้มเหลวบางส่วน

โมเดล Fast-Fail แตกต่างจากโมเดลการดำเนินการไม่สำเร็จบางส่วนใน Google API อื่นๆ เช่น 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 API โดยจะให้รายละเอียดข้อผิดพลาดในลักษณะที่มีโครงสร้างและสอดคล้องกัน ข้อผิดพลาดแต่ละรายการจาก Data Manager API อาจมีข้อความเพย์โหลดรายละเอียดมาตรฐานหลายรายการ ไลบรารีของไคลเอ็นต์ Data Manager API มีเมธอดตัวช่วยเพื่อรับเพย์โหลดรายละเอียดมาตรฐานจากข้อผิดพลาด

    ไม่ว่าจะเป็นรหัสข้อผิดพลาดใด เราขอแนะนำให้คุณตรวจสอบและบันทึกเพย์โหลด ErrorInfo, RequestInfo, Help และ LocalizedMessage

    • ErrorInfo มีข้อมูลที่อาจไม่อยู่ในเพย์โหลดอื่นๆ
    • RequestInfo มีรหัสคำขอ ซึ่งจะเป็นประโยชน์หากคุณต้องการติดต่อทีมสนับสนุน
    • Help และ LocalizedMessage มีลิงก์และรายละเอียดอื่นๆ เพื่อช่วยคุณแก้ไขข้อผิดพลาด

    นอกจากนี้ เพย์โหลด BadRequest ยังมีประโยชน์สำหรับข้อผิดพลาด INVALID_ARGUMENT เนื่องจากให้ข้อมูลเกี่ยวกับช่องที่ทำให้เกิดข้อผิดพลาด

คำเตือนเกี่ยวกับการส่งผ่านข้อมูล

Data Manager API จะยอมรับคำขอการนำเข้าให้มากที่สุดเท่าที่จะเป็นไปได้ หากคุณใส่ข้อมูลที่ไม่จำเป็น การตรวจสอบความถูกต้องที่ล้มเหลวสำหรับช่องเหล่านั้นจะไม่ทำให้คำขอล้มเหลว เช่น หากสินค้าในรถเข็นไม่มีรหัสผลิตภัณฑ์ของผู้ขาย API จะประมวลผลคำขอที่เหลือและแสดงคำเตือน

การตอบกลับการนำเข้าที่สำเร็จ (รหัสสถานะ HTTP 200) จะมีคำเตือนเหล่านี้ในรายการ fieldWarnings แต่ละรายการคือออบเจ็กต์ FieldWarning ที่มีฟิลด์ต่อไปนี้

field

ตำแหน่งของช่องในคำขอ ในไวยากรณ์เส้นทาง Snake Case

หากเส้นทางชี้ไปยังรายการในลิสต์ (ช่อง 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"
    }
  ]
}

เพย์โหลดรายละเอียดมาตรฐาน

เพย์โหลดรายละเอียดมาตรฐานที่พบบ่อยที่สุดสำหรับ Data Manager API มีดังนี้

BadRequest

ตรวจสอบเพย์โหลด BadRequest เมื่อคำขอล้มเหลวด้วย INVALID_ARGUMENT (รหัสสถานะ HTTP 400)

ข้อความ BadRequest แสดงว่าคำขอมีช่องที่มีค่าไม่ถูกต้อง หรือไม่มีค่าสำหรับช่องที่ต้องกรอก ตรวจสอบรายการ field_violations ใน BadRequest เพื่อดูว่าช่องใดมีข้อผิดพลาด รายการ field_violations แต่ละรายการจะมีข้อมูลที่จะช่วยคุณแก้ไขข้อผิดพลาด ดังนี้

field

ตำแหน่งของช่องในคำขอ ในไวยากรณ์เส้นทาง Snake 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 จะแสดงข้อผิดพลาด 2 รายการ ดังนี้

  1. event แรกมีค่าที่ไม่ได้เข้ารหัสฐานสิบหกในตัวระบุผู้ใช้ที่ 2 ของเหตุการณ์

  2. event รายการที่ 2 มีค่าที่ไม่ได้เข้ารหัสฐานสิบหกในตัวระบุผู้ใช้รายการที่ 3 ของเหตุการณ์

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

ตรวจสอบข้อความ ErrorInfo เพื่อดึงข้อมูลเพิ่มเติมที่อาจไม่ได้บันทึกไว้ในเพย์โหลดรายละเอียดมาตรฐานอื่นๆ เพย์โหลด 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) เพย์โหลด ErrorInfo จะแสดงรายละเอียดเกี่ยวกับขีดจำกัดที่เกินในแมป metadata ดังนี้

consumer
โปรเจ็กต์ Google Cloud ที่เชื่อมโยงกับคำขอ ซึ่งจัดรูปแบบเป็น 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 ที่ไม่ได้เปิดใช้ Data Manager API เพย์โหลด 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"
          }
        ]
      },
      ...
    ]
  }
}

รายละเอียดข้อผิดพลาดในการเข้าถึง

หากคุณใช้ไลบรารีของไคลเอ็นต์รายการใดรายการหนึ่ง ให้ใช้เมธอดตัวช่วยเพื่อรับเพย์โหลดรายละเอียดมาตรฐาน

.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 จะแสดงข้อผิดพลาดทั้งหมดในเพย์โหลด BadRequest ของการตอบกลับ

ใน gRPC บริการจะแสดงรายละเอียดข้อผิดพลาดเหล่านี้ในส่วนหัวการตอบกลับ HTTP/2 (ข้อมูลเมตา) โดยค่าเริ่มต้น ไลบรารีของไคลเอ็นต์ gRPC จะจำกัดส่วนหัวขาเข้าให้มีขนาดสูงสุด (โดยทั่วไปคือ 8-10 KB) หากรายละเอียดข้อผิดพลาดเกินขีดจำกัดนี้ การส่ง HTTP/2 ฝั่งไคลเอ็นต์จะล้มเหลวก่อนที่จะแยกวิเคราะห์การตอบกลับข้อผิดพลาด โดยจะแสดงข้อยกเว้น เช่น

Http2Exception: Header size exceeded max allowed size (10240)

เนื่องจากไคลเอ็นต์ไม่สามารถประมวลผลส่วนหัวการตอบกลับ จึงยกเลิกสตรีม (ซึ่งปรากฏเป็นสถานะ HTTP 499 Client Closed Request ในบันทึกฝั่งเซิร์ฟเวอร์) และแอปพลิเคชันของคุณไม่สามารถเข้าถึงรายละเอียดข้อผิดพลาด BadRequest ได้

หากต้องการแก้ไขปัญหานี้และตรวจสอบรายการข้อผิดพลาดทั้งหมด ให้กำหนดค่าไคลเอ็นต์ gRPC โดยเพิ่มขนาดข้อมูลเมตาขาเข้าสูงสุด (เช่น 16 MB) ดังนี้

.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 เพื่อตรวจจับข้อผิดพลาดที่ทำให้ดำเนินการไม่สำเร็จก่อนที่จะนำเข้าข้อมูล
ตรวจสอบรายละเอียดข้อผิดพลาด
มองหาเพย์โหลดรายละเอียดมาตรฐานอย่างใดอย่างหนึ่งเสมอ เช่น 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) ให้หยุดคำขอชั่วคราวและลองอีกครั้งโดยใช้ Exponential Backoff ที่มี Jitter

    • หากขีดจำกัดเป็นรายวัน (เช่น IngestionMutateRequestsPerDayPerProject) อย่าลองอีกครั้งทันที หยุดการประมวลผลชั่วคราวจนกว่าโควต้ารายวันจะรีเซ็ตตอนเที่ยงคืนตามเวลาแปซิฟิก

  • ใช้อัลกอริทึม Exponential Backoff เพื่อรอระยะเวลาที่เพิ่มขึ้นระหว่างการลองใหม่แต่ละครั้ง ซึ่งจะช่วยหลีกเลี่ยงการสร้างภาระมากเกินไปให้กับบริการที่ทำงานหนักอยู่แล้ว เช่น รอ 1 วินาที จากนั้นรอ 2 วินาที แล้วรอ 4 วินาที โดยเพิ่มระยะเวลารอไปเรื่อยๆ จนกว่าจะถึงจำนวนครั้งสูงสุดที่ลองใหม่หรือเวลารอรวม

  • เพิ่ม "ความผันผวน" แบบสุ่มเล็กน้อยลงในความล่าช้าของ Backoff เพื่อป้องกันปัญหา "Thundering Herd" ที่ไคลเอ็นต์จำนวนมากลองใหม่พร้อมกัน

บันทึกอย่างละเอียด

บันทึกการตอบกลับข้อผิดพลาดทั้งหมด รวมถึงเพย์โหลดรายละเอียดมาตรฐานทั้งหมด โดยเฉพาะรหัสคำขอ ข้อมูลนี้มีความสำคัญต่อการแก้ไขข้อบกพร่องและการรายงานปัญหาไปยังทีมสนับสนุนของ Google หากจำเป็น

แสดงความคิดเห็นของผู้ใช้

ให้ความคิดเห็นที่ชัดเจนและเป็นประโยชน์แก่ผู้ใช้แอปพลิเคชันของคุณโดยอิงตามรหัสและข้อความในเพย์โหลดรายละเอียดมาตรฐาน เช่น แทนที่จะระบุแค่ "เกิดข้อผิดพลาด" คุณอาจระบุว่า "ไม่พบรหัสธุรกรรม" หรือ "ไม่พบรหัสบัญชีของปลายทาง"

การทำตามหลักเกณฑ์เหล่านี้จะช่วยให้คุณวิเคราะห์และจัดการข้อผิดพลาดที่ Data Manager API แสดงผลได้อย่างมีประสิทธิภาพ ซึ่งจะทำให้แอปพลิเคชันมีความเสถียรและใช้ง่ายมากขึ้น