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

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

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

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

رموز الخطأ المتعلقة بالعناوين الأساسية

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

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

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

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

  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 وQuotaFailure وRetryInfo مفيدة لرموز الخطأ المحدّدة التالية:

    • إذا كان رمز الحالة هو INVALID_ARGUMENT، راجِع حمولة BadRequest للحصول على معلومات حول الحقول التي تسبّبت في حدوث الخطأ.
    • إذا كان رمز الحالة هو RESOURCE_EXHAUSTED، راجِع حمولات QuotaFailure وRetryInfo للحصول على معلومات حول الحصة واقتراح بشأن تأخير إعادة المحاولة.

حمولة التفاصيل العادية

في ما يلي حمولات التفاصيل العادية الأكثر شيوعًا لواجهة برمجة التطبيقات "إدارة بيانات Google":

BadRequest

ابحث عن حمولة 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

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

QuotaFailure وRetryInfo

تحقَّق من حمولات QuotaFailure وRetryInfo عند تعذُّر تنفيذ طلب مع ظهور الخطأ RESOURCE_EXHAUSTED (رمز حالة HTTP 429).

تشير الرسالة QuotaFailure إلى أنّه تم استنفاد أحد الموارد (على سبيل المثال، تجاوزت الحصة المخصّصة لك)، أو أنّ النظام مثقل. افحص قائمة violations لتحديد الحصص التي تم تجاوزها.

قد يتضمّن الخطأ أيضًا الرسالة RetryInfo، التي تشير إلى retry_delay مقترَحة لإعادة محاولة الطلب.

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.developers.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.developers.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.developers.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.developers.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 developers console API activation",
            "url": "https://console.developers.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.QuotaFailure)
        {
            Google.Rpc.QuotaFailure quotaFailure = (Google.Rpc.QuotaFailure)detail;
            foreach (
                Google.Rpc.QuotaFailure.Types.Violation violation in quotaFailure.Violations
            )
            {
                // Access attributes such as violation.Subject and violation.QuotaId
            }
        }
        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.QuotaFailureException quotaFailureException) {
  // Gets the standard QuotaFailure payload from the exception.
  QuotaFailure quotaFailure = quotaFailureException.getErrorDetails().getQuotaFailure();
  for (int i = 0; i < quotaFailure.getViolationsCount(); i++) {
    QuotaFailure.Violation violation = quotaFailure.getViolations(i);
    // Access attributes such as violation.getSubject() and violation.getQuotaId()
  }

  // Gets the standard RequestInfo payload from the exception.
  RequestInfo requestInfo = quotaFailureException.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.
  ...
}

أفضل الممارسات لمعالجة الأخطاء

لإنشاء تطبيقات مرنة، اتّبِع أفضل الممارسات التالية.

فحص تفاصيل الخطأ
ابحث دائمًا عن أحد حمولة التفاصيل القياسية مثل 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 والتعامل معها بفعالية، ما يؤدي إلى إنشاء تطبيقات أكثر استقرارًا وسهولة في الاستخدام.