কম্পিউটার টিউটোরিয়াল

রুবি এক্সেপশনে লোকাল ও ইনস্ট্যান্স ভেরিয়েবল লগ করুন দ্রুত ডিবাগিংয়ের জন্য

আপনার কি কখনো এমন একটি বাগ পড়েছে যা আপনি সহজে রিপ্রডিউস করতে পারলেন না? এটি শুধু তখনই হয় বলে মনে হয় যখন লোকেরা আপনার অ্যাপটি একদেরি ব্যবহার করে। এবং এরর মেসেজ ও ব্যাকট্রেস আশ্চর্যजनকভাবে অনহেল্পফুল।

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

এই পোস্টে আমি আপনাকে দেখাব কীভাবে এক্সেপশনের সময় লোকালস ক্যাপচার করতে হয়। কিন্তু প্রথমে, আমাকে আপনাকে সতর্ক করতে হবে। এই কোনো টেকনিক প্রোডাকশনে ব্যবহার করা উচিত নয়। আপনি স্টেজিং, প্রিপ্রোড, ডেভেলপমেন্ট ইত্যাদিতে ব্যবহার করতে পারেন। শুধু প্রোডাকশনে নয়। আমরা যেসব জেম ব্যবহার করব সেগুলো কিছু খুব ভারি ইন্ট্রাস্পেকশন ম্যাজিকের ওপর নির্ভর করে, যা 베स्ट কেসে আপনার অ্যাপকে স্লো করবে। ওৰ্স্ট কেসে... কে জানে?

binding_of_caller পরিচিতি

binding_of_caller জেম আপনাকে কারেন্ট স্ট্যাকের যেকোনো লেভেলের বাইন্ডিং এক্সেস করতে দেয়। সু...এটি একদম কী মানে?

"স্ট্যাক" হলো সিম্পলি মেথডগুলোর একটি লিস্ট যেগুলো করেন্টলি "ইন-প্রোগ্রেস"। আপনি caller মেথড ব্যবহার করে কারেন্ট স্ট্যাক এক্সামিন করতে পারেন। এখানে একটি সিম্পল উদাহরণ:

def a puts caller.inspect # ["caller.rb:20:in `<main>'"] b() end def b puts caller.inspect # ["caller.rb:4:in `a'", "caller.rb:20:in `<main>'"] c() end def c puts caller.inspect # ["caller.rb:11:in `b'", "caller.rb:4:in `a'", "caller.rb:20:in `<main>'"] end a() 

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

def get_binding a = "marco" b = "polo" return binding end my_binding = get_binding puts my_binding.local_variable_get(:a) # "marco" puts my_binding.local_variable_get(:b) # "polo" 

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

require "rubygems" require "binding_of_caller" def a fruit = "orange" b() end def b fruit = "apple" c() end def c fruit = "pear" # "two levels up" এর বাইন্ডিং পান এবং এর লোকাল ভেরিয়েবল "fruit" চান puts binding.of_caller(2).local_variable_get(:fruit) end a() # prints "orange" 

এই পয়েন্টে, আপনি সম্ভবত দুটি কনফ্লিক্টিং ইমোশন অনুভব করছেন। এক্সাইটমেন্ট, কারণ এটি খুব কুল। এবং ঘৃণা, কারণ এটি দ্রুত একটি অগ্লি মেস অফ ডিপেন্ডেন্সিতে পরিণত হতে পারে যেন আপনি DHH বলতে পারেন।

এক্সেপশনের সময় লোকালস লগ করা

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

require "rubygems" require "binding_of_caller" module LogLocalsOnRaise def raise(*args) b = binding.of_caller(1) b.eval("local_variables").each do |k| puts "Local variable #{ k }: #{ b.local_variable_get(k) }" end super end end class Object include LogLocalsOnRaise end def buggy s = "hello world" raise RuntimeError end buggy() 

এটি একশনে কেমন দেখে সেটি নিচে:

রুবি এক্সেপশনে লোকাল ও ইনস্ট্যান্স ভেরিয়েবল লগ করুন দ্রুত ডিবাগিংয়ের জন্য

এক্সারসাইজ: ইনস্ট্যান্স ভেরিয়েবল লগ করুন

আমি ইনস্ট্যান্স ভেরিয়েবল লোকালসের পাশাপাশি লগ করার টাস্ক আপনার জন্য এক্সারসাইজ হিসেবে রেখে দিচ্ছি। এখানে একটি হিন্ট: আপনি my_binding.eval("instance_variables") এবং my_binding.instance_variable_get ঠিক একইভাবে ব্যবহার করতে পারেন যেভাবে আপনি my_binding.eval("local_variables") এবং my_binding.instance_variable_get ব্যবহার করতেন।

সহজ উপায়

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

যদি আপনি Honeybadger ব্যবহার করেন আপনার অ্যাপের এরর মনিটর করার জন্য, আমরা অটোমেটিক্যালি লোকালস ক্যাপচার করতে পারি। আপনাকে শুধু binding_of_caller জেমটি আপনার Gemfile-এ যোগ করতে হবে:

# Gemfile group :development, :staging do # এই জেমটি ইনক্লুড করলে Honeybadger ভিয়া লোকাল ভেরিয়েবল ক্যাপচার ইনেবল হয় gem "binding_of_caller" ... end 

এখন, যখনই একটি এক্সেপশন ঘটবে, আপনি ব্যাকট্রেস, প্যারামস ইত্যাদির পাশাপাশি সকল লোকালসের একটি রিপোর্ট পাবেন।

রুবি এক্সেপশনে লোকাল ও ইনস্ট্যান্স ভেরিয়েবল লগ করুন দ্রুত ডিবাগিংয়ের জন্য


  1. রুবি এক্সেপশনে কনটেক্সচুয়াল ডেটা যোগ করুন: একটি প্র্যাক্টিক্যাল গাইড

  2. রুবি লগিং মাস্টারি: Logger এবং Lograge-এ এক্সপার্ট গাইড

  3. রুবিতে এনভায়রনমেন্ট ভেরিয়েবল মাস্টার করুন: একটি প্র্যাকটিক্যাল গাইড

  4. রুবি Case স্টেটমেন্ট মাস্টার করুন: বহুমুখী ব্যবহার এবং প্র্যাকটিক্যাল উদাহরণ