API ত্রুটিগুলি বুঝুন

এই নির্দেশিকাটি ব্যাখ্যা করে যে ডেটা ম্যানেজার এপিআই কীভাবে ত্রুটিগুলি পরিচালনা করে এবং জানায়। এপিআই ত্রুটিগুলির গঠন এবং অর্থ বোঝা শক্তিশালী অ্যাপ্লিকেশন তৈরির জন্য অত্যন্ত গুরুত্বপূর্ণ, যা ভুল ইনপুট থেকে শুরু করে পরিষেবার সাময়িক অনুপলব্ধতার মতো সমস্যাগুলি সুন্দরভাবে সামলাতে পারে।

ডেটা ম্যানেজার এপিআই স্ট্যান্ডার্ড গুগল এপিআই এরর মডেল অনুসরণ করে, যা gRPC স্ট্যাটাস কোডের উপর ভিত্তি করে তৈরি। প্রতিটি এপিআই রেসপন্স, যার ফলে কোনো এরর হয়, তাতে একটি Status অবজেক্ট থাকে, যাতে নিম্নলিখিত বিষয়গুলো উল্লেখ থাকে:

  • একটি সাংখ্যিক ত্রুটি কোড।
  • একটি ত্রুটি বার্তা।
  • ঐচ্ছিক, অতিরিক্ত ত্রুটির বিবরণ।

ক্যানোনিকাল ত্রুটি কোড

ডেটা ম্যানেজার এপিআই gRPC এবং HTTP দ্বারা সংজ্ঞায়িত কিছু প্রমিত ত্রুটি কোড ব্যবহার করে। এই কোডগুলো ত্রুটির ধরন সম্পর্কে একটি উচ্চ-স্তরের ধারণা দেয়। সমস্যার মৌলিক প্রকৃতি বোঝার জন্য আপনার সর্বদা প্রথমে এই কোডটি পরীক্ষা করা উচিত।

এই কোডগুলো সম্পর্কে আরও বিস্তারিত জানতে, এপিআই ডিজাইন গাইড - ত্রুটি কোডসমূহ দেখুন।

ত্রুটিগুলি পরিচালনা করুন

কোনো অনুরোধ ব্যর্থ হলে এই পদক্ষেপগুলো অনুসরণ করুন:

  1. ত্রুটির ধরণ জানতে এরর কোডটি যাচাই করুন।

    • আপনি যদি gRPC ব্যবহার করেন, তাহলে এরর কোডটি Status এর code ফিল্ডে থাকে। আপনি যদি কোনো ক্লায়েন্ট লাইব্রেরি ব্যবহার করেন , তবে এটি এরর কোডটির সাথে সঙ্গতিপূর্ণ একটি নির্দিষ্ট ধরনের এক্সেপশন থ্রো করতে পারে। উদাহরণস্বরূপ, জাভার ক্লায়েন্ট লাইব্রেরিটি com.google.api.gax.rpc.InvalidArgumentException থ্রো করে, যদি এরর কোডটি INVALID_ARGUMENT হয়।
    • আপনি যদি REST ব্যবহার করেন, তাহলে এরর রেসপন্সের error.status অংশে এরর কোডটি থাকে এবং এর সংশ্লিষ্ট HTTP স্ট্যাটাসটি error.code অংশে থাকে।
  2. এরর কোডের জন্য স্ট্যান্ডার্ড ডিটেইল পেলোডটি পরীক্ষা করুন। স্ট্যান্ডার্ড ডিটেইল পেলোডগুলো হলো গুগল এপিআই (Google APIs) থেকে আসা এররের জন্য একগুচ্ছ মেসেজ । এগুলো আপনাকে একটি সুসংগঠিত এবং সামঞ্জস্যপূর্ণ উপায়ে এররের বিস্তারিত তথ্য দেয়। ডেটা ম্যানেজার এপিআই (Data Manager API) থেকে আসা প্রতিটি এররের একাধিক স্ট্যান্ডার্ড ডিটেইল পেলোড মেসেজ থাকতে পারে। ডেটা ম্যানেজার এপিআই ক্লায়েন্ট লাইব্রেরিগুলোতে কোনো এরর থেকে স্ট্যান্ডার্ড ডিটেইল পেলোডগুলো পাওয়ার জন্য হেল্পার মেথড রয়েছে

    এরর কোড যাই হোক না কেন, আমরা আপনাকে ErrorInfo , RequestInfo , Help , এবং LocalizedMessage পেলোডগুলো চেক করতে এবং লগ করতে পরামর্শ দিই।

    • ErrorInfo এমন তথ্য থাকে যা অন্য পেলোডগুলিতে নাও থাকতে পারে।
    • RequestInfo রিকোয়েস্ট আইডি থাকে, যা সাপোর্টের সাথে যোগাযোগ করার প্রয়োজনে সহায়ক হয়।
    • ত্রুটিটি সমাধান করার জন্য Help এবং LocalizedMessage লিঙ্ক ও অন্যান্য বিবরণ রয়েছে।

    এছাড়াও, BadRequest পেলোডটি INVALID_ARGUMENT ত্রুটির ক্ষেত্রে উপযোগী, কারণ এটি কোন ফিল্ডগুলোর কারণে ত্রুটিটি ঘটেছে সে সম্পর্কে তথ্য প্রদান করে।

স্ট্যান্ডার্ড বিস্তারিত পেলোড

ডেটা ম্যানেজার এপিআই-এর জন্য সবচেয়ে সাধারণ স্ট্যান্ডার্ড ডিটেইল পেলোডগুলো হলো:

BadRequest

যখন কোনো অনুরোধ INVALID_ARGUMENT (HTTP স্ট্যাটাস কোড 400 ) এর কারণে ব্যর্থ হয়, তখন BadRequest পেলোডটি পরীক্ষা করুন।

একটি BadRequest বার্তা দেখায় যে অনুরোধটিতে ভুল মান সহ ফিল্ড ছিল, অথবা একটি প্রয়োজনীয় ফিল্ডের জন্য মান অনুপস্থিত ছিল। কোন ফিল্ডগুলিতে ত্রুটি আছে তা খুঁজে বের করতে BadRequest এর field_violations তালিকাটি দেখুন। প্রতিটি field_violations এন্ট্রিতে ত্রুটিটি সমাধান করতে সাহায্য করার জন্য তথ্য রয়েছে:

field

অনুরোধে ফিল্ডটির অবস্থান, ক্যামেল কেস পাথ সিনট্যাক্স ব্যবহার করে।

যদি কোনো পাথ কোনো তালিকার কোনো আইটেমকে নির্দেশ করে (একটি repeated ফিল্ড), তাহলে তালিকার নামের পরে বর্গাকার বন্ধনীতে ( [...] ) তার সূচকটি দেখানো হয়।

উদাহরণস্বরূপ, destinations[0].operating_account.account_id হল destinations তালিকার প্রথম আইটেমের operating_account account_id

description

মানটি কেন ত্রুটির কারণ হয়েছিল তার ব্যাখ্যা।

reason

ErrorReason enum, যেমন INVALID_HEX_ENCODING বা INVALID_CURRENCY_CODE

BadRequest এর উদাহরণ

এখানে BadRequest মেসেজ সহ একটি INVALID_ARGUMENT এররের জন্য একটি নমুনা প্রতিক্রিয়া দেওয়া হল। field_violations দেখাচ্ছে যে ত্রুটিটি একটি accountId যা সংখ্যা নয়। field value destinations[0].login_account.account_id দেখাচ্ছে যে field violation সহ accountId টি destinations তালিকার প্রথম আইটেমের login_account এ রয়েছে।

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

এখানে BadRequest মেসেজ সহ একটি INVALID_ARGUMENT এরর থেকে প্রাপ্ত আরেকটি নমুনা প্রতিক্রিয়া দেওয়া হলো। এক্ষেত্রে, 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 থাকে, যা আপনার API অনুরোধটিকে অনন্যভাবে শনাক্ত করে।

{
  "@type": "type.googleapis.com/google.rpc.RequestInfo",
  "requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}

ত্রুটি নথিভুক্ত করার সময় বা সাপোর্টের সাথে যোগাযোগ করার সময়, সমস্যা নির্ণয়ে সহায়তার জন্য রিকোয়েস্ট আইডিটি অবশ্যই উল্লেখ করবেন।

ErrorInfo

অন্যান্য স্ট্যান্ডার্ড ডিটেইল পেলোডগুলিতে অন্তর্ভুক্ত নাও থাকতে পারে এমন অতিরিক্ত তথ্য পেতে ErrorInfo মেসেজটি পরীক্ষা করুন। ErrorInfo পেলোডটিতে ত্রুটি সম্পর্কিত তথ্যসহ একটি metadata ম্যাপ থাকে।

উদাহরণস্বরূপ, এমন একটি গুগল ক্লাউড প্রজেক্টের ক্রেডেনশিয়াল ব্যবহার করার কারণে PERMISSION_DENIED ব্যর্থতার জন্য ErrorInfo দেওয়া হলো, যেখানে ডেটা ম্যানেজার এপিআই (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 পেলোডগুলো দেখুন।

উদাহরণস্বরূপ, এমন একটি গুগল ক্লাউড প্রজেক্টের ক্রেডেনশিয়াল ব্যবহার করার কারণে PERMISSION_DENIED ত্রুটি দেখা দিলে তার জন্য Help এবং LocalizedMessage হলো, যেখানে 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 মতো কোড। এগুলো এপিআই (API) পরিষেবাতে একটি অস্থায়ী সমস্যার ইঙ্গিত দেয়।
পুনরায় চেষ্টা করার কৌশল প্রয়োগ করুন

ত্রুটিটি পুনরায় চেষ্টা করা যাবে কিনা তা নির্ধারণ করুন এবং একটি পুনঃপ্রচেষ্টা কৌশল ব্যবহার করুন।

  • শুধুমাত্র সাময়িক সার্ভার ত্রুটি, যেমন— UNAVAILABLE , DEADLINE_EXCEEDED , INTERNAL , UNKNOWN , এবং ABORTED ক্ষেত্রে পুনরায় চেষ্টা করুন।
  • পুনরায় চেষ্টার মধ্যবর্তী সময় বাড়ানোর জন্য একটি এক্সপোনেনশিয়াল ব্যাকঅফ অ্যালগরিদম ব্যবহার করুন। এটি আগে থেকেই চাপের মধ্যে থাকা একটি সার্ভিসকে অতিরিক্ত ভারাক্রান্ত হওয়া থেকে বাঁচাতে সাহায্য করে। উদাহরণস্বরূপ, প্রথমে ১ সেকেন্ড, তারপর ২ সেকেন্ড, তারপর ৪ সেকেন্ড অপেক্ষা করুন এবং এভাবে সর্বোচ্চ সংখ্যক পুনরায় চেষ্টা বা মোট অপেক্ষার সময় পর্যন্ত তা চালিয়ে যান।
  • "থান্ডারিং হার্ড" সমস্যা, যেখানে অনেক ক্লায়েন্ট একই সাথে পুনরায় চেষ্টা করে, তা প্রতিরোধ করার জন্য ব্যাকঅফ ডিলে-তে সামান্য এলোমেলো পরিমাণ "জিটার" যোগ করুন।
পুঙ্খানুপুঙ্খভাবে লগ করুন

সমস্ত স্ট্যান্ডার্ড ডিটেইল পেলোড সহ সম্পূর্ণ এরর রেসপন্সটি লগ করুন, বিশেষ করে রিকোয়েস্ট আইডি । ডিবাগিং এবং প্রয়োজনে গুগল সাপোর্টে সমস্যা রিপোর্ট করার জন্য এই তথ্য অপরিহার্য।

ব্যবহারকারীর মতামত দিন

স্ট্যান্ডার্ড ডিটেইল পেলোড- এ থাকা কোড এবং মেসেজগুলোর উপর ভিত্তি করে আপনার অ্যাপ্লিকেশনের ব্যবহারকারীদের স্পষ্ট এবং সহায়ক ফিডব্যাক দিন। উদাহরণস্বরূপ, শুধু "একটি ত্রুটি ঘটেছে" বলার পরিবর্তে, আপনি বলতে পারেন "ট্রানজ্যাকশন আইডি অনুপস্থিত ছিল" অথবা "গন্তব্যের অ্যাকাউন্ট আইডি খুঁজে পাওয়া যায়নি।"

এই নির্দেশিকাগুলো অনুসরণ করে, আপনি ডেটা ম্যানেজার এপিআই থেকে প্রাপ্ত ত্রুটিগুলো কার্যকরভাবে নির্ণয় ও সমাধান করতে পারবেন, যার ফলে আরও স্থিতিশীল এবং ব্যবহারকারী-বান্ধব অ্যাপ্লিকেশন তৈরি হবে।