Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

तेज़ डीबगिंग के लिए रूबी एक्सेप्शन पर लोकल और इंस्टेंस वेरिएबल लॉग करें

क्या आपको कभी ऐसा बग मिला है जिसे आप आसानी से पुन: पेश नहीं कर सके? यह केवल तब होता प्रतीत होता है जब लोग आपके ऐप का कुछ समय से उपयोग कर रहे हों। और एरर मैसेज और बैकट्रेस आश्चर्यजनक रूप से अनुपयोगी होते हैं।

ऐसे समय में यह वास्तव में आसान होता अगर आप एक्सेप्शन होने से ठीक पहले ऐप की स्थिति का स्नैपशॉट ले सकते। यदि आपके पास, उदाहरण के लिए, सभी लोकल वेरिएबल और उनके मानों की सूची होती। खैर, आप कर सकते हैं - और यह उतना कठिन भी नहीं है!

इस पोस्ट में मैं आपको दिखाऊंगा कि एक्सेप्शन के समय लोकल को कैसे कैप्चर किया जाए। लेकिन पहले, मुझे आपको चेतावनी देनी होगी। इनमें से किसी भी तकनीक का उत्पादन में उपयोग नहीं किया जाना चाहिए। आप इन्हें स्टेजिंग, प्रीप्रोड, डेवलपमेंट आदि में उपयोग कर सकते हैं। बस उत्पादन में नहीं। हम जिन जेम्स का उपयोग करेंगे वे कुछ बहुत भारी इंट्रोस्पेक्शन जादू पर भरोसा करते हैं, जो कम से कम आपके ऐप को धीमा कर देगा। सबसे खराब स्थिति में... कौन जानता है?

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 में महारत हासिल कर ली है, तो एक्सेप्शन के समय सभी लोकल वेरिएबल लॉग करना केक का टुकड़ा है। नीचे दिए गए उदाहरण में मैं 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 का उपयोग करेंगे।

आसान तरीका

यह एक बहुत अच्छी ट्रिक है। लेकिन लॉग फाइलों को ग्रेप करना बग्स को ठीक करने का सबसे सुविधाजनक तरीका नहीं है, खासकर अगर आपका ऐप स्टेजिंग पर है और कई लोग इसका उपयोग कर रहे हैं। साथ ही, यह सिर्फ अधिक कोड है जिसे आपको बनाए रखना है।

यदि आप अपने ऐप में एरर की निगरानी के लिए हनीबैजर का उपयोग करते हैं, तो हम स्वचालित रूप से लोकल को कैप्चर कर सकते हैं। आपको बस अपने Gemfile में binding_of_caller जेम जोड़ना है:

# Gemfile group :development, :staging do # Including this gem enables local variable capture via Honeybadger gem "binding_of_caller" ... end 

अब, जब भी कोई एक्सेप्शन होता है, आपको बैकट्रेस, पैरामीटर्स आदि के साथ सभी लोकल की रिपोर्ट मिल जाएगी।

तेज़ डीबगिंग के लिए रूबी एक्सेप्शन पर लोकल और इंस्टेंस वेरिएबल लॉग करें


  1. रूबी लॉगिंग में महारत हासिल करें: Logger और Lograge के साथ विशेषज्ञ गाइड रूबी लॉगिंग में महारत हासिल करें: Logger और Lograge के साथ विशेषज्ञ गाइड

    रूबी में लॉग्स के साथ काम करना लॉगिंग उन प्राथमिक कार्यों में से एक है जिसे एक एप्लिकेशन आमतौर पर संबोधित करता है। लॉग्स का उपयोग तब किया जाता है जब आपको आवश्यकता होती है, उदाहरण के लिए, अपने ऐप्स के अंदर क्या हो रहा है, यह देखने के लिए, उनकी निगरानी करने के लिए, या कुछ विशिष्ट डेटा के लिए मेट्रिक्

  1. रूबी में एनवायरनमेंट वेरिएबल्स मास्टर करें: एक व्यावहारिक मार्गदर्शिका रूबी में एनवायरनमेंट वेरिएबल्स मास्टर करें: एक व्यावहारिक मार्गदर्शिका

    एक एनवायरनमेंट वेरिएबल एक कुंजी/मान जोड़ी है, यह इस तरह दिखती है: KEY=VALUE हम इन वेरिएबल्स का उपयोग अपने कंप्यूटर में सभी प्रोग्राम्स के बीच कॉन्फ़िगरेशन विकल्प साझा करने के लिए करते हैं। यही कारण है कि यह सीखना महत्वपूर्ण है कि वे कैसे काम करते हैं और ENV विशेष वेरिएबल का उपयोग करके अपने रूबी प्

  1. रूबी केस स्टेटमेंट्स में महारत: बहुमुखी उपयोग और व्यावहारिक उदाहरण रूबी केस स्टेटमेंट्स में महारत: बहुमुखी उपयोग और व्यावहारिक उदाहरण

    जब भी आपको कुछ if / elsif स्टेटमेंट्स का उपयोग करने की आवश्यकता होती है तो आप इसके बजाय रूबी केस स्टेटमेंट का उपयोग करने पर विचार कर सकते हैं। इस पोस्ट में, आप कुछ अलग उपयोग के मामले सीखेंगे और यह वास्तव में हुड के नीचे कैसे काम करता है। नोट: अन्य प्रोग्रामिंग भाषाओं में इसे स्विच स्टेटमेंट के रूप