আপনি কি কখনও একটি বাগ ছিল যে আপনি সহজে পুনরুত্পাদন করতে পারে না? এটি তখনই মনে হয় যখন লোকেরা কিছু সময়ের জন্য আপনার অ্যাপ ব্যবহার করে। এবং ত্রুটি বার্তা এবং ব্যাকট্রেস আশ্চর্যজনকভাবে অসহায়৷
৷এটি এমন সময় যে আপনি ব্যতিক্রম হওয়ার ঠিক আগে অ্যাপটির অবস্থার একটি স্ন্যাপশট নিতে পারলে এটি সত্যিই কার্যকর হবে। আপনি যদি পারে, উদাহরণস্বরূপ, সমস্ত স্থানীয় ভেরিয়েবল এবং তাদের মানগুলির একটি তালিকা। ঠিক আছে, আপনি পারেন - এবং এটি এতটা কঠিনও নয়!
এই পোস্টে আমি আপনাকে দেখাব কিভাবে একটি ব্যতিক্রম সময়ে স্থানীয়দের ক্যাপচার করতে হয়। কিন্তু প্রথম, আমি আপনাকে সতর্ক করতে হবে. এই কৌশলগুলির কোনোটিই উৎপাদনে ব্যবহার করা উচিত নয়৷৷ আপনি এগুলোকে স্টেজিং, প্রিপ্রোড, ডেভেলপমেন্ট ইত্যাদিতে ব্যবহার করতে পারেন। শুধু উৎপাদন নয়। আমরা যে রত্নগুলি ব্যবহার করব তা কিছু চমত্কার ভারী আত্মদর্শন জাদুর উপর নির্ভর করে, যা সর্বোত্তমভাবে আপনার অ্যাপকে ধীর করে দেবে। সবচেয়ে খারাপ...কে জানে?
প্রবর্তন করা হচ্ছে 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"
# Get the binding "two levels up" and ask it for its local variable "fruit"
puts binding.of_caller(2).local_variable_get(:fruit)
end
a() # prints "orange"
এই মুহুর্তে, আপনি সম্ভবত দুটি পরস্পরবিরোধী আবেগ অনুভব করছেন। উত্তেজনা, কারণ এটি সত্যিই দুর্দান্ত। এবং বিদ্রোহ, কারণ এটি আপনি DHH বলার চেয়ে দ্রুত নির্ভরতার কুৎসিত জগাখিচুড়িতে পরিণত হতে পারে।
ব্যতিক্রমের সময়ে স্থানীয়দের লগ করা
এখন যেহেতু আমরা binding_of_caller আয়ত্ত করেছি, ব্যতিক্রমের সময়ে সমস্ত স্থানীয় ভেরিয়েবল লগ করা একটি কেকের টুকরো। নীচের উদাহরণে আমি বাড়াতে পদ্ধতি ওভাররাইড করছি। আমার নতুন উত্থাপন পদ্ধতি এটিকে বলা যাই হোক না কেন পদ্ধতির বাঁধাই আনে। তারপর এটি সমস্ত স্থানীয়দের মাধ্যমে পুনরাবৃত্তি করে এবং তাদের প্রিন্ট করে।
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
.
সহজ উপায়
এটি একটি চমত্কার শান্ত কৌশল. কিন্তু লগ ফাইলের চারপাশে গ্রেপ করা বাগগুলি ঠিক করার সবচেয়ে সুবিধাজনক উপায় নয়, বিশেষ করে যদি আপনার অ্যাপ স্টেজিংয়ে থাকে এবং আপনার একাধিক লোক এটি ব্যবহার করে থাকে। এছাড়াও, এটি আরও কোড যা আপনাকে বজায় রাখতে হবে।
আপনি যদি Honeybadger ব্যবহার করে ত্রুটির জন্য আপনার অ্যাপ নিরীক্ষণ করেন, আমরা স্বয়ংক্রিয়ভাবে স্থানীয়দের ক্যাপচার করতে পারি। আপনাকে যা করতে হবে তা হল আপনার জেমফাইলে binding_of_caller রত্ন যোগ করুন:
# Gemfile
group :development, :staging do
# Including this gem enables local variable capture via Honeybadger
gem "binding_of_caller"
...
end
এখন, যখনই একটি ব্যতিক্রম ঘটবে, আপনি ব্যাকট্রেস, প্যারাম, ইত্যাদি সহ সমস্ত স্থানীয়দের একটি রিপোর্ট পাবেন৷