التعرّف على أخطاء واجهة برمجة التطبيقات

يشرح هذا الدليل كيفية معالجة الأخطاء في Data Manager API وكيفية الإبلاغ عنها. إنّ فهم بنية أخطاء واجهة برمجة التطبيقات ومعناها أمر بالغ الأهمية لإنشاء تطبيقات قوية يمكنها معالجة المشاكل بشكل سليم، بدءًا من الإدخال غير الصالح وصولاً إلى عدم توفّر الخدمة مؤقتًا.

تتّبع Data Manager API نموذج أخطاء Google API العادي، الذي يستند إلى رموز حالة gRPC. يتضمّن كل ردّ من واجهة برمجة التطبيقات يؤدي إلى حدوث خطأ كائن Status يتضمّن ما يلي:

  • رمز خطأ رقمي
  • رسالة خطأ
  • تفاصيل خطأ إضافية اختيارية

رموز الخطأ الأساسية

تستخدِم Data Manager API مجموعة من رموز الخطأ الأساسية التي تحدّدها gRPC وHTTP. تقدّم هذه الرموز إشارة عالية المستوى إلى نوع الخطأ. ننصحك بالتحقّق من هذا الرمز أولاً لفهم الطبيعة الأساسية للمشكلة.

لمزيد من التفاصيل حول هذه الرموز، يُرجى الاطّلاع على دليل تصميم واجهة برمجة التطبيقات - رموز الخطأ.

نموذج الإيقاف السريع

تستخدِم Data Manager API نموذج الإيقاف السريع. إذا كان الطلب يتضمّن أخطاء في البنية أو إذا تعذّر التحقّق من صحة أي سجلّ لحقل مطلوب، سيتعذّر تنفيذ الطلب بالكامل، ولن تعالج واجهة برمجة التطبيقات أيًا من البيانات في هذا الطلب.

يختلف نموذج الإيقاف السريع عن نموذج الإيقاف الجزئي في بعض واجهات برمجة التطبيقات الأخرى من Google ، مثل Google Ads API و Campaign Manager 360 API. في نموذج الإيقاف الجزئي، ينجح الطلب حتى إذا كانت بعض السجلات تتضمّن أخطاء، ويحتوي الردّ على تفاصيل الخطأ للسجلات التي تعذّر تنفيذها.

على الرغم من أنّ الإيقاف الجزئي قد يكون مناسبًا، إلا أنّه ينطوي على مخاطر كبيرة لأنّ نموذج الإيقاف الجزئي لا يُنبّهك بشكل استباقي إلى الأخطاء، بل عليك التحقّق من الأخطاء في كل ردّ بشكل صريح. يمكن أن يؤدي ذلك إلى إخفاء المشاكل المهمة لأنّ الطلب ينجح حتى إذا رفضت واجهة برمجة التطبيقات العديد من السجلات أو حتى جميعها في الطلب. إذا كان جزء كبير من السجلات في الطلب يتضمّن أخطاء ولكنّك لم تفحص الردّ، قد لا تكون على علم تمامًا بالمشاكل المنتشرة في بياناتك، ولن تكتشف هذه المشاكل إلا بعد أيام أو أسابيع عندما لا تتطابق النتائج التراكمية مع توقّعاتك.

يتجنّب نموذج الإيقاف السريع هذه المشاكل من خلال تنبيهك إلى المشاكل في بياناتك أو عملية الربط على الفور حتى تتمكّن من اتّخاذ الإجراء المناسب.

معالجة الأخطاء

اتّبِع هذه الخطوات عندما يتعذّر تنفيذ طلب:

  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 رسائل حمولة تفاصيل عادية متعدّدة. تحتوي مكتبات عميل Data Manager API على طرق مساعِدة للحصول على حمولات التفاصيل العادية من الخطأ.

    بغض النظر عن رمز الخطأ، ننصحك بالبحث عن حمولات ErrorInfo وRequestInfo وHelp و وLocalizedMessage وتسجيلها.

    • تحتوي ErrorInfo على معلومات قد لا تكون متوفّرة في حمولات أخرى.
    • RequestInfo يحتوي على رقم تعريف الطلب، وهو مفيد إذا كنت بحاجة إلى التواصل مع فريق الدعم.
    • تحتوي Help وLocalizedMessage على روابط وتفاصيل أخرى لمساعدتك في معالجة الخطأ.

    بالإضافة إلى ذلك، تكون حمولة BadRequest مفيدة لأخطاء INVALID_ARGUMENT لأنّها تقدّم معلومات عن الحقول التي تسبّبت في حدوث الخطأ.

تحذيرات بشأن عملية الإدخال

تقبل Data Manager API أكبر قدر ممكن من طلب الإدخال. إذا تضمّنت بيانات غير مطلوبة، لن تؤدي حالات تعذُّر التحقّق من صحة هذه الحقول إلى تعذُّر تنفيذ الطلب. على سبيل المثال، إذا كان أحد عناصر سلة التسوّق لا يتضمّن رقم تعريف منتج التاجر، تعالج واجهة برمجة التطبيقات باقي الطلب وتعرض تحذيرًا.

يتضمّن ردّ الإدخال الناجح (رمز حالة HTTP 200) هذه التحذيرات في قائمة field_warnings. كل إدخال هو كائن FieldWarning يتضمّن الحقول التالية:

field

موقع الحقل في الطلب، باستخدام بنية المسار في التنسيق snake_case

إذا كان المسار يشير إلى عنصر في قائمة (حقل repeated)، يظهر فهرسه بين قوسَين مربّعَين ([...]) بعد اسم القائمة.

على سبيل المثال، يشير events.events[0].cart_data.items[0].merchant_product_id إلى تحذير مرتبط بالعنصر الأول في بيانات سلة التسوّق للحدث الأول في الطلب.

description

شرح لسبب تسبُّب القيمة المقدَّمة في ظهور تحذير

reason

قيمة تعداد 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

تعداد ErrorReason، مثل INVALID_HEX_ENCODING أو INVALID_CURRENCY_CODE.

أمثلة على BadRequest

في ما يلي نموذج ردّ لخطأ INVALID_ARGUMENT يتضمّن رسالة BadRequest. توضّح field_violations أنّ الخطأ هو accountId ليس رقمًا. توضّح القيمة destinations[0].login_account.account_id للحقل field أنّ 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

ابحث عن حمولة RequestInfo كلما تعذّر تنفيذ طلب. تحتوي RequestInfo على request_id الذي يحدّد طلب بيانات من واجهة برمجة التطبيقات بشكل فريد.

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

Help وLocalizedMessage

ابحث عن حمولتَي Help وLocalizedMessage للحصول على روابط تؤدي إلى المستندات ورسائل الخطأ المترجَمة التي تساعدك في فهم الخطأ وإصلاحه.

على سبيل المثال، في ما يلي Help وLocalizedMessage لخطأ PERMISSION_DENIED ناتج عن استخدام بيانات اعتماد لمشروع على Google Cloud لم يتم تفعيل 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...

            // Log the details in the 'Metadata' map...
            foreach (
                KeyValuePair<String, String> metadataEntry in errorInfo.Metadata
            )
            {
                // Log the metadataEntry.Key and metadataEntry.Value...
            }
        }
        else
        {
            // ...
        }
    }
}

جافا

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. تحتوي كل حمولة تفاصيل عادية على معلومات لمساعدتك في فهم سبب الخطأ.
التمييز بين أخطاء العميل وأخطاء الخادم

حدِّد ما إذا كان الخطأ ناتجًا عن مشكلة في عملية التنفيذ (العميل) أو مشكلة في واجهة برمجة التطبيقات (الخادم).

  • أخطاء العميل: رموز مثل INVALID_ARGUMENT وNOT_FOUND وPERMISSION_DENIED وFAILED_PRECONDITION وUNAUTHENTICATED تتطلّب هذه الأخطاء إجراء تغييرات على الطلب أو حالة تطبيقك أو بيانات اعتماده. لا تعِد محاولة إرسال الطلب بدون معالجة المشكلة.
  • أخطاء الخادم: رموز مثل UNAVAILABLE وINTERNAL وDEADLINE_EXCEEDED وUNKNOWN تشير هذه الأخطاء إلى مشكلة مؤقتة في خدمة واجهة برمجة التطبيقات.
تنفيذ استراتيجية إعادة المحاولة

حدِّد ما إذا كان يمكن إعادة محاولة تنفيذ الطلب، واستخدِم استراتيجية إعادة المحاولة.

  • أعِد المحاولة فقط لأخطاء الخادم المؤقتة، مثل UNAVAILABLE وDEADLINE_EXCEEDED وINTERNAL وUNKNOWN وABORTED.
  • استخدِم خوارزمية الرقود الأسي للانتظار لفترات متزايدة بين عمليات إعادة المحاولة. يساعد ذلك في تجنُّب إرهاق خدمة متأثرة أصلاً. على سبيل المثال، انتظِر ثانية واحدة، ثم ثانيتَين، ثم 4 ثوانٍ، وهكذا حتى الوصول إلى الحد الأقصى لعدد عمليات إعادة المحاولة أو إجمالي وقت الانتظار.
  • أضِف مقدارًا صغيرًا عشوائيًا من "التذبذب" إلى فترات الرقود لتجنُّب مشكلة "القطيع الصاخب" حيث يعيد العديد من العملاء المحاولة في الوقت نفسه.
تسجيل البيانات بدقة

سجِّل ردّ الخطأ الكامل، بما في ذلك جميع حمولات التفاصيل العادية، وخاصةً رقم تعريف الطلب. هذه المعلومات ضرورية لتصحيح الأخطاء والإبلاغ عن المشاكل إلى فريق دعم Google إذا لزم الأمر.

تقديم ملاحظات للمستخدمين

استنادًا إلى الرموز والرسائل في الـ حمولات التفصيل العادية، قدِّم ملاحظات واضحة و مفيدة لمستخدمي تطبيقك. على سبيل المثال، بدلاً من "حدث خطأ"، يمكنك كتابة "لم يتم العثور على رقم تعريف المعاملة" أو "لم يتم العثور على رقم تعريف حساب الوجهة".

باتّباع هذه الإرشادات، يمكنك تشخيص الأخطاء التي تعرضها Data Manager API ومعالجتها بفعالية، ما يؤدي إلى إنشاء تطبيقات أكثر استقرارًا وسهولة في الاستخدام.