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

रूबी में जटिल अपवाद व्यवहार का पता लगाने के लिए ट्रेसपॉइंट का उपयोग करना

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

मैं आपको आपके ऐप में अपवादों के बारे में थोड़ी अधिक जानकारी प्राप्त करने के लिए TracePoints का उपयोग करने का एक आसान तरीका दिखाने जा रहा हूं - भले ही वे अपवाद निगल लिए गए हों।

एक सुविधाजनक उदाहरण

रेल में नियंत्रकों और विचारों के बीच की सीमा एक ऐसा स्थान है जहां अपवाद तर्क को धता बताते हैं। अपने लिए देखना आसान है। बस एक दृश्य में अपवाद उठाएं और इसे नियंत्रक में बचाने का प्रयास करें। आप पाएंगे कि आप नियंत्रक से टेम्पलेट त्रुटि को नहीं बचा सकते!

# pages_controller.rb

def index
  render
rescue
  # this will never run
  logger.debug "someone raised the roof"
end
# index.haml

- raise "the roof"

रूबी में जटिल अपवाद व्यवहार का पता लगाने के लिए ट्रेसपॉइंट का उपयोग करना डब्ल्यूटीएफ!?! मुझे लगा कि मैंने इसे बचा लिया!

यह स्पष्ट है कि कुछ मुश्किल हो रहा है। आइए देखें कि क्या हम यह पता लगा सकते हैं कि यह क्या है।

ट्रेसपॉइंट के साथ सभी अपवादों को लॉग करना

TracePoints वास्तव में एक शक्तिशाली आत्मनिरीक्षण उपकरण है जो रूबी 2.0 के बाद से मौजूद है। वे आपको विभिन्न प्रकार के रनटाइम ईवेंट के लिए कॉलबैक परिभाषित करने की अनुमति देते हैं। उदाहरण के लिए, जब भी किसी वर्ग को परिभाषित किया जाता है, जब भी कोई विधि कहा जाता है या जब भी कोई अपवाद उठाया जाता है, तो आपको सूचित किया जा सकता है। और भी अधिक घटनाओं के लिए TracePoint दस्तावेज़ीकरण देखें।

आइए एक ट्रेसपॉइंट जोड़कर शुरू करें जिसे जब भी कोई अपवाद उठाया जाता है और लॉग में इसका सारांश लिखता है।

class PagesController < ApplicationController
  def index
    TracePoint.new(:raise) do |tp|
      # tp.raised_exeption contains the actual exception object that was raised!
      logger.debug "#{tp.raised_exception.object_id}: #{tp.raised_exception.class} #{tp.raised_exception.message} ".yellow + tp.raised_exception.backtrace[0].sub(Rails.root.to_s, "").blue
    end.enable do
      render
    end
  end
end

यदि आप yellow के बारे में उत्सुक हैं और blue विधियाँ,  मैं रंगीन रत्न का उपयोग कर रहा हूँ। यह आउटपुट में एएनएसआई रंग कोड जोड़ता है।

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

रूबी में जटिल अपवाद व्यवहार का पता लगाने के लिए ट्रेसपॉइंट का उपयोग करना यह लॉग raise के हर उपयोग को दर्शाता है प्रतिपादन प्रक्रिया में

कौन सी विधि के कारण कौन सी वृद्धि हुई?

"उठाएं" घटनाओं की सूची रखना बहुत उपयोगी है। लेकिन यह और भी बेहतर होगा अगर हमें इस बात का अंदाजा हो कि कौन से तरीके प्रत्येक वृद्धि का कारण बन रहे हैं। एक बार फिर, ट्रेसपॉइंट बचाव के लिए आता है।

ट्रेसपॉइंट हमें एक हैंडलर जोड़ने देता है जिसे जब भी कोई विधि वापस आती है तो उसे कॉल किया जाता है। इसका उपयोग करना उतना ही सरल है जितना कि "raise" ईवेंट था। नीचे दिए गए उदाहरण में हम हर मेथड रिटर्न लॉग कर रहे हैं:

TracePoint.trace(:return) do |tp|
  logger.debug [tp.method_id, tp.lineno, tp.path.sub(Rails.root.to_s, "")].join(" : ").green 
end

हालांकि एक समस्या है। यदि आप इस कोड को अपने रेल ऐप में जोड़ते हैं, तो आप पाएंगे कि आपका ऐप अनुरोधों का जवाब देना बंद कर देता है। सबसे सरल रेल अनुरोध में इतने सारे मेथड कॉल हैं कि सर्वर समय समाप्त होने से पहले उन सभी को लॉग में लिख सकता है।

चूंकि हम वास्तव में केवल विधि कॉल में रुचि रखते हैं जो अपवादों का कारण बनती हैं, इसलिए प्रत्येक अपवाद के बाद होने वाली पहली दो "रिटर्न" घटनाओं को आउटपुट करने के लिए हमारे कोड को संशोधित करें।

class PagesController < ApplicationController
  def index
    counter = 0
    return_trace = TracePoint.trace(:return) do |tp|
      logger.debug "\t" + [tp.method_id, tp.lineno, tp.path.sub(Rails.root.to_s, "")].join(" : ").green 
      if (counter += 1) > 3
        return_trace.disable
        counter = 0
      end
    end
    return_trace.disable # disable the tracepoint by default

    TracePoint.new(:raise) do |tp|
      logger.debug "#{tp.raised_exception.object_id}: #{tp.raised_exception.class} #{tp.raised_exception.message} ".yellow + tp.raised_exception.backtrace[0].sub(Rails.root.to_s, "").blue
      # The "raise" enables the "return" tracepoint
      return_trace.enable
    end.enable do
      render
    end

  end
end

जब मैं अपने ब्राउज़र को रीफ़्रेश करता हूँ, तो मैं देखता हूँ कि लॉग में निम्नलिखित पंक्तियाँ जोड़ी गई हैं:

रूबी में जटिल अपवाद व्यवहार का पता लगाने के लिए ट्रेसपॉइंट का उपयोग करना प्रत्येक "raise" ईवेंट को उस विधि के ऊपर दिखाया गया है जिसके कारण यह हुआ

चूंकि हम केवल "रिटर्न" ट्रेसपॉइंट को सक्षम करते हैं जब कोई अपवाद उठाया जाता है, तो पहला "रिटर्न" ईवेंट उस विधि से होगा जिसने अपवाद उठाया था।

हम इस जानकारी का उपयोग अपने रहस्य को सुलझाने के लिए कर सकते हैं। हमारा मूल RuntimeError एक ActionView::Template::Error में कनवर्ट किया जा रहा है handle_render_error . द्वारा template.rb की लाइन 310 पर विधि।

इस तकनीक की अच्छी बात यह है कि इसका रेल से कोई लेना-देना नहीं है। आप इसे किसी भी समय उपयोग कर सकते हैं जब आपको अधिक विस्तार से समझने की आवश्यकता हो कि कौन से अपवाद उठाए जा रहे हैं और हुड के तहत पकड़े गए हैं।


  1. रूबी में लैम्ब्डा का उपयोग करना

    ब्लॉक रूबी का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना मुश्किल है। लेकिन लैम्ब्डा? लैम्ब्डा को कौन प्यार करता है? आप एक का उपयोग किए बिना वर्षों तक जा सकते हैं। वे लगभग पुराने जमाने के अवशेष की तरह लगते हैं। ...लेकिन यह बिल्कुल सच नहीं है। एक बार जब आप उनकी थोड़ी जांच कर लेते हैं त

  1. रूबी अपवाद पदानुक्रम को समझना

    रुबी में अपवाद सिर्फ कक्षाएं हैं। अपवाद अपवाद पदानुक्रम उन सभी वर्गों से बना है जो अपवाद से इनहेरिट करते हैं। यहां रूबी 2.1 की मानक लाइब्रेरी के लिए अपवाद पदानुक्रम है। Exception NoMemoryError ScriptError LoadError NotImplementedError SyntaxError SecurityError SignalException

  1. रूबी में कस्टम अपवाद

    रूबी में अपने स्वयं के अपवाद बनाना आसान है। बस इन चरणों का पालन करें: 1. एक नई कक्षा बनाएं अपवाद वर्ग हैं, जैसे रूबी में बाकी सब कुछ! एक नए प्रकार का अपवाद बनाने के लिए, बस एक ऐसा वर्ग बनाएं जो StandardError या उसके किसी बच्चे से विरासत में मिला हो। class MyError < StandardError end raise MyErr