বেশির মানুষ লগের প্রয়োজনীয়তা বুঝে তখনই যখন সেটা সবচেয়ে বেশি দরকার। কিন্তু যখন অ্যাপ্লিকেশন ব্রেক করে, ইউজার কমপ্লেইন পড়ে, এবং আপনার কোনো ক্লু নেই কীভাবে ফিক্স করবেন — তখন লগ মেসেজ যোগ করার জন্য খুব দেরি হয়ে গেছে।
ভালো লগ নিজের খরচ দশগুন ফেরত দেয়। সেগুলো ট্রিকি বাগ ডায়াগনোজ করতে সহজ করে, এবং যদি লগিং ঠিকমতো করা হয়, তবে ইউজার নোটিশ করার আগেই ইস্যু আলার্ট দিতে পারে। কিন্তু 'লগিং ঠিকমতো করা' বলতে কী বোঝায়?
লগিং শুরু করা সহজ কিন্তু মাস্টার করা কঠিন। এই পোস্টে আমরা দেখব কীভাবে আপনার Rails অ্যাপ্লিকেশনের লগগুলো সর্বোচ্চ সম্ভাবনায় ব্যবহার করা যায়।
Rails-এ Logging
বেসিকস থেকে শুরু করি। নতুন Rails অ্যাপ্লিকেশন শুরু করলে লগিং ইতিমধ্যে সেটআপ থাকে। Rails ActiveSupport::Logger-এর একটি নতুন ইনস্ট্যান্স ইনিশিয়ালাইজ করে যা অ্যাপ্লিকেশনের যেকোনো জায়গায় ব্যবহার করা যায়।
Rails.logger.info "Application started"
Rails logger স্ট্যান্ডার্ড আউটপুট বা log/-এ লেখে এবং ইনকামিং রিকোয়েস্ট বা এক্সিকিউটেড কোয়েরি অটোমেটিক্যালি লগ করে আপনার এক্সপ্লিসিট লগ মেসেজের পাশাপাশি।
Rails লগ কনফিগার করার অনেক উপায় আছে। আমাদের ইন্টরেস্ট লগ লেভেল এবং লগ ফরম্যাটিং-এ।
ভালো লগিং vs খারাপ লগিং
লগের উদ্দেশ্য: সিস্টেম ইভেন্ট সম্পর্কে আপনাকে জানাতে যাতে আপনি রিয়্যাক্ট করতে পারেন। এরর হলে লগ মেসেজ সেটা আপনাকে বোঝানো উচিত।
লগ মেসেজ কতটুকু বুঝা যায় সেটা নির্ভর করে কতটুকু descriptive (বর্ণনামূলক) এবং contextual (প্রসঙ্গ-সাপেক্ষ) সেটা। Descriptive লগ মেসেজ রিলেভেন্ট ইনফোর্মেশন দেয় কী ঘটেছে। Contextual লগ মেসেজ সিস্টেমের স্টেট ইনক্লুড করে যখন সেটা লেখা হয়েছিল।
উদাহরণ: এক্সটার্নাল API কল
কোড যা এক্সটার্নাল API কল করে এবং রেসপন্স রিটার্ন করে:
def call_external_api
log.debug "Method entered"
response = ExternalApi.call
if response.success?
log.info "Response success"
else
log.error "Response failure"
end
end
কাস্টমার রিপোর্ট করলে লগ চেক করলে দেখতে পাবেন:
DEBUG: Method entered
INFO: Response success
ERROR: An error occurred
এই লগ মেসেজগুলো কিছু ইনফোর্মেশন দেয় কিন্তু যথেষ্ট নয়। রুট কause খুঁজে বের করা যাচ্ছে না। এগুলো noise।
Rails-এ Log Levels
ডিফল্ট Rails logger-এ DEBUG, INFO, WARN, ERROR লেভেল আছে। এগুলো ব্যবহার করে লগ মেসেজ রিলেভেন্স ক্যাটাগরাইজ করা যায়।
DEBUG: সিস্টেমের ভেতরে হচ্ছা অ্যাকশনের ডিটেইলড ইনফো (মেথড এন্টার/এক্সিট, ডিবাগিং-এ 벨류 অ্যাড করলে)INFO: সিস্টেম স্টেট চেঞ্জ বা রিলেভেন্ট ইভেন্ট (রিসিভড রিকোয়েস্ট, এক্সটার্নাল API রিকোয়েস্ট, জব স্টার্ট/ফিনিশ)WARN: কিছু অনপ্রত্যাশিত হয়েছে। এখনও সমস্যা নয় (অ্যাপ হ্যান্ডেল করতে পারে), কিন্তু বারবার হলে অটেনশন লাগবে।ERROR: এরর হয়েছে। ইনভ্যালিড অ্যাপ্লিকেশন স্টেট যা অবশ্যই সমাধান করতে হবে।
এনভায়রনমেন্ট ফাইল মডিফাই করে লগ লেভেল চেঞ্জ করা যায়। প্রোডাকশনে Rails DEBUG ডিসকার্ড করে, কিন্তু চেঞ্জ করা যায়:
config.log_level = :debug
Descriptive Log Messages
Descriptive লগ মেসেজ কোনো অনিশ্চিততা রেখে না। রিডারের কাছে ইনস্ট্যান্ট নলেজ দেয় কী ঘটেছে।
'An error occurred' পড়লে এರೆর কী সেটা জানা যায় না। এটা এড়িয়ে যেতে হলে এরর নিজেই লগ করুন তার মেসেজসহ।
log.error { "API call failed: #{response.error_message}" }
নোট: ব্লক সিনট্যাক্স (log.debug { ... }) ব্যবহার করলে স্ট্রিং ইন্টারপোলেশন তখনই হবে যখন লগ লেভেল ডিবাগ হবে। অপ্রয়োজনীয় কম্পিউটেশন বাঁচে।
অন্যান্য মেসেজও ইম্প্রুভ করুন: 'Method entered' -> কনসিস্টেন্ট মেথড নাম, 'Response success' -> একচুইট রেসপন্স, 'Response failure' -> ফেইলচারের ন্যাচার।
লগ মেসেজের জন্য আরও প্রসঙ্গ (Context)
নতুন লগ মেসেজগুলো কী ঘটেছে সেটা ক্লিয়ার করে দেয়। কিন্তু কেন ঘটেছে সেটা বুঝতে প্রসঙ্গ দরকার।
উদাহরণ: রিকোয়েস্ট/রেসপন্স লগ করার সময় কে রিকোয়েস্ট করল সেটা জানা উপকারী। এররের জন্য স্ট্যাক ট্রেস আট্যাচ করলে ডিবাগিং সহজ হয়।
log.error { "API call failed: #{response.error_message}, user: #{current_user.id}" }
log.error { "Exception: #{e.message}\n#{e.backtrace.join('\n')}" }
নোট: Rails ডিফল্ট logger-এ কনটেক্সচুয়াল ইনফোর্মেশন যুক্ত করা কষ্টসাধ্য। কাস্টম লগার যেমন Ougai বা MrLogaLoga ব্যবহার করলে সহজ হয়।
Structured Logging
মানবের জন্য রিডেবল লগ বানালে পরবর্তী লেভেল: মেশিন-রিডেবল লগ বানান যাতে মনিটরিং এবং ডেটা অ্যানালাইসিস করা যায়।
JSON ফরম্যাট আমার পছন্দ, কিন্তু Logstash ও ব্যবহার করা যায়। কাস্টম লগ ফরম্যাটার বানিয়ে লগ মেসেজের ফরম্যাট চেঞ্জ করা যায়।
# কাস্টম JSON ফরম্যাটার
class JsonFormatter < Logger::Formatter
def call(severity, time, progname, msg)
{ severity: severity, time: time, message: msg }.to_json + "\n"
end
end
Rails.logger.formatter = JsonFormatter.new
খুদে ফরম্যাটার লিখার বদলে gems ব্যবহার করুন। Lograge রিকমেন্ড — আউট-অফ-দ-বক্স ফরম্যাটিং দেয় এবং Rails-এর ভার্বোজ রিকোয়েস্ট ফরম্যাট ক্লিন আপ করে।
AppSignal-সহ Rails Logging
লগগুলো নাইস ও রিডেবল বানালে সেগুলো আরো অ্যাক্সেসিবল করা উচিত। SSH করে tail/grep করার প্রয়োজন নেই।
AppSignal-এ недаśে Logging feature (beta) লঞ্চ করা হয়েছে! এটি Rails লগ ডাইরেক্টলি AppSignal ওয়েব ইন্টারফেসে ইনসপেক্ট ও অ্যানালাইজ করতে দেয়।
বাম মেনুর 'Logging' ট্যাব থেকে অ্যাক্সেস করুন:
Ruby logging docs ফলো করে config/environment.rb-এ initialization-এর আগে নিচের কোড যোগ করুন:
require "appsignal/logger"
Rails.logger = AppSignal::Logger.new(Rails.logger)
JSON ফরম্যাট বা Lograge-ওয়ালা স্ট্রাকচার্ড লগও ইনজেস্ট করা যায়। সেটআপের পর AppSignal-এ Rails লগ দেখতে পাবেন:
Logging এবং Error Reporting
Error tracking টুলস অ্যাপ্লিকেশন এরর সম্পর্কে ডিটেইলড ইনফোর্মেশন দেয় — ফুল স্ট্যাক ট্রেস, কনটেক্সচুয়াল ইনফো। কিন্তু আربیট্রারি মেসেজ পাঠানো সাধারণত ইনফিজিবল। ডিটেইলড, হিস্টরিক্যাল ইনফো যা ভালো লগ দেয়, সেটা রিপ্লেস করা যাবে না।
বাস্তবে, ভালো লেখা লগ error tracking টুলকে augment এবং support করে। দুটোই ব্যবহার করা উচিত।
Wrap Up
এই পোস্টে আমরা দেখেছি কীভাবে লগ থেকে সর্বোচ্চ আউটপুট নেওয়া যায়। Rails-এ লগিং শুরু করা সহজ, কিন্তু ইউজফুল লগ লিখা চ্যালেঞ্জিং।
Descriptiveness বা context ছাড়া লগ ডিস্ক পূরণ করবে কিন্তু ভ্যালু দেবে না। সঠিক লগ লেভেল এবং রিডারের প্রয়োজনীয় ইনফোর্মেশন দিয়ে লগ মেসেজ লিখলে সেটা great asset হয়।
গ্রেট লগ মেসেজ লিখতে পারলে সেগুলো মেশিন-রিডেবল ফরম্যাটে কনভার্ট করুন যাতে অ্যানালাইসিস এবং ফিল্টারিং সহজ হয়। AppSignal-এর নতুন লগিং ফিচার ব্যবহার করে লগ সহজে অ্যাক্সেস করুন। অবশেষে, লগ error tracking টুলকে রিপ্লেস না করে augment করা উচিত।
Happy logging!
P.S. Ruby Magic পোস্টগুলি প্রকাশ होते সাথে সাথে পেতে আমাদের Ruby Magic নিউজলেটার সাবস্ক্রাইব করুন!
Hans-Jörg Schnedlitz
আমাদের অতিথি লেখক Hans ভিয়েনা, অস্ট্রিয়া থেকে একজন Rails ইঞ্জিনিয়ার। অধিকাংশ সময় কোডিং বা কোডিং সম্পর্কে পড়তে ব্যতিত করেন, এবং কখনো কখনো তার ব্লগে লেখেন! স্ক্রিনের সামনে না থাকলে পর্বত আরোহণ করেন।
Hans-Jörg Schnedlitz-এর সব আর্টিকেল