সেন্ট্রালাইজড লগিং
এই পাঠে যা শিখবেন
- কেন মাল্টি-সার্ভিস, মাল্টি-ইনস্ট্যান্স পরিবেশে বিক্ষিপ্ত লগ ফাইল ডিবাগিংয়ের জন্য অকার্যকর হয়ে ওঠে
- স্ট্রাকচার্ড (JSON) লগিং কেন সেন্ট্রালাইজড লগিং-কে সত্যিকারের কাজে লাগায়
- একটি সাধারণ সেন্ট্রালাইজড লগিং পাইপলাইনের ধাপগুলো (ELK-স্টাইল অ্যাগ্রিগেশন)
- লগ রিটেনশন পলিসি কীভাবে খরচ ও ডিবাগযোগ্যতার মধ্যে ভারসাম্য আনে
- Python দিয়ে একাধিক সার্ভিসের লগ একত্র ও সার্চ করার একটি ছোট্ট সিমুলেশন
১ · বিক্ষিপ্ত লগ কেন স্কেলে অকার্যকর
একটি একক সার্ভারে চলা একটি অ্যাপ্লিকেশনের জন্য "একটি লগ ফাইল দেখুন" যথেষ্ট। কিন্তু আধুনিক ক্লাউড পরিবেশে একটি রিকোয়েস্ট প্রায়ই একাধিক সার্ভিস, একাধিক ইনস্ট্যান্স/পড, একাধিক অঞ্চল জুড়ে ভ্রমণ করে (M6-M7-এর কন্টেইনার/Kubernetes পরিবেশে এই সংখ্যা শত শত হতে পারে)। প্রতিটি ইনস্ট্যান্স নিজের স্থানীয় ডিস্কে লগ লিখলে, একটি প্রোডাকশন ইনসিডেন্ট ডিবাগ করতে ইঞ্জিনিয়ারকে একে একে প্রতিটি মেশিনে লগইন করে সঠিক লগ ফাইল খুঁজতে হতো — বাস্তবে অসম্ভব, বিশেষ করে যখন ইনস্ট্যান্স নিজেই ইতিমধ্যে টার্মিনেট বা রিসাইকেল হয়ে গেছে (সার্ভারলেস/অটো-স্কেলিং পরিবেশে এটি খুবই সাধারণ)।
সমাধান হলো প্রতিটি সোর্স থেকে লগ একটি কেন্দ্রীয়, সার্চযোগ্য সিস্টেমে পাঠানো — যাতে "গত ৫ মিনিটে সব সার্ভিস জুড়ে কোন ERROR লগ এসেছে?" এই ধরনের প্রশ্নের উত্তর এক কোয়েরিতে পাওয়া যায়, প্রতিটি মেশিনে আলাদা করে না গিয়ে।
২ · স্ট্রাকচার্ড লগিং — কেন ফ্রি-টেক্সট যথেষ্ট নয়
একটি ফ্রি-টেক্সট লগ লাইন যেমন "User 42 login failed at 10:32" মানুষের চোখে পড়া সহজ,
কিন্তু হাজার হাজার সার্ভিসের কোটি কোটি লাইন জুড়ে নির্ভরযোগ্যভাবে পার্স/ফিল্টার/অ্যাগ্রিগেট করা কঠিন —
প্রতিটি ডেভেলপার সামান্য ভিন্ন ফরম্যাটে বার্তা লিখলে অনুসন্ধান ভঙ্গুর হয়ে পড়ে।
স্ট্রাকচার্ড লগিংStructured Loggingকনসিস্টেন্ট ফিল্ড-নাম সহ JSON (বা অনুরূপ) ফরম্যাটে লগ লেখার প্র্যাকটিস — যাতে প্রতিটি লগ এন্ট্রি নির্ভরযোগ্যভাবে মেশিন-পার্সেবল হয়।
—প্রতিটি লগ এন্ট্রিকে কনসিস্টেন্ট ফিল্ড (timestamp, level, service,
message, এবং প্রাসঙ্গিক কনটেক্সট ফিল্ড যেমন user_id) সহ JSON হিসেবে লেখে —
কেন্দ্রীয় সিস্টেম তখন নির্ভরযোগ্যভাবে যেকোনো ফিল্ড দিয়ে ফিল্টার/অ্যাগ্রিগেট করতে পারে।
৩ · সেন্ট্রালাইজড লগিং পাইপলাইন
একটি সাধারণ পাইপলাইন (ELK — Elasticsearch/Logstash/Kibana — স্টাইল, বা অনুরূপ যেকোনো সিস্টেম, নাম নির্দিষ্ট প্রোভাইডার-নিরপেক্ষ একটি উদাহরণ মাত্র): প্রতিটি সার্ভিস স্ট্রাকচার্ড লগ লেখে → একটি লগ ফরওয়ার্ডার/এজেন্ট প্রতিটি মেশিনে চলে ও সেই লগ কালেক্ট করে → কেন্দ্রীয় স্টোরেজে অ্যাগ্রিগেট ও ইনডেক্স হয় → একটি ড্যাশবোর্ড/সার্চ ইন্টারফেস দিয়ে যেকোনো ইঞ্জিনিয়ার পুরো সিস্টেম জুড়ে খুঁজতে পারে।
৪ · লগ রিটেনশন — ডিবাগযোগ্যতা বনাম খরচ
স্কেলে লগ দ্রুত জমা হয় — প্রতিটি রিকোয়েস্ট, প্রতিটি সার্ভিস কল কয়েক লাইন লগ তৈরি করতে পারে, তাই সব লগ চিরকাল সম্পূর্ণ বিস্তারিতভাবে রাখলে স্টোরেজ খরচ দ্রুত বেড়ে যায়। একটি রিটেনশন পলিসি ঠিক করে কতদিন কোন ডিটেইল লেভেলে লগ রাখা হবে — যেমন সাম্প্রতিক ৭ দিনের লগ সম্পূর্ণ বিস্তারিত ও দ্রুত-অনুসন্ধানযোগ্য রাখা, তারপর পুরনো লগ সংক্ষিপ্ত/সংকুচিত করে সস্তা আর্কাইভ স্টোরেজে সরানো (L11-এর স্টোরেজ-টায়ারিং ধারণার সরাসরি প্রয়োগ, এবার লগের জন্য) — খুব পুরনো ইনসিডেন্ট তদন্তে সামান্য বেশি সময় লাগলেও দৈনন্দিন খরচ অনেক কমে।
# একাধিক সিমুলেটেড সার্ভিস থেকে স্ট্রাকচার্ড লগ — একটি কেন্দ্রীয় তালিকায় অ্যাগ্রিগেট করা হচ্ছে
service_logs = {
"auth-service": [
{"ts": 101, "level": "INFO", "msg": "user login succeeded", "user_id": 42},
{"ts": 104, "level": "ERROR", "msg": "token validation failed", "user_id": 17},
{"ts": 110, "level": "INFO", "msg": "user logout", "user_id": 42},
],
"payment-service": [
{"ts": 102, "level": "INFO", "msg": "payment initiated", "order_id": 501},
{"ts": 105, "level": "ERROR", "msg": "gateway timeout", "order_id": 501},
{"ts": 108, "level": "WARN", "msg": "retrying payment", "order_id": 501},
],
"inventory-service": [
{"ts": 103, "level": "INFO", "msg": "stock check ok", "sku": "SKU-9"},
{"ts": 109, "level": "ERROR", "msg": "stock database unreachable", "sku": "SKU-9"},
],
}
def aggregate_logs(service_logs):
"""সব সার্ভিসের লগ একটি একক কেন্দ্রীয় তালিকায় একত্র করে, প্রতিটি এন্ট্রিতে সার্ভিসের নাম যোগ করে।"""
central_log = []
for service_name, entries in service_logs.items():
for entry in entries:
merged = {"service": service_name, **entry}
central_log.append(merged)
central_log.sort(key=lambda e: e["ts"])
return central_log
def search_logs(all_logs, service=None, level=None):
"""কেন্দ্রীয় লগে সার্ভিস ও/অথবা লেভেল দিয়ে ফিল্টার করে — বিক্ষিপ্ত থাকলে এই কোয়েরি অসম্ভব হতো।"""
results = []
for entry in all_logs:
if service is not None and entry["service"] != service:
continue
if level is not None and entry["level"] != level:
continue
results.append(entry)
return results
central_log = aggregate_logs(service_logs)
print(f"মোট কেন্দ্রীভূত লগ এন্ট্রি: {len(central_log)}")
print("\n--- সব সার্ভিস জুড়ে সব ERROR-level লগ (এক কোয়েরিতে) ---")
for entry in search_logs(central_log, level="ERROR"):
print(f"[{entry['ts']}] {entry['service']:18}{entry['msg']}")
search_logs একটি কোয়েরিতেই তিনটি ভিন্ন সার্ভিস জুড়ে সব ERROR খুঁজে পেল —
যদি লগ তিনটি আলাদা মেশিনে বিক্ষিপ্ত থাকত, একজন ইঞ্জিনিয়ারকে তিনবার আলাদাভাবে লগইন করে প্রতিটি ফাইল
হাতে খুঁজতে হতো। স্ট্রাকচার্ড ফরম্যাট (কনসিস্টেন্ট level/service ফিল্ড)
ছাড়া এই ফিল্টারিং নির্ভরযোগ্যভাবে সম্ভবই হতো না।
সেন্ট্রালাইজড লগিং শুধু "লগ এক জায়গায় জমা করা" নয় — এটি স্ট্রাকচার্ড ফরম্যাট, সঠিক অ্যাগ্রিগেশন পাইপলাইন এবং একটি সুচিন্তিত রিটেনশন পলিসির সমন্বয়ে তৈরি একটি সিস্টেম, যা স্কেলে ডিবাগিংকে সম্ভব রাখে। পরবর্তী পাঠে (L43) আমরা দেখব লগের পাশাপাশি ট্রেসিং কীভাবে একটি একক রিকোয়েস্টের সম্পূর্ণ পথ পুনর্গঠন করে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ একটি সার্ভিস যদি ফ্রি-টেক্সট লগ লেখে (স্ট্রাকচার্ড JSON না লিখে), তাহলে সেন্ট্রালাইজড লগিং সিস্টেমে যোগ করলেও কেন এটি এখনও সমস্যাযুক্ত থাকবে?
কেন্দ্রীয় সিস্টেম সব লগ এক জায়গায় জমা করবে ঠিকই, কিন্তু ফ্রি-টেক্সট লগে নির্ভরযোগ্য ফিল্ড
(যেমন level বা service) না থাকায় সিস্টেমটি নির্দিষ্টভাবে "সব ERROR
দেখাও" জাতীয় ফিল্টার করতে পারবে না — শুধু পুরো টেক্সট জুড়ে কীওয়ার্ড সার্চ করতে হবে, যা ভুল
পজিটিভ/নেগেটিভে ভরা এবং অনির্ভরযোগ্য। কেন্দ্রীকরণ আর স্ট্রাকচারিং দুটোই একসাথে প্রয়োজন।
প্র ০২ একটি সার্ভারলেস ফাংশন (M11-এ শিখবেন) যা কয়েক সেকেন্ড চলে তারপর সম্পূর্ণ বন্ধ হয়ে যায় — তার জন্য সেন্ট্রালাইজড লগিং সাধারণ VM-এর চেয়ে কেন আরও বেশি জরুরি?
একটি সবসময়-চালু VM-এ প্রয়োজনে এখনও লাইভ মেশিনে গিয়ে লগ ফাইল দেখার (কম আদর্শ হলেও) সুযোগ থাকে। কিন্তু একটি সার্ভারলেস ফাংশনের এক্সিকিউশন এনভায়রনমেন্ট রান শেষ হওয়ার পরপরই সম্পূর্ণ বিলুপ্ত হয়ে যায় — লগ তখনই কেন্দ্রীয় সিস্টেমে না পাঠালে সেই এক্সিকিউশনের কোনো রেকর্ডই আর অবশিষ্ট থাকে না।
প্র ০৩ "সব লগ চিরকালের জন্য পূর্ণ বিস্তারিতভাবে রাখা সবচেয়ে নিরাপদ" — এই ধারণাটি বাস্তবে কেন ভুল?
স্কেলে লগের পরিমাণ এত দ্রুত বাড়ে যে চিরস্থায়ী পূর্ণ-বিস্তারিত রিটেনশন দ্রুত স্টোরেজ খরচকে অবাস্তব পর্যায়ে নিয়ে যায় — এবং এত বিপুল ডেটার মধ্যে প্রাসঙ্গিক তথ্য খুঁজে বের করাও ধীর ও ব্যয়বহুল হয়ে ওঠে। একটি বিচক্ষণ রিটেনশন পলিসি (সাম্প্রতিক = বিস্তারিত, পুরনো = সংক্ষিপ্ত/আর্কাইভড) প্রকৃত ডিবাগযোগ্যতাকে বজায় রেখেই খরচ নিয়ন্ত্রণে রাখে — L11-এর টায়ারিং নীতিরই একটি প্রয়োগ।
অনুশীলন
-
চিন্তা করুন: উপরের কোডে
search_logsফাংশনে শুধুservice="payment-service"দিয়ে (level ছাড়াই) কল করলে কী ফলাফল আসবে, এবং কেন এটি এখনও দরকারী?এটি payment-service-এর তিনটি এন্ট্রিই (INFO, ERROR, WARN — সব লেভেল) ফেরত দেবে, কারণ
level=Noneথাকলে লেভেল-ফিল্টার স্কিপ হয়ে যায়। এটি দরকারী কারণ একটি নির্দিষ্ট সার্ভিসের পুরো টাইমলাইন (শুধু এরর নয়) দেখতে চাইলে — যেমন একটি নির্দিষ্ট অর্ডারের পুরো প্রসেসিং হিস্ট্রি বুঝতে — এই ধরনের সার্ভিস-শুধু কোয়েরি প্রয়োজন হয়। -
পরীক্ষা করুন:
service_logs-এ একটি নতুন সার্ভিস"shipping-service"যোগ করুন (একটি ERROR-লেভেল এন্ট্রিসহ), তারপর কোডটি আবার চালিয়ে দেখুন সেটি ERROR-অনুসন্ধানের ফলাফলে স্বয়ংক্রিয়ভাবে যুক্ত হয় কিনা।হ্যাঁ — যেহেতু
aggregate_logsএবংsearch_logsকোনো নির্দিষ্ট সার্ভিসের নাম হার্ডকোড করা নেই (এরাservice_logsdict-এর যেকোনো key নিয়ে কাজ করে), নতুন সার্ভিস যোগ করলেই এটি স্বয়ংক্রিয়ভাবে কেন্দ্রীয় লগ ও অনুসন্ধান উভয়ের অংশ হয়ে যায় — ঠিক যেমন বাস্তব সেন্ট্রালাইজড লগিং সিস্টেমে একটি নতুন সার্ভিস যোগ করলে আলাদা কোনো "সার্চ কোড" পরিবর্তন করতে হয় না।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ পরবর্তী পাঠ (L43) — ডিস্ট্রিবিউটেড ট্রেসিং ও অবজারভেবিলিটির তিন স্তম্ভ।
- System Design & Software Architecture কোর্স সঙ্গী কোর্স ডিস্ট্রিবিউটেড সিস্টেমের লগিং ও অবজারভেবিলিটি প্যাটার্ন আরও গভীরভাবে দেখুন।
- Cybersecurity & Ethical Hacking কোর্স সঙ্গী কোর্স লগ ডেটা নিরাপদ রাখা ও ইনসিডেন্ট ফরেনসিক্সে লগের ভূমিকা শিখতে দেখুন।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity ও Cloud Computing & DevOps — সব এক জায়গায়।