7 মিনিট

করিলেশন আইডি এন্ড-টু-এন্ড: লগে একটি ব্যবহারকারীর অ্যাকশন ট্রেস করুন

Correlation IDs end-to-end দেখায় কিভাবে ফ্রন্টএন্ডে একটি আইডি তৈরি করা হয়, API-গুলোর মধ্য দিয়ে সেটি পাস করা হয় এবং লগে অন্তর্ভুক্ত করা হয় যাতে সাপোর্ট দ্রুত ইস্যুগুলো ট্রেস করতে পারে।

করিলেশন আইডি এন্ড-টু-এন্ড: লগে একটি ব্যবহারকারীর অ্যাকশন ট্রেস করুন

কেন করিলেশন আইডি সাপোর্টের জন্য গুরুত্বপূর্ণ

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

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

মানুষরা প্রায়ই কয়েকটি সমজাতীয় আইডি মিলিয়ে ফেলেন। এখানে পরিষ্কার ভেদাভেদ:

  • Correlation ID: একটি অ্যাকশনের সাথে সম্পর্কিত সবকিছুকে গ্রুপ করে (উদাহরণ: "Save settings").
  • Request ID: একটি নির্দিষ্ট HTTP রিকোয়েস্টকে শনাক্ত করে। রিট্রায় নতুন request ID হয়।
  • Trace ID: ডিস্ট্রিবিউটেড ট্রেসিং টুলগুলোতে ব্যবহৃত; লক্ষ একই, প্রায়ই ট্রেসিং লাইব্রেরি জেনারেট করে।
  • Session ID: একটি ইউজার সেশনকে শনাক্ত করে, বহু অ্যাকশন জুড়ে; একটি নির্দিষ্ট ইনসিডেন্ট ডিবাগ করার জন্য এটা অনেক বড় পরিধির।

ভালো কিভাবে দেখতে লাগে তা সরল: একটি ব্যবহারকারী সমস্যা জানায়, আপনি UI-তে দেখানো (অথবা সাপোর্ট স্ক্রীনে পাওয়া) করিলেশন আইডি চাইলে, দলের যে কেউ মিনিটের মধ্যে পুরো কাহিনী খুঁজে পায়। আপনি ফ্রন্টএন্ড রিকোয়েস্ট, API রেসপন্স, ব্যাকএন্ড ধাপ এবং ডেটাবেস রেজাল্ট—সবকিছুই একই আইডি দিয়ে বাঁধা দেখতে পাবেন।

করিলেশন আইডির কনভেনশন নির্ধারণ করুন

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

একটি canonical নাম থেকে শুরু করুন এবং তাদেই সব জায়গায় ব্যবহার করুন। সাধারণ পছন্দ একটি HTTP হেডার, যেমন X-Correlation-Id, এবং একটি স্ট্রাকচার্ড লগ ফিল্ড যেমন correlation_id. একটি বানান এবং কেসিং বেছে নিন, ডকুমেন্ট করুন, এবং নিশ্চিত করুন যে আপনার রিভার্স প্রক্সি বা গেটওয়ে হেডারটি বদলাবে বা ড্রপ করবে না।

এমন একটি ফরম্যাট বেছে নিন যা তৈরি করা সহজ এবং টিকেট/চ্যাটে শেয়ার করা নিরাপদ। UUID গুলো ভালো কারণ এগুলো ইউনিক এবং সাধারণ। আইডিটি কপি করা সুবিধাজনক হবে এমন ছোট রাখুন, কিন্তু এত ছোট না যাতে কোলিজনের ঝুঁকি থাকে। ধারাবাহিকতা কৃতিত্বের চেয়ে বেশি মূল্যবান।

ফলত, সিদ্ধান্ত নিন আইডি কোথায় থাকতে হবে যাতে মানুষ সত্যিই ব্যবহার করতে পারে। বাস্তবে এর মানে হল: এটি রিকোয়েস্ট, লগ, এবং এরর আউটপুটে থাকা উচিত, এবং আপনার টিম যে টুল ব্যবহার করে সেখানে সার্চেবল থাকা উচিত।

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

একটি কঠিন নিয়ম: আইডির মধ্যে কখনই ব্যক্তিগত তথ্য রাখবেন না। ইমেইল, ফোন নম্বর, ইউজার আইডি বা অর্ডার নম্বর বাদ দিন। যদি সেই প্রসঙ্গ দরকার হয়, আলাদা ফিল্ডে লগ করুন এবং প্রাইভেসি কন্ট্রোল প্রয়োগ করুন।

ফ্রন্টএন্ডে আইডি জেনারেট করা (প্রায়োগিক উপায়)

শুরু করার সবচেয়ে সহজ জায়গা হল যখন ব্যবহারকারী যেই অ্যাকশনটি শুরু করে—"Save" ক্লিক করা, ফর্ম সাবমিট করা, বা এমন কোনো ফ্লো যা একাধিক রিকোয়েস্ট চালু করে। যদি আপনি ব্যাকএন্ডকে অপেক্ষা করে আইডি তৈরির জন্য দেন, সাধারণত গল্পের প্রথম অংশ হারিয়ে যায় (UI ত্রুটি, রিটারাই, বাতিল রিকোয়েস্ট)।

র‍্যান্ডম, ইউনিক ফরম্যাট ব্যবহার করুন। UUID v4 সাধারণ পছন্দ কারণ আধুনিক ব্রাউজারে সহজে জেনারেট করা যায় এবং কোলিজন সম্ভাবনা কম। এটিকে opaque রাখুন (কোন ইউজারনেম, ইমেইল বা টাইমস্ট্যাম্প না) যাতে হেডার ও লগে ব্যক্তিগত তথ্য ফাঁস না হয়।

একটি ওয়ার্কফ্লো-এর জন্য আইডি তৈরি ও রাখা

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

사용자 একই অ্যশন আবার শুরু করলে, দ্বিতীয় চেষ্টার জন্য নতুন করিলেশন আইডি জেনারেট করুন। এতে সাপোর্ট বুঝতে পারবে "একই ক্লিক রিট্রাই করা" আর "দুই আলাদা সাবমিশন" আলাদা।

ওই ওয়ার্কফ্লো দ্বারা করা প্রতিটি রিকোয়েস্টে এটাকে যুক্ত করুন

ওয়ার্কফ্লো দ্বারা ট্রিগার হওয়া প্রতিটি API কল-এ আইডি যোগ করুন, সাধারণত X-Correlation-ID-এর মতো একটি হেডার ব্যবহার করে। যদি আপনার একটি শেয়ার্ড API ক্লায়েন্ট থাকে (fetch র‍্যাপার, Axios ইনস্ট্যান্স ইত্যাদি), একবার আইডিটি পাস করুন এবং ক্লায়েন্ট তা সব কল-এ ইনজেক্ট করুক।

// 1) when the user action starts
const correlationId = crypto.randomUUID(); // UUID v4 in modern browsers

// 2) pass it to every request in this workflow
await api.post('/orders', payload, {
  headers: { 'X-Correlation-ID': correlationId }
});

await api.get('/orders/summary', {
  headers: { 'X-Correlation-ID': correlationId }
});

যদি আপনার UI ব্যাকগ্রাউন্ডে অননুমোদিত রিকোয়েস্ট করে (পোলিং, অ্যানালিটিক্স, অটোরিফ্রেশ), ঐগুলোর জন্য ওয়ার্কফ্লো আইডি পুনরায় ব্যবহার করবেন না। করিলেশন আইডিগুলোকে ফোকাসেড রাখুন যাতে এক আইডি এক গল্প বলে।

আপনার API-গুলোতে আইডি নির্ভরযোগ্যভাবে পাঠানো

ব্রাউজারে আইডি জেনারেট হলে কাজটি সহজ: এটি প্রতিটি রিকোয়েস্টের সঙ্গে ফ্রন্টএন্ড ছাড়বে এবং প্রতিটি API বাউন্ডারির কাছে অপরিবর্তিত পৌঁছাতে হবে। নতুন এন্ডপয়েন্ট, ক্লায়েন্ট বা মিডলওয়্যার যোগ করলে এখানে বিভ্রাট ঘটে।

সবচেয়ে নিরাপদ ডিফল্ট হচ্ছে প্রতিটি কল-এ একটি HTTP হেডার (উদাহরণ X-Correlation-Id)। হেডারগুলো এক জায়গায় অ্যাড করা সহজ (fetch র‍্যাপার, Axios ইন্টারসেপ্টর, মোবাইল নেটওয়ার্কিং লেয়ার) এবং পে-লোড বদলানোর প্রয়োজন থাকে না।

যদি ক্রস-অরিজিন রিকোয়েস্ট থাকে, নিশ্চিত করুন আপনার API ঐ হেডারটি অনুমোদন করে। নাহলে ব্রাউজার তা নীরবে ব্লক করতে পারে এবং আপনি ভাববেন যে আপনি এটা পাঠাচ্ছেন, অথচ পাঠানো হচ্ছে না।

কখনো কখনো যদি ID-টি কুয়েরি স্ট্রিং বা রিকোয়েস্ট বডিতে রাখতে হয় (কিছু থার্ড-পার্টি টুল বা ফাইল আপলোডের কারণে), তবে ধারাবাহিক রাখুন এবং ডকুমেন্ট করুন। একটি ফিল্ড নাম বেছে নিন এবং সব জায়গায় তা ব্যবহার করুন। correlationId, requestId, এবং cid মিশিয়ে ব্যবহার করবেন না।

রিটারিও একটি কমন ফাঁদ। একই ব্যবহারকারীর অ্যাকশন থাকলে একটি রিট্রাই একই করিলেশন আইডি রাখা উচিত। উদাহরণ: ব্যবহারকারী "Save" ক্লিক করে, নেটওয়ার্ক পড়ে যায়, ক্লায়েন্ট POST রিট্রাই করে। সাপোর্ট একটিবারের সংযুক্ত ট্রেইল দেখতে পাবে, তিনটি আলাদা নয়। নতুন ব্যবহারকারী ক্লিক (অথবা নতুন ব্যাকগ্রাউন্ড জব) হলে নতুন আইডি দিন।

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

দ্রুত একটা রিলায়বিলিটি চেক চাইলে সরল রাখুন:

  • একটি শেয়ার্ড ক্লায়েন্ট হেল্পার প্রতিটি রিকোয়েস্টে হেডার যোগ করুক।
  • রিট্রায় একই অ্যাকশনের জন্য একই আইডি পুনরায় ব্যবহার করুক।
  • কোন বডি/কুয়েরি ব্যাকফল ব্যবহার হলে একটি ডকুমেন্ট করা ফিল্ড নাম ব্যবহার করা হোক।
  • ওয়েবসকেট মেসেজে স্পষ্টভাবে correlationId ফিল্ড থাকুক।

API এন্ট্রি পয়েন্ট আচরণ ঠিক করুন

Deploy a traceable app faster
Go from plan to a running app without setting up servers yourself.

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

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

খারাপ মান লোগে ঢুকছে না তা দেখতে লাইট-ভ্যালিডেশন করুন। তবে বেশি কড়া নয়: দৈর্ঘ্য ও অনুমোদিত কির্দার পরীক্ষা করুন, কিন্তু এমন কঠোর ফরম্যাট ব্যবহার করে বাস্তব ট্রাফিক বাতিল করবেন না। উদাহরণস্বরূপ, 16-64 অক্ষরের মধ্যে এবং অক্ষর, সংখ্যা, ড্যাশ, আন্ডারস্কোর erlauben করুন। যদি ভ্যালু ভ্যালিডেশন না পাস করে, একটি নতুন আইডি দিয়ে ফেলুন এবং চলুন।

কলে আইডি কলে কলে ভিজিবল করুন। সবসময় রেসপন্স হেডার-এ সেট করুন, এবং এরর বডিতেও অন্তর্ভুক্ত করুন। এভাবে ব্যবহারকারী UI থেকে এটি কপি করতে পারবে, অথবা সাপোর্ট এজেন্ট চাইলে সঠিক লগ ট্রেইল খুঁজে পাবে।

প্রায়োগিক এজ নীতি দেখলে এমন হওয়া উচিত:

  • অনুরোধ থেকে X-Correlation-ID পড়ুন (বা আপনার নির্বাচিত হেডার)।
  • অনুপস্থিত বা অবৈধ হলে, একটি নতুন আইডি তৈরি করে রিকোয়েস্ট কনটেক্সটে সংযুক্ত করুন।
  • প্রতিটি রেসপন্সে, এররসহ, X-Correlation-ID যোগ করুন।
  • JSON এররের সময়, পে-লোডে আইডি ইকো করুন।

উদাহরণ এরর পে-লোড (যা সাপোর্ট টিকেট বা স্ক্রিনশটে দেখা উচিত):

{
  "error": {
    "code": "PAYMENT_FAILED",
    "message": "We could not confirm the payment.",
    "correlation_id": "c3a8f2d1-9b24-4c61-8c4a-2a7c1b9c2f61"
  }
}

ব্যাকএন্ড সার্ভিস জুড়ে আইডি প্রোপাগেট করুন

রিকোয়েস্ট আপনার ব্যাকএন্ডে পৌঁছালে, করিলেশন আইডিকে রিকোয়েস্ট কনটেক্সটের অংশ হিসেবে বিবেচনা করুন—কোনও গ্লোবাল ভ্যারিয়েবলে রাখবেন না। গ্লোবাল ভেযারগুলো তখন ভেঙে পড়ে যখন একই সময়ে দুইটি রিকোয়েস্ট হ্যান্ডেল করা হয়, অথবা অ্যাসিঙ্ক কাজ রেসপন্সের পরে চালিয়ে গেলে।

একটি স্কেলেবল নিয়ম: যে প্রতিটি ফাংশন লগ করতে পারে বা অন্য সার্ভিস কল করতে পারে তা কনটেক্সট পাস করে নেবে যাতে আইডি থাকে। Go সার্ভিসগুলোতে সাধারণত context.Context হ্যান্ডলার, বিজনেস লজিক, এবং ক্লায়েন্ট কোডে নীচে নীচে পাস করাই হয়।

যখন সার্ভিস A সার্ভিস B-কে কল করে, একই আইডি আউটগোয়িং রিকোয়েস্টে কপি করুন। মাঝপথে নতুন আইডি জেনারেট করবেন না যদি না আপনি মূল আইডিটা আলাদাভাবে (উদাহরণ: parent_correlation_id) হিসেবে রাখেন। আইডি বদলে দিলে সাপোর্ট সেই এক থ্রেড ধরে রাখতে পারবে না।

প্রোপাগেশন প্রায়ই মিস হয় কিছু পূর্বাভাসযোগ্য জায়গায়: রিকোয়েস্ট চলাকালীন কিক করা ব্যাকগ্রাউন্ড জব, ক্লায়েন্ট লাইব্রেরির ভিতরের রিট্রাই, পরে ট্রিগার হওয়া webhook, এবং ফ্যান-আউট কল। যেকোনও অ্যাসিঙ্ক মেসেজ (কিউ/জব) আইডি বহন করা উচিত, এবং রিট্রাই লজিক সেটি সংরক্ষণ করবে।

লগগুলো স্ট্রাকচার্ড হওয়া উচিত এবং একটি স্থির ফিল্ড নাম যেমন correlation_id ব্যবহার করুন। এক বানানই বেছে নিন এবং সব জায়গায় রাখুন। requestId, req_id, এবং traceId মেশাবেন না যদি না আপনি স্পষ্ট ম্যাপিংও দেন।

সম্ভব হলে, ডেটাবেজ ভিজিবিলিটিতেও আইডি অন্তর্ভুক্ত করুন। একটি প্রয়োগিক উপায় হচ্ছে তা কুয়েরি কমেন্ট বা সেশন মেটাডেটায় যুক্ত করা যাতে স্লো কুয়েরি লগে আইডি দেখা যায়। কেউ যদি বলুক "Save বাটন ১০ সেকেন্ড আটকে ছিল", সাপোর্ট correlation_id=abc123 সার্চ করে API লগ, ডাউনস্ট্রিম সার্ভিস কল এবং সেটা ধীর করে দেয়া স্লো SQL স্টেটমেন্ট দেখতে পাবে।

মানুষদের কাজে লাগবে এমনভাবে লগে আইডি অন্তর্ভুক্ত করুন

একটি করিলেশন আইডি তখনই সাহায্য করে যখন মানুষ তা খুঁজে পেতে পারে এবং অনুসরণ করতে পারে। এটিকে প্রথম-শ্রেণীর লগ ফিল্ড করুন (মেসেজ স্ট্রিংয়ের ভেতরে লুকিয়ে না রেখে), এবং সার্ভিস জুড়ে লগ এন্ট্রির বাকি অংশ সঙ্গত রাখুন।

লগ ফিল্ড যা আইডিকে ব্যবহারযোগ্য করে

করিলেশন আইডির সাথে কয়েকটি ছোট কিন্তু গুরুত্বপূর্ণ ফিল্ড জোড়া রাখুন যা জিজ্ঞাসার উত্তর দেয়: কখন, কোথায়, কি, এবং কে (ইউজার-সেফ ভাবে)। অধিকাংশ টিমের জন্য সেটি হচ্ছে:

  • timestamp (টাইমজোনসহ)
  • service এবং env (api, worker, prod, staging)
  • route (অথবা অপারেশন নাম) এবং method
  • status এবং duration_ms
  • একটি ইউজার-সেফ শনাক্তকারী (উদাহরণ account_id বা হ্যাশ করা ইউজার আইডি, ইমেইল নয়)

এর মাধ্যমে সাপোর্ট আইডি দিয়ে সার্চ করে নিশ্চিত হবে তারা সঠিক রিকোয়েস্ট দেখছে এবং কোন সার্ভিস হ্যান্ডেল করেছে তা দেখতে পারবে।

শুরু, সাফল্য এবং ব্যর্থতায় কি লগ করা উচিত

প্রতিটি রিকোয়েস্টে কয়েকটা শক্তিশালী ব্রেডক্রাম্ব রাখুন, পুরো ট্রান্সক্রিপ্ট না।

  • Start: correlation ID, route, সেফ ইউজার আইডেন্টিফায়ার, এবং প্রধান ইনপুটগুলোর সংক্ষিপ্ত বিবরণ।
  • Success: correlation ID, status, duration, এবং সংক্ষিপ্ত আউটকাম (উদাহরণ rows=12).
  • Failure: correlation ID, error টাইপ, সেফ প্রসঙ্গ, এবং যেখানে হয়েছে (হ্যান্ডলার, ডিপেন্ডেন্সি)।

নয়েজি লগ এড়াতে, ডিফল্টে ডিবাগ-লেভেল বিস্তারিত রাখবেন না এবং শুধুমাত্র সেই ইভেন্টগুলোকে info-লে প্রবেশ করান যা সাহায্য করে "কোথায় ব্যর্থ হয়েছে?" প্রশ্নের উত্তর দিতে। যদি কোনো লাইন সমস্যা লোকেট করতে বা ইমপ্যাক্ট পরিমাপ করতে সাহায্য না করে, তবে সেটি info-লেভেলে থাকা উচিত নয়।

রেড্যাকশনও গঠন যতটা গুরুত্বপূর্ণ। কখনই PII করিলেশন আইডি বা লগে রাখবেন না: ইমেইল, নাম, ফোন নম্বর, পূর্ণ ঠিকানা বা র ক টোকেন। যদি একটি ইউজার শনাক্ত করতে হয়, একটি অভ্যন্তরীণ আইডি বা ওয়ান-ওয়ে হ্যাশ লগ করুন।

উদাহরণ: UI থেকে ডেটাবেস পর্যন্ত একটি ব্যবহারকারী রিপোর্ট ট্রেস করা

Debug without risky releases
Use snapshots and rollback so debugging changes are easy to undo.

একটি ব্যবহারকারী সাপোর্ট-এ লিখলেন: "Checkout failed when I clicked Pay." শ্রেষ্ঠ ফলো-আপ প্রশ্ন সহজ: "এরর স্ক্রিনে দেখানো করিলেশন আইডি কি কপি করে দিতে পারেন?" তারা উত্তর দিল cid=9f3c2b1f6a7a4c2f

এখন সাপোর্টের কাছে একটি হ্যান্ডেল আছে যা UI, API এবং ডেটাবেস কাজগুলোকে সংযুক্ত করে। লক্ষ্য হল যে ঐ অ্যেশনের প্রতিটি লগ লাইনে একই আইডি থাকা উচিত।

সাপোর্ট 9f3c2b1f6a7a4c2f সার্চ করে প্রবাহ দেখে:

frontend  INFO  cid=9f3c2b1f6a7a4c2f event="checkout_submit" cart=3 items
api       INFO  cid=9f3c2b1f6a7a4c2f method=POST path=/api/checkout user=1842
api       ERROR cid=9f3c2b1f6a7a4c2f msg="payment failed" provider=stripe status=502

সেখান থেকে ইঞ্জিনিয়ার একই আইডি নিয়ে পরবর্তী হপে যায়। মূল বিষয় হলো ব্যাকএন্ড সার্ভিস কলগুলো (এবং কিউ জব) আইডি ফরওয়ার্ড করে।

payments  INFO  cid=9f3c2b1f6a7a4c2f action="charge" amount=49.00 currency=USD
payments  ERROR cid=9f3c2b1f6a7a4c2f err="timeout" upstream=stripe timeout_ms=3000
db        INFO  cid=9f3c2b1f6a7a4c2f query="insert into failed_payments" rows=1

এখন সমস্যা স্পষ্ট: পেমেন্ট সার্ভিস ৩ সেকেন্ড পরে টাইমআউট করেছে, এবং একটি ব্যর্থতা রেকর্ড লেখা হয়েছে। ইঞ্জিনিয়ার সাম্প্রতিক ডিপ্লয় পরীক্ষা করতে পারবেন, নিশ্চিত করবেন টাইমআউট সেটিং পরিবর্তন হয়েছে কিনা, এবং দেখা হবে রিট্রাই হচ্ছে কি না।

লুপ বন্ধ করতে চারটা চেক করুন:

  • কারণ ঠিক করুন (উদাহরণ, টাইমআউট সামঞ্জস্য করুন এবং একটি সেফ রিট্রাই যোগ করুন)।
  • নিশ্চিত করুন ব্যবহারকারী-ফেসিং এররগুলোতে করিলেশন আইডি আছে।
  • একই এরর প্যাটার্ন নতুন আইডি দিয়ে আসছে কি না মনিটর করুন।
  • নিশ্চিত করুন আইডি প্রতিটি হপে টিকে আছে (workers এবং কিউ মেসেজসহ)।

সাধারণ ভুল ও কিভাবে এড়াবেন

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

একটি ক্লাসিক ভুল হল প্রতিটি হপে একটি নতুন আইডি জেনারেট করা। যদি ব্রাউজার একটি আইডি পাঠায়, আপনার API গেটওয়ে সেটি রেখে দিবে—বদলাবে না। যদি অভ্যন্তরীণভাবে একটি আইডির প্রয়োজন হয় (কিউ মেসেজ বা ব্যাকগ্রাউন্ড জবের জন্য), তাহলে মূলটিকে parent ফিল্ড হিসেবে রাখুন যাতে গল্পটি সংযুক্ত থাকে।

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

"নেমিং কাহোস" সমস্যা এড়ান

আইডি সব জায়গায় থাকলেও সার্চ করা কঠিন হয়ে যায় যদি প্রতিটি সার্ভিস ভিন্ন ফিল্ড নাম বা ফরম্যাট ব্যবহার করে। একটি নাম বেছে নিন এবং ফ্রন্টএন্ড, API, এবং লগে সবাই তা অনুসরণ করুক (উদাহরণ correlation_id)। একই ফরম্যাট (প্রায়শই UUID) ব্যবহার করুন, এবং কপি-পেস্ট কাজ করার জন্য কেস-সেনসিটিভ থাকুক।

যদি কোনও কিছু ভেঙে যায়, আইডি হারাবে। যদি API 500 দেয় বা ভ্যালিডেশন এরর হয়, রেসপন্সে করিলেশন আইডি অন্তর্ভুক্ত করুন (এবং আদর্শভাবে রেসপন্স হেডারেও)। এতে ব্যবহারকারী সাপোর্ট চ্যাটে আইডি পেস্ট করে পুরো ট্রেইল ট্রেস করাতে পারবে।

দ্রুত পরীক্ষা: কি একটি সাপোর্ট ব্যক্তি এক আইডি নিয়ে শুরু করে এবং প্রতিটি সংযুক্ত লগ লাইনে তা অনুসরণ করতে পারে—ব্যর্থতাসহ? যদি হয়, আপনি ভাল পথে আছেন।

এন্ড-টু-এন্ড কভারেজ যাচাই করার দ্রুত চেকলিস্ট

Get rewarded for building
Share what you build on Koder.ai or refer teammates to get credits.

এটি একটি স্যানিটি চেক হিসেবে ব্যবহার করুন আগে আপনি সাপোর্টকে বলবেন "লগ সার্চ করো"। এই ব্যবস্থা তখনই কাজ করে যখন প্রতিটি হপ একই নিয়ম মেনে চলে।

অবশ্যই পাস করা চেকগুলো

  • আপনার একটি আইডি ফরম্যাট এবং একটি হেডার নাম আছে, যা সবখানে ব্যবহার হয় (ফ্রন্টএন্ড, গেটওয়ে, API, workers)।
  • ফ্রন্টএন্ড একটি ব্যবহারকারীর অ্যাকশনের শুরুতে আইডি তৈরি (বা গ্রহণ) করে এবং অ্যাকশন শেষ না হওয়া পর্যন্ত স্থিতিশীল রাখে।
  • আপনার API এন্ট্রি পয়েন্ট অনুপস্থিত হলে আইডি তৈরি করে এবং সর্বদা রেসপন্স হেডারে তা ফিরিয়ে দেয়।
  • প্রতিটি ব্যাকএন্ড সার্ভিস correlation_id-কে রিকোয়েস্ট-সংক্রান্ত লগে স্ট্রাকচার্ড ফিল্ড হিসেবে অন্তর্ভুক্ত করে।
  • অন-কল একজন সহজে একটি আইডি কপি করে লগ সার্চে পেস্ট করে পুরো পথ কয়েক মিনিটের মধ্যে দেখতে পারে: এজ রিকোয়েস্ট, অথ, সার্ভিস কল, ডেটাবেস অপারেশন এবং রিট্রাই।

যদি কোনো চেক ফেল করে, এটি এভাবে ঠিক করুন

সবচেয়ে ছোট পরিবর্তন বেছে নিন যা চেইনকে অবিচ্ছিন্ন রাখে।

  • যদি আইডি মাঝপথে বদলে যায়, অভ্যন্তরীণ সার্ভিসে নতুন আইডি জেনারেট করা বন্ধ করুন। মূল correlation_id রাখুন এবং যদি আরো ডিটেইল দরকার হয় তবে আলাদা span_id যোগ করুন।
  • যদি লগগুলোতে ফিল্ড অনুপস্থিত থাকে, লগিং মিডলওয়্যার যোগ করুন যাতে ইঞ্জিনিয়াররা প্রতিবার মনে না করে ফিল্ড যুক্ত করে।
  • যদি সাপোর্ট আইডি পেতে না পারে, নিশ্চিত করুন UI এরর স্ক্রিনে তা দেখায় এবং গেটওয়ে প্রতিটি রেসপন্সে আইডি ইকো করে।

একটা দ্রুত টেস্ট যা গ্যাপ ধরবে: ডেভটুলস খুলুন, একটি অ্যাকশন ট্রিগার করুন, প্রথম রিকোয়েস্ট থেকে করিলেশন আইডি কপি করুন, তারপর নিশ্চিত করুন আপনি একই ভ্যালু প্রতিটি সম্পর্কিত API রিকোয়েস্টে এবং প্রতিটি সংশ্লিষ্ট লগ লাইনে দেখছেন।

পরবর্তী ধাপ: এটাকে আপনার বিল্ড প্রসেসে অন্তর্ভুক্ত করুন

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

নতুন কোনো এন্ডপয়েন্ট বা UI অ্যাকশনের জন্য আপনার Definition of Done এ একটি ছোট ট্রেসিবিলিটি ধাপ যোগ করুন। কভার করুন কীভাবে আইডি তৈরি (বা পুনরায় ব্যবহার) হবে, ফ্লো চলাকালীন কোথায় থাকবে, কোন হেডার বহন করবে, এবং কোন সার্ভিস হেডার অনুপস্থিত হলে কী করবে।

একটি লাইটওয়েট চেকলিস্ট সাধারণত যথেষ্ট:

  • Frontend: প্রতিটি ব্যবহারকারী অ্যাকশনের জন্য একটি আইডি জেনারেট বা পুনরায় ব্যবহার করুন, এবং সেই অ্যাকশনের সমস্ত API কল-এ এটাকে সংযুক্ত করুন।
  • API entry point: হেডার গ্রহণ করুন, ভ্যালিডেট বা জেনারেট করুন, এবং রেসপন্সে ইকো করুন।
  • Backend: ডাউনস্ট্রিম সার্ভিস ও জবগুলোতে পাঠান, এবং লগে অন্তর্ভুক্ত করুন।
  • Logging: অ্যাপ ও সার্ভিস জুড়ে ফিল্ডের নাম ধারাবাহিক রাখুন (উদাহরণ correlation_id)।
  • Reviews: এমন PR গুলো Reject করুন যা নতুন এন্ডপয়েন্ট যোগ করে কিন্তু টেস্ট দেখায় না যে আইডি লগে উপস্থিত হচ্ছে।

সাপোর্টের জন্যও একটি সহজ স্ক্রিপ্ট থাকা উচিত যাতে ডিবাগ দ্রুত ও পুনরাবৃত্তি যোগ্য হয়। ঠিক করে নিন ব্যবহারকারীর কাছে আইডি কোথায় দেখানো হবে (উদাহরণ, এরর ডায়ালগে একটি "Copy debug ID" বাটন), এবং সাপোর্টকে কি জানতে হবে এবং কোথায় সার্চ করতে হবে তা নথিভুক্ত করুন।

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

যদি আপনি Koder.ai-তে অ্যাপ বানান, তবে আপনার করিলেশন আইডি হেডার এবং লগিং কনভেনশনগুলো Planning Mode-এ লিখে রাখা বরং ভালো—তাহলে জেনারেট করা React ফ্রন্টেন্ড এবং Go সার্ভিসগুলো ডিফল্টভাবে কনসিস্টেন্ট থাকবে।

সাধারণ প্রশ্ন

What is a correlation ID in plain terms?

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

When should I use a correlation ID instead of a session ID or request ID?

যখন আপনি একবারের ঘটনার পুরো পথ দ্রুত ডিবাগ করতে চান—যেমন “Pay বাটনে ক্লিক করলাম এবং ফেইল করেছে”—তখন করিলেশন আইডি ব্যবহার করুন। সেশন আইডি অনেক বড় পরিধির (অনেকগুলো অ্যাকশন) এবং রিকোয়েস্ট আইডি খুব সীমিত (একটি HTTP রিকোয়েস্ট) তাই রিকোয়েস্ট রিটারির সময় বদলে যায়।

Where should the correlation ID be created: frontend or backend?

সর্বোত্তম ডিফল্ট হল ফ্রন্টএন্ডে, যখন ইউজার অ্যাকশন শুরু করে (ফর্ম সাবমিট, বাটন ক্লিক, মাল্টি-স্টেপ ফ্লো)। এতে UI-র আগে ঘটা ত্রুটি, রিটারির তথ্য এবং বাতিল হওয়া রিকোয়েস্টগুলোও ধরে রাখা হয়।

What format should a correlation ID use?

UUID-ধাঁচের এমন একটি অবোধ (opaque) ভ্যালু ব্যবহার করুন যা কপি করা সহজ এবং সাপোর্ট টিকিটে ভাগ করা নিরাপদ। ব্যক্তিগত তথ্য (ইমেইল, অর্ডার নম্বর, টাইমস্ট্যাম্প ইত্যাদি) আইডির মধ্যে রাখবেন না—এগুলো আলাদা লগ ফিল্ডে রাখুন এবং প্রাইভেসি কন্ট্রোল প্রয়োগ করুন।

What header and log field name should we standardize on?

একটি একক ক্যাননিক্যাল হেডার নাম বেছে নিন এবং সব জায়গায় তা ব্যবহার করুন, উদাহরণস্বরূপ X-Correlation-ID। লগে একটি সংগঠিত ফিল্ড হিসেবে একই নাম রাখুন, যেমন correlation_id. ধারাবাহিকতা নামের চেয়ে বেশি গুরুত্ব রাখে যাতে সাপোর্ট সহজে সার্চ করতে পারে।

Should a retry reuse the same correlation ID or generate a new one?

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

What should the API gateway or first service do if the header is missing?

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

How do we propagate the correlation ID across microservices and background jobs?

রিকোয়েস্ট কনটেক্সটে করিলেশন আইডিটাকে রাখুন এবং প্রতিটি ডাউনস্ট্রিম কলেও সেটি কপি করুন—অভ্যন্তরীণ HTTP/gRPC অনুরোধ এবং কিউড জবগুলোতেও। মাঝপথে নতুন করিলেশন আইডি তৈরি করা থেকে বিরত থাকুন; যদি বেশি বিশদ দরকার হয় তো আলাদা একটি অভ্যন্তরীণ আইডি যোগ করুন যাতে মূল চেইন ভেঙে না যায়।

What needs to be in logs for correlation IDs to actually help support?

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

How can we quickly verify we have true end-to-end coverage?

দ্রুত পরীক্ষা: একটি অ্যাকশন ট্রিগার করুন, প্রথম রিকোয়েস্ট বা এরর স্ক্রিন থেকে করিলেশন আইডি কপি করুন, তারপর নিশ্চয়তা দিন যে একই ভ্যালু প্রতিটি সম্পর্কিত রিকোয়েস্ট হেডার এবং প্রতিটি সার্ভিস লগ লাইনে দেখা যাচ্ছে। যদি আইডি workers, retries বা এরর রেসপন্সে দেখা না যায়, সেটা ঠিক করতে হবে।

Related posts