خطاهای API را درک کنید

این راهنما توضیح می‌دهد که چگونه رابط برنامه‌نویسی کاربردی (API) مدیریت داده، خطاها را مدیریت و گزارش می‌کند. درک ساختار و معنای خطاهای API برای ساخت برنامه‌های قدرتمندی که می‌توانند به طور شایسته‌ای مشکلات را مدیریت کنند، از ورودی نامعتبر گرفته تا عدم دسترسی موقت به سرویس، بسیار مهم است.

رابط برنامه‌نویسی کاربردی مدیریت داده (Data Manager API) از مدل خطای استاندارد API گوگل پیروی می‌کند که مبتنی بر کدهای وضعیت gRPC است. هر پاسخ API که منجر به خطا می‌شود، شامل یک شیء Status با موارد زیر است:

  • یک کد خطای عددی.
  • یک پیام خطا.
  • جزئیات خطای اضافی و اختیاری.

کدهای خطای متعارف

رابط برنامه‌نویسی کاربردی مدیریت داده (Data Manager API) از مجموعه‌ای از کدهای خطای متعارف استفاده می‌کند که توسط gRPC و HTTP تعریف شده‌اند. این کدها نشان‌دهنده‌ی سطح بالایی از نوع خطا هستند. شما همیشه باید ابتدا این کد را بررسی کنید تا ماهیت اساسی مشکل را درک کنید.

برای جزئیات بیشتر در مورد این کدها، به راهنمای طراحی API - کدهای خطا مراجعه کنید.

مدیریت خطاها

وقتی درخواست ناموفق بود، این مراحل را دنبال کنید:

  1. برای پیدا کردن نوع خطا ، کد خطا را بررسی کنید.

    • اگر از gRPC استفاده می‌کنید، کد خطا در فیلد code در Status قرار دارد. اگر از یک کتابخانه کلاینت استفاده می‌کنید ، ممکن است نوع خاصی از استثنا را که مربوط به کد خطا است، ایجاد کند. برای مثال، کتابخانه کلاینت برای جاوا اگر کد خطا INVALID_ARGUMENT باشد، یک استثنای com.google.api.gax.rpc.InvalidArgumentException ایجاد می‌کند.
    • اگر از REST استفاده می‌کنید، کد خطا در پاسخ خطا در error.status قرار دارد و وضعیت HTTP مربوطه در error.code است.
  2. بار داده استاندارد جزئیات (detail payload) را برای کد خطا بررسی کنید. بارهای داده استاندارد مجموعه‌ای از پیام‌ها برای خطاها از APIهای گوگل هستند. آن‌ها جزئیات خطا را به روشی ساختاریافته و سازگار به شما ارائه می‌دهند. هر خطا از API مدیریت داده (Data Manager API) ممکن است چندین پیام بار داده استاندارد جزئیات داشته باشد. کتابخانه‌های کلاینت API مدیریت داده دارای متدهای کمکی برای دریافت بارهای داده استاندارد از یک خطا هستند.

    صرف نظر از کد خطا، توصیه می‌کنیم که بارهای داده ErrorInfo ، RequestInfo ، Help و LocalizedMessage را بررسی و گزارش کنید.

    • ErrorInfo اطلاعاتی دارد که ممکن است در سایر فایل‌های مخرب وجود نداشته باشد.
    • RequestInfo شناسه درخواست را دارد که در صورت نیاز به تماس با پشتیبانی مفید است.
    • Help و LocalizedMessage حاوی لینک‌ها و جزئیات دیگری هستند که به شما در رفع خطا کمک می‌کنند.

    علاوه بر این، پیلودهای BadRequest ، QuotaFailure و RetryInfo برای کدهای خطای خاص مفید هستند:

    • اگر کد وضعیت INVALID_ARGUMENT است، برای اطلاع از اینکه کدام فیلدها باعث خطا شده‌اند، فایل اجرایی BadRequest را بررسی کنید.
    • اگر کد وضعیت RESOURCE_EXHAUSTED است، برای اطلاعات سهمیه و توصیه تأخیر در تلاش مجدد، کدهای QuotaFailure و RetryInfo را بررسی کنید.

بارهای جزئیات استاندارد

رایج‌ترین بارهای جزئیات استاندارد برای رابط برنامه‌نویسی کاربردی مدیریت داده عبارتند از:

BadRequest

وقتی درخواستی با INVALID_ARGUMENT (کد وضعیت HTTP 400 ) با شکست مواجه می‌شود، وجود بار داده BadRequest را بررسی کنید.

یک پیام 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

وقتی درخواستی با RESOURCE_EXHAUSTED (کد وضعیت HTTP 429 ) با شکست مواجه می‌شود، وجود Payloadهای QuotaFailure و RetryInfo را بررسی کنید.

پیام QuotaFailure نشان می‌دهد که یا یک منبع به اتمام رسیده است (برای مثال، شما از سهمیه خود فراتر رفته‌اید)، یا سیستم بیش از حد بارگذاری شده است. لیست violations را بررسی کنید تا مشخص شود کدام سهمیه‌ها بیش از حد شده‌اند.

این خطا همچنین ممکن است حاوی یک پیام RetryInfo باشد که نشان دهنده‌ی توصیه‌ی retry_delay برای تلاش مجدد درخواست است.

RequestInfo

هر زمان که درخواستی با شکست مواجه می‌شود، payload مربوط به 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.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 که در آن 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"
          }
        ]
      },
      ...
    ]
  }
}

جزئیات خطای دسترسی

اگر از یکی از کتابخانه‌های کلاینت استفاده می‌کنید، از متدهای کمکی برای دریافت بارهای داده استاندارد استفاده کنید.

دات نت

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
        {
            // ...
        }
    }
}

جاوا

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 باشید. هر بسته داده استاندارد حاوی اطلاعاتی است که به شما در درک علت خطا کمک می‌کند.
تشخیص خطاهای کلاینت از خطاهای سرور

مشخص کنید که آیا خطا ناشی از مشکلی در پیاده‌سازی شما (کلاینت) است یا مشکلی در API (سرور).

  • خطاهای کلاینت: کدهایی مانند INVALID_ARGUMENT ، NOT_FOUND ، PERMISSION_DENIED ، FAILED_PRECONDITION ، UNAUTHENTICATED . این کدها نیاز به تغییراتی در درخواست یا وضعیت/اعتبارنامه‌های برنامه شما دارند. بدون رسیدگی به مشکل، درخواست را دوباره امتحان نکنید.
  • خطاهای سرور: کدهایی مانند UNAVAILABLE ، INTERNAL ، DEADLINE_EXCEEDED ، UNKNOWN . این کدها نشان دهنده یک مشکل موقت در سرویس API هستند.
پیاده‌سازی استراتژی تلاش مجدد

بررسی کنید که آیا خطا قابل تکرار است یا خیر، و از یک استراتژی تکرار استفاده کنید.

  • فقط برای خطاهای گذرای سرور مانند UNAVAILABLE ، DEADLINE_EXCEEDED ، INTERNAL ، UNKNOWN و ABORTED دوباره امتحان کنید.
  • از یک الگوریتم بازگشت نمایی برای انتظار برای دوره‌های افزایشی بین تلاش‌های مجدد استفاده کنید. این به جلوگیری از تحت فشار قرار گرفتن یک سرویس از قبل تحت فشار کمک می‌کند. به عنوان مثال، ۱ ثانیه، سپس ۲ ثانیه، سپس ۴ ثانیه صبر کنید و این کار را تا حداکثر تعداد تلاش‌های مجدد یا کل زمان انتظار ادامه دهید.
  • برای جلوگیری از مشکل «گله رعدآسا» که در آن بسیاری از کلاینت‌ها به‌طور همزمان دوباره تلاش می‌کنند، مقدار تصادفی کمی «جیتر» به تأخیرهای برگشتی اضافه کنید.
کاملاً وارد شوید

پاسخ کامل خطا، شامل تمام جزئیات استاندارد payloads، به ویژه شناسه درخواست را ثبت کنید. این اطلاعات برای اشکال‌زدایی و گزارش مشکلات به پشتیبانی گوگل در صورت نیاز ضروری است.

ارائه بازخورد کاربر

بر اساس کدها و پیام‌های موجود در بسته‌های داده استاندارد ، بازخورد واضح و مفیدی را به کاربران برنامه خود ارائه دهید. برای مثال، به جای اینکه فقط بگویید «خطایی رخ داده است»، می‌توانید بگویید «شناسه تراکنش از دست رفته است» یا «شناسه حساب مقصد پیدا نشد».

با پیروی از این دستورالعمل‌ها، می‌توانید خطاهایی را که توسط رابط برنامه‌نویسی کاربردی مدیریت داده (Data Manager API) برگردانده می‌شوند، به طور مؤثر تشخیص داده و مدیریت کنید و به برنامه‌های پایدارتر و کاربرپسندتری منجر شوید.