इस दो-भाग वाली श्रृंखला के पहले भाग में, हमने देखा कि Ruby on Rails एप्लिकेशन में AppSignal को कैसे सेटअप करें ताकि बॉक्स से बाहर कई बेहतरीन इनसाइट्स मिल सकें। AppSignal स्वचालित रूप से एरर्स को ट्रैक करता है, परफॉरमेंस की निगरानी करता है, और कुछ निर्भरताओं के बारे में मेट्रिक्स रिपोर्ट करता है।
लेकिन, कई मामलों में, हमारे प्रत्येक एप्लिकेशन अलग-अलग तरीके से व्यवहार करते हैं, इसलिए हमें केवल जेनेरिक मॉनिटरिंग से अधिक चाहिए।
इस पोस्ट में, हम Ruby on Rails एप्लिकेशन में कस्टम इंस्ट्रूमेंटेशन और मॉनिटरिंग जोड़ने की प्रक्रिया देखेंगे। इससे आपको इस बात की गहरी जानकारी मिलेगी कि आपका एप्लिकेशन कैसे व्यवहार कर रहा है।
कोड के साथ फॉलो करने के लिए पूर्वापेक्षाएँ:
- www.appsignal.com पर एक अकाउंट
- Docker इंस्टॉल और रनिंग (
docker-composeउपयोग के लिए)
इस पोस्ट के साथ आगे बढ़ने के लिए, आपको अपने AppSignal अकाउंट के साथ सैंपल एप्लिकेशन में AppSignal सेटअप करना होगा।
कस्टम इंस्ट्रूमेंटेशन और मॉनिटरिंग
जब आपको AppSignal द्वारा बॉक्स से बाहर इंस्ट्रूमेंट की जाने वाली चीज़ों से अधिक की आवश्यकता होती है, तो AppSignal जेम आपको अपने Rails एप्लिकेशन में कस्टम इंस्ट्रूमेंटेशन जोड़ने की अनुमति देता है।
कोड के भागों को इंस्ट्रूमेंट करना
मान लीजिए आप किसी एप्लिकेशन में एक नया फीचर जोड़ना चाहते हैं। जब कोई उपयोगकर्ता सभी पोस्ट देखने के लिए /posts पर जाता है, तो उन्हें उन पोस्ट को फ़िल्टर करने में सक्षम होना चाहिए जिनका शीर्षक किसी विशिष्ट अक्षर से शुरू होता है (या कुछ अधिक जटिल 🪄)।
यह नई खोज कार्यक्षमता पहले से ही Post मॉडल में Post.where_title_starts_with मेथड के साथ लागू की गई है। आइए PostsController#index को अपडेट करें ताकि यदि कोई विशिष्ट क्वेरी पैरामीटर मौजूद है तो नई मेथड का उपयोग किया जाए:
# app/controllers/posts_controller.rb def index starts_with = params[:starts_with] @posts = if starts_with.present? Post.where_title_starts_with(starts_with) else Post.all end endयह आपके एप्लिकेशन का इतना मुख्य हिस्सा है कि आप जानना चाहेंगे कि यह कैसा परफॉर्म करता है और जब वह परफॉरमेंस बदलती है। AppSignal इसके लिए कुछ तरीके प्रदान करता है।
सबसे पहले, हम Post.where_title_starts_with मेथड की सामग्री को इंस्ट्रूमेंट करेंगे। यदि आप किसी भी कोड ब्लॉक के बारे में इनसाइट्स प्राप्त करना चाहते हैं, तो आप कोड ब्लॉक्स को लपेटने के लिए इंस्ट्रूमेंटेशन ब्लॉक्स का उपयोग कर सकते हैं। मेथड को इस तरह अपडेट करें:
# app/models/post.rb def self.where_title_starts_with(letter) Appsignal.instrument('Post.where_title_starts_with', "Fetch posts that start with letter") do Analytics.track_post_title_search(letter.downcase) select('*, pg_sleep(0.01)').where("title ILIKE :letter", letter: "#{letter.downcase}%").load end endदूसरे, हम Analytics.track_post_title_search मेथड को भी इंस्ट्रूमेंट करना चाहते हैं जिसे कॉल किया जा रहा है क्योंकि app/services/analytics.rb कुछ भारी प्रोसेसिंग कर रहा है। इस मामले में, हम पूरे मेथड को अधिक सटीकता से इंस्ट्रूमेंट करने के लिए मेथड इंस्ट्रूमेंटेशन का उपयोग करेंगे:
# app/services/analytics.rb require 'appsignal/integrations/object' class Analytics def self.track_post_title_search(letter, sleep = sleep(1)) # Some heavy processing sleep 1 end appsignal_instrument_class_method :track_post_title_search endइनसाइट्स
उपरोक्त कोड को एप्लिकेशन में सेव करने के कुछ मिनट बाद, अपने AppSignal डैशबोर्ड पर उपलब्ध नई जानकारी पर एक नज़र डालें (यदि आपको जानकारी नहीं दिखती है, तो आपको डॉकर कंटेनर्स को फिर से रीस्टार्ट करने की आवश्यकता हो सकती है)। आप पोस्ट इंडेक्स पेज पर सर्च पैरामीटर के साथ जाकर नए फीचर को वेरिफाई कर सकते हैं: https://localhost:3000/posts?starts_with=f
डेटाबेस में बने पोस्ट की संख्या के आधार पर, /posts एंडपॉइंट काफी धीमा हो गया होगा।
यदि आप AppSignal पर परफॉरमेंस इश्यू खोलते हैं ('Performance' → 'Issue list') और PostsController#index एक्शन देखते हैं, तो पेज पर नीचे की ओर, आपको 'Event Timeline' देखने में सक्षम होना चाहिए। यह आपको इस बात का ब्रेकडाउन देता है कि विशिष्ट कोड चलाने में कितना समय खर्च होता है:
यह टाइमलाइन सभी परफॉरमेंस इवेंट्स के लिए मौजूद है, लेकिन यहां हम कस्टम इंस्ट्रूमेंटेशन इवेंट्स भी देख सकते हैं। यह हमें दिखाता है कि Post.where_title_starts_with को कॉल करने में 8.84 सेकंड लगे, जिसमें 2.01 सेकंड Analytics.track_post_title_search मेथड द्वारा उपयोग किए गए, और शेष समय एक एक्टिव रिकॉर्ड क्वेरी द्वारा उपयोग किया गया। आप व्यक्तिगत इवेंट्स में क्लिक करके आगे की जांच कर सकते हैं और उनके परफॉरमेंस के बारे में अधिक जानकारी देख सकते हैं — जैसे sql.active_record इवेंट।
AppSignal के इंस्ट्रूमेंटेशन हेल्पर्स आपको एप्लिकेशन कोड का अधिक विस्तृत ब्रेकडाउन देते हैं, इसलिए उन विशेष कोड के टुकड़ों में इनसाइट्स प्राप्त करना आसान हो जाता है जो आपको लगता है कि एप्लिकेशन के परफॉरमेंस को प्रभावित कर सकते हैं। आप AppSignal के इंस्ट्रूमेंटेशन गाइड में इसके बारे में अधिक जान सकते हैं।
एक्सेप्शन हैंडलिंग
अपने कोड के परफॉरमेंस की निगरानी के अलावा, आपको यह भी जानने की आवश्यकता है कि एप्लिकेशन कब अपेक्षा के अनुरूप व्यवहार नहीं करता और चीजें कहां गलत हो जाती हैं। हम पहले ही देख चुके हैं कि AppSignal उन एक्सेप्शंस को कैसे रिपोर्ट करता है जिन्हें हमारे कोड द्वारा हैंडल नहीं किया गया है। लेकिन हमेशा बॉक्स से बाहर आने वाली चीज़ों से थोड़ा अधिक होता है।
आप उस मौजूदा कोड को हटाकर शुरू कर सकते हैं जो एक इंटरमिटेंट एरर का कारण बनता है। हम देखते हैं कि डैशबोर्ड पर एरर देखते समय बैकट्रेस में यह एरर कहां होता है। app/controllers/pages_controller.rb के अंदर if स्टेटमेंट को हटा दें:
class PagesController < ApplicationController def home CreateRandomPostsJob.perform_later end endअब, ओवरव्यू डैशबोर्ड में, एप्लिकेशन की एरर दर में काफी गिरावट आएगी।
वर्तमान में, जब कोई उपयोगकर्ता किसी ऐसे पोस्ट को देखने का प्रयास करता है जो मौजूद नहीं है, तो एप्लिकेशन क्रैश हो जाता है — उदाहरण के लिए, https://localhost:3000/posts/doesnotexist। इसके बजाय, आप उन्हें एक मैसेज दिखाना चाह सकते हैं। PostsController के अंदर जहां ऐसा हो सकता है, वहां एक रेस्क्यू जोड़ें। #set_post मेथड को अपडेट करें:
# app/controllers/posts_controller.rb class PostsController < ApplicationController . . . private def set_post @post = Post.find(params[:id]) rescue ActiveRecord::RecordNotFound => e render json: { error: "Oops. That post isn't here" } , status: :not_found end . . endक्योंकि हम मैन्युअली एक्सेप्शन को हैंडल कर रहे हैं, यह स्वचालित रूप से AppSignal को रिपोर्ट नहीं किया जाएगा। आप अभी भी Appsignal.set_error का उपयोग करके एरर्स को मैन्युअली ट्रैक कर सकते हैं।
एरर को ट्रैक करने का सबसे आसान तरीका है कि इसे केवल फंक्शन के आर्गुमेंट के रूप में जोड़ दिया जाए जैसे Appsignal.set_error(e)। हम रिक्वेस्ट में अधिक संदर्भ जोड़ने की क्षमता का भी लाभ उठाना चाहते हैं। AppSignal आपको Appsignal.tag_request का उपयोग करके इवेंट्स को अपनी मनमानी जानकारी के साथ टैग करने की अनुमति देता है:
def set_post Appsignal.tag_request(user_id: 'user-from-params', post_id: params[:id]) @post = Post.find(params[:id]) rescue ActiveRecord::RecordNotFound => e Appsignal.set_error(e) render json: { error: "Oops. That post isn't here" }, status: :not_found endअब https://localhost:3000/posts/doesnotexist पर जाएं ताकि यह वेरिफाई हो सके कि आपको अपेक्षित JSON रिस्पॉन्स वापस मिलता है, एप्लिकेशन के क्रैश होने के बजाय।
इनसाइट्स
जब आप किसी ऐसे पोस्ट को देखने का प्रयास करते हैं जो मौजूद नहीं है, तो जोड़े गए अपडेट यह सुनिश्चित करते हैं कि एरर्स AppSignal को रिपोर्ट किए जाएं। AppSignal डैशबोर्ड पर, 'Errors → Issue list' में, नई रिपोर्ट की गई एरर (ActiveRecord::RecordNotFound) को ढूंढें और देखें।
एरर डिटेल पेज हमें एरर के बारे में उपयोगी संदर्भ देता है, जिसमें डिफ़ॉल्ट रूप से रिक्वेस्ट के बारे में जानकारी शामिल होती है जैसे HTTP मेथड, पैरामीटर्स, और सेशन डेटा। आप देख सकते हैं कि कस्टम टैग्स भी शामिल हैं, जो आपको मिलान करने वाले टैग वाली सभी एरर्स को फ़िल्टर करने की क्षमता देता है।
क्योंकि हमने रिक्वेस्ट को टैग किया, यह जानकारी एरर्स और अन्य इंस्ट्रूमेंटेड इवेंट्स में जुड़ जाती है। यदि आप कुछ बार व्यक्तिगत पोस्ट देखते हैं, उदाहरण के लिए, https://localhost:3000/posts/1, तो आप देखेंगे कि परफॉरमेंस मेजरमेंट देखते समय टैग्स भी शामिल हैं ('Performance' → 'Issue list' → 'PostsController#show')। आप गाइड्स में ट्रांजैक्शन टैगिंग के बारे में अधिक पढ़ सकते हैं।
ट्रांजैक्शन में कस्टम मेटाडेटा जोड़ने की यह क्षमता प्रोडक्शन में मुद्दों का निदान करने में मदद करने के लिए कई अवसर खोलती है। इसका एक बेहतरीन उदाहरण कुबेरनेट्स मेटाडेटा को अपनी एरर्स में जोड़ना है।
मेट्रिक्स
अब जब कुछ कस्टम इंस्ट्रूमेंटेशन और एरर मॉनिटरिंग लागू है, तो आपको एहसास हो सकता है कि कभी-कभी पोस्ट सर्च में बड़े स्पाइक्स होते हैं। जब भी कोई उपयोगकर्ता सर्च करता है, तो Analytics#track_post_title_search कॉल किया जाता है, जो कुछ गणना करता है और थर्ड-पार्टी सर्विस पर API कॉल करता है। इस थर्ड पार्टी की API पर रेट लिमिट्स हैं। हम ट्रैक करना चाहते हैं कि इसे कितनी बार कॉल किया जाता है ताकि यह नजर रखी जा सके कि एप्लिकेशन अपनी सीमाओं के कितना करीब है।
AppSignal आपको एप्लिकेशन में कस्टम मेट्रिक्स को ट्रैक करने की अनुमति देता है जैसा आप चाहते हैं।
सबसे पहले, हम ट्रैक करेंगे कि हम अपनी एनालिटिक्स सर्विस को कितनी बार कॉल कर रहे हैं और किस डेटा के साथ, एक काउंटर और टैग्स का उपयोग करके:
#app/services/analytics.rb require 'appsignal/integrations/object' class Analytics def self.track_post_title_search(letter, sleep = sleep(1)) Appsignal.increment_counter("track_post_search", 1, { letter: letter }) # Some heavy processing sleep 1 end appsignal_instrument_class_method :track_post_title_search endदूसरे, हम PostsController#index में लौटाए जा रहे पोस्ट की संख्या को भी ट्रैक करेंगे, क्योंकि यह एप्लिकेशन के व्यवहार का एक मुख्य हिस्सा है, और हम जानते हैं कि यह बढ़ता रहता है:
#app/controllers/posts_controller.rb class PostsController < ApplicationController . . def index . . Appsignal.set_gauge("posts_index", @posts.size, starts_with: params[:starts_with]) end endएप्लिकेशन पर चल रहा फेक ट्रैफिक स्क्रिप्ट कुछ डेटा जेनरेट करेगा, लेकिन अधिक विविधता जोड़ने के लिए, आइए f, l, और v से शुरू होने वाले पोस्ट भी सर्च करें।
इनसाइट्स
कस्टम मेट्रिक्स देखने के लिए, आपको AppSignal पर कस्टम ग्राफ़ के साथ एक डैशबोर्ड बनाना होगा। यह UI के माध्यम से किया जा सकता है, लेकिन हम इस उदाहरण के लिए बस एक इम्पोर्ट करेंगे। 'Dashboard' सेक्शन के तहत, 'Add dashboard' पर क्लिक करें और निम्नलिखित के साथ एक डैशबोर्ड इम्पोर्ट करें:
{ "title": "Post Search", "description": "Sample dashboard about posts search activity", "visuals": [ { "title": "Analytics", "line_label": "%name% %letter%", "display": "LINE", "format": "number", "draw_null_as_zero": true, "metrics": [ { "name": "track_post_search", "fields": [ { "field": "COUNTER" } ], "tags": [ { "key": "letter", "value": "*" } ] } ], "type": "timeseries" }, { "title": "Search", "line_label": "%name% %starts_with%", "display": "LINE", "format": "number", "draw_null_as_zero": true, "metrics": [ { "name": "posts_index", "fields": [ { "field": "GAUGE" } ], "tags": [ { "key": "starts_with", "value": "*" } ] } ], "type": "timeseries" } ] }आपको कुछ मिनटों के भीतर अपने ग्राफ़ पर डेटा दिखाई देना चाहिए। लाइन्स पर होवर करने से आपको उस समय सीमा के भीतर एकत्रित मेट्रिक्स का लेजेंड दिखाई देगा जिसे आप देख रहे हैं।
ध्यान दें कि यह प्रत्येक टैग वैल्यू के लिए अलग-अलग लाइन्स दिखाता है। वर्तमान में, हमारा फेक ट्रैफिक केवल अक्षर e के लिए सर्च कर रहा है, लेकिन क्योंकि हमने मैन्युअली अन्य अक्षरों के लिए सर्च किया, आपको ग्राफ़ पर प्रत्येक के लिए एक नई लाइन दिखाई देगी जो एक और डेटा पॉइंट को इंगित करती है।
क्या आपको लगा कि यह पर्याप्त था? AppSignal के पास पेशकश करने के लिए और अधिक कस्टम इंस्ट्रूमेंटेशन समाधान हैं जिन्हें हम यहां कवर नहीं करेंगे। एक जिसका त्वरित उल्लेख करना उचित है, वह है ब्रेडक्रंब्स। ब्रेडक्रंब्स आपको अपने एप्लिकेशन में कार्यों की एक सूची को ट्रैक करने की अनुमति देते हैं, जिसे तब एक एरर में रिपोर्ट किया जाएगा। आपके पास इस बारे में और भी अधिक विशिष्ट और क्रमबद्ध जानकारी होगी कि एरर का कारण क्या था।
गाइड्स में कस्टम इंस्ट्रूमेंटेशन के बारे में सब पढ़ें।
समापन: AppSignal के साथ Ruby ऐप्स के लिए कस्टम इंस्ट्रूमेंटेशन और मॉनिटरिंग
इस श्रृंखला के भाग 1 में आपके Ruby एप्लिकेशन के लिए AppSignal के बेसिक सेटअप और उपयोग को कवर किया गया था।
इस भाग में, हमने एक ऐसे एप्लिकेशन को लिया जिसमें पहले से ही बेहतरीन आउट-ऑफ-द-बॉक्स मॉनिटरिंग है और AppSignal जेम का उपयोग करके इसे और भी बेहतर बनाया।
AppSignal के कस्टम इंस्ट्रूमेंटेशन, एरर ट्रैकिंग, और परफॉरमेंस मॉनिटरिंग फीचर्स आपको इस बात की जानकारी देते हैं कि आपके एप्लिकेशन कैसे व्यवहार कर रहे हैं। यह आपके एप्लिकेशन को बॉक्स से बाहर बहुत कुछ देता है जबकि आपको जरूरत पड़ने पर नियंत्रण लेने देता है।
अपने कोड को जंगल में आज़ाद दौड़ने दें, जब तक आप इस बात पर नज़र रखते हैं कि यह कैसा कर रहा है। हैप्पी कोडिंग!
P.S. यदि आप Ruby Magic पोस्ट्स को प्रेस से निकलते ही पढ़ना चाहते हैं, तो हमारे Ruby Magic न्यूज़लेटर को सब्सक्राइब करें और कभी भी एक भी पोस्ट मिस न करें!