रूबी में लॉग्स के साथ काम करना
लॉगिंग उन प्राथमिक कार्यों में से एक है जिसे एक एप्लिकेशन आमतौर पर संबोधित करता है। लॉग्स का उपयोग तब किया जाता है जब आपको आवश्यकता होती है, उदाहरण के लिए,
- अपने ऐप्स के अंदर क्या हो रहा है, यह देखने के लिए,
- उनकी निगरानी करने के लिए, या
- कुछ विशिष्ट डेटा के लिए मेट्रिक्स एकत्र करने के लिए।
एक नई प्रोग्रामिंग भाषा सीखते समय, जानकारी लॉग करने के लिए पहला स्पष्ट विकल्प नेटिव मैकेनिज्म है। यह आमतौर पर आसान, प्रलेखित, और समुदाय में अच्छी तरह से फैला हुआ होता है।
लॉग डेटा कंपनी, व्यवसाय, और आपके द्वारा काम किए जा रहे एप्लिकेशन के प्रकार के आधार पर बहुत भिन्न होता है। इसलिए, यह समझना बहुत महत्वपूर्ण है कि आपके और आपकी टीम द्वारा चुना गया लॉगिंग समाधान इसके समग्र उपयोग को कैसे प्रभावित करेगा।
इस लेख में, हम रूबी और रेल्स के लिए लॉगिंग के उपलब्ध विकल्पों के माध्यम से एक सवारी लेंगे, बिल्ट-इन वालों से लेकर प्रिय थर्ड-पार्टी कम्युनिटी फ्रेमवर्क तक। चलिए शुरू करते हैं!
रूबी के बिल्ट-इन विकल्प
रूबी लॉगिंग को संभालने के लिए दो बिल्ट-इन विकल्पों के साथ आता है: प्रिंटिंग कमांड (विशेष रूप से कमांड-लाइन परिदृश्यों के लिए डिज़ाइन किए गए) और Logger क्लास।
आइए उन्हें थोड़ा एक्सप्लोर करें।
कंसोल पर प्रिंट करना
रूबी में कंसोल पर टेक्स्ट प्रिंट करने के चार सामान्य तरीके हैं: puts, print, p, और pp।
puts मेथड आपके द्वारा पास की गई किसी भी चीज़ को प्रिंट करता है, उसके बाद एक नई लाइन:
2.7.0 :001 > puts "Hey, I'm a log!"
Hey, I'm a log!
=> nil
print मेथड puts के समान है, हालांकि यह हमेशा आर्गुमेंट्स को to_s मेथड का उपयोग करके स्ट्रिंग्स में परिवर्तित करता है।
अंत में, p और pp मेथड दोनों आपके द्वारा पास किए गए रॉ ऑब्जेक्ट को बिना रूपांतरण किए प्रिंट करेंगे; एकमात्र अंतर यह है कि बाद वाला आउटपुट को अधिक इंडेंटेड तरीके से फॉर्मेट करता है, जबकि पूर्व नहीं करता।
एप्लिकेशन लॉग्स
सर्वर पर चल रहे एप्लिकेशन के लिए, कंसोल पर प्रिंट करना मायने नहीं रखता।
इसके बजाय, हम Logger क्लास का उपयोग करते हैं, जो बहुत अधिक लचीला है।
यहाँ बताया गया है कि आप इसका उपयोग "डिबग" लॉग प्रिंट करने के लिए कैसे कर सकते हैं:
require "logger"
logger = Logger.new(STDOUT)
logger.debug("I'm a debug log")
हम इसे लॉग्स को एक फाइल में स्टोर करने के लिए भी कॉन्फ़िगर कर सकते थे, या यदि हम चाहते थे तो STDOUT पर प्रिंट करने के बजाय उन्हें लॉग एग्रीगेटर को भेज सकते थे।
यदि आप सोच रहे हैं, तो "डिबग" एक लॉग लेवल है। लॉग लेवल आपको सिस्टम को बताने देते हैं "यह लॉग संदेश एक निश्चित प्रकार की घटना से संबंधित है।" छह बिल्ट-इन लॉग लेवल हैं: Fatal, Error, Warn, Info, Debug और Unknown।
logger.debug("I'm a debug log")
logger.info("I'm an info log")
logger.warn("I'm a warn log")
logger.error("I'm an error log: error message")
logger.fatal("I'm a fatal log")
जब हम लॉग आउटपुट को देखते हैं, तो हम देखते हैं कि लॉग लेवल, प्रोसेस आईडी और टाइमस्टैम्प प्रत्येक लाइन में जोड़े गए हैं:

एक और बढ़िया विशेषता यह है कि आप अपने Logger ऑब्जेक्ट को एक विशिष्ट लेवल पर सेट करने की क्षमता रखते हैं:
logger.level = Logger::WARN
जब आप ऐसा करते हैं, तो Logger केवल warn के बराबर या उससे अधिक महत्व के लॉग्स को संभालेगा। यह प्रोडक्शन में बहुत उपयोगी है, जहां हम आकार या सुरक्षा कारणों से "डिबग" लॉग्स को सहेजना नहीं चाहते होंगे।
यह आउटपुट होना चाहिए:

अपने लॉग्स कस्टमाइज़ करना
यदि आप अपने लॉग्स को कस्टमाइज़ करना चाहते हैं, तो बहुत सारे विकल्प हैं। उदाहरण के लिए, डेट और समय बदलने के लिए, बस डिफ़ॉल्ट को ओवरराइट करें:
logger.datetime_format = "%Y-%m-%d %H:%M"
आउटपुट का एक उदाहरण यहां दिया गया है:
W, [2020-07-28 10:50#87786] WARN -- : I'm a warn log
date_time फॉर्मेट मानक विशिष्टता का पालन करता है, इसलिए ऐसे परिवर्तन करते समय इसका संदर्भ लेना सुनिश्चित करें।
हालांकि, कभी-कभी, आपको अपने लॉग्स के फॉर्मेट को पूरी तरह से संशोधित करने की आवश्यकता हो सकती है। इस उद्देश्य के लिए, रूबी Formatter क्लास प्रदान करता है। यह डेवलपर्स को डिफ़ॉल्ट टेम्पलेट को ओवरराइट करने की अनुमति देकर काम करता है जिसका उपयोग Logger लॉग्स प्रिंट करने के लिए करता है।
कल्पना करें कि आपका ऐप एक केंद्रीकृत लॉग विश्लेषण टूल का उपयोग करता है और आपके सभी लॉग्स को name=value फॉर्मेट में प्रिंट करने की आवश्यकता है। यह नया फॉर्मेटर कोड होगा:
logger.formatter = proc do |severity, datetime, progname, msg|
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
"date=[#{date_format}] severity=#{severity.ljust(5)} pid=##{Process.pid} message='#{msg}'\n"
end
यहां, हम सभी लॉग्स को इंटरसेप्ट करने और उन्हें प्रिंट करने के डिफ़ॉल्ट तरीके को वांछित तरीके में बदलने के लिए एक proc का उपयोग कर रहे हैं। अब, हमारे पास निम्नलिखित परिणाम है:

कोड की कुछ ही लाइनों के साथ, आपके सभी ऐप लॉग्स अब टूल द्वारा इंडेक्स किए जा सकते हैं।
JSON में लॉगिंग
Formatter की शक्ति के साथ, अपने लॉग्स को जो भी आउटपुट प्रकार आप चाहते हैं उसमें कस्टमाइज़ करना आसान है। उदाहरण के लिए, हम अपने लॉग्स को उस फॉर्मेट में आउटपुट करने के लिए JSON मॉड्यूल का उपयोग कर सकते हैं।
require "json"
logger.formatter = proc do |severity, datetime, progname, msg|
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
JSON.dump(date: "#{date_format}", severity:"#{severity.ljust(5)}", pid:"##{Process.pid}", message: msg) + "\n"
end
और, यहां परिणामी लॉग्स हैं:

फाइल में लॉगिंग
जैसा कि पहले देखा गया, Logger कंस्ट्रक्टर पहले आर्गुमेंट के रूप में वह स्थान प्राप्त करता है जहां लॉग स्टोर किया जाना चाहिए।
यदि आप अपने लॉग्स को एक फाइल में सहेजना चाहते हैं, तो बस ऐसा कहें:
require 'logger'
logger = Logger.new('my_logs.log')
यह उसी फोल्डर में एक नई फाइल my_logs.log बनाएगा जहां आपकी रूबी फाइल जिसमें यह कोड है, स्थित है:

हालांकि, क्लास कई कस्टम विकल्पों की भी अनुमति देती है, जैसे रिटेंशन पॉलिसी कॉन्फिग। निम्न उदाहरण लें:
# वर्तमान सप्ताह के लिए डेटा रखें।
Logger.new('my_weekly_logs.log', 'weekly')
# आज और पिछले 2 महीनों के लिए डेटा रखें।
Logger.new('my_latest_2_months_logs.log', 2, 'monthly')
# जब यह आकार में 26GB से अधिक हो जाए तो लॉग को पुनरारंभ करें।
Logger.new('my_custom_logs.log', 0, 20 * 1024 * 1024 * 1024)
दूसरे पैरामीटर के रूप में, Logger यह परिभाषा स्वीकार करता है कि उसे कितनी बार लॉग्स को रखना या मिटाना चाहिए।
पहले ऑब्जेक्ट में, लॉग्स केवल एक सप्ताह के लिए रखे जाएंगे। दूसरा उन्हें दो महीने की रेंज के लिए स्टोर करेगा, जबकि नवीनतम केवल फाइल के आकार का विश्लेषण करेगा (उदाहरण के लिए, जब भी यह 20GB तक पहुंचता है, इसे तीसरे पैरामीटर के आधार पर त्याग दिया जाएगा)।
रूबी ऑन रेल्स में लॉगिंग
अब तक हमने Logger के अधिकांश लाभ देखे हैं, उन सभी का उपयोग रेल्स ऐप्स के साथ किया जा सकता है। Logger का रेल्स संस्करण रूबी के नेटिव क्लास का एक सरल विस्तार है।
इसके अलावा, रेल्स डेवलपर्स को अपने लॉग्स को कई लॉगर्स पर प्रसारित करने की अनुमति देने के लिए एक अच्छी सुविधा भी जोड़ता है। इस प्रकार, यदि आप एक से अधिक लॉगिंग लाइब्रेरी के साथ काम करना चाहते हैं, तो आप रेल्स logger के भीतर ऐसा कर सकते हैं:
custom_logger = Logger.new(STDOUT)
Rails.logger.extend(ActiveSupport::Logger.broadcast(custom_logger))
यह तब भी उपयोगी हो सकता है जब आपको उन स्थानों के बारे में कुछ इंटेलिजेंस की आवश्यकता हो जहां आपके लॉग्स जाने चाहिए। आपके ऐप के कुछ हिस्सों को अलग-अलग स्थानों या अलग-अलग फॉर्मेट में लॉग्स की आवश्यकता हो सकती है।
थर्ड-पार्टी लॉगिंग फ्रेमवर्क चुनना
यदि रूबी का बिल्ट-इन लॉगर ठीक वही नहीं करता जो आपको चाहिए, तो आपके पास विकल्प हैं।
जब थर्ड-पार्टी लॉगिंग फ्रेमवर्क चुनने की बात आती है तो बहुत सारे विकल्प होते हैं। इनमें से सबसे लोकप्रिय Lograge है। आइए उस पर एक नज़र डालें!
Lograge के साथ पहले कदम
Lograge रेल्स ऐप्स के लिए बनाया गया था। यदि आप वेनिला रूबी के साथ काम कर रहे हैं, तो यह एक अच्छा विकल्प नहीं हो सकता है।
इसे इंस्टॉल करने के लिए, बस निम्नलिखित जेम जोड़ें:
bundle add lograge
फिर, config/initializers/lograge.rb पर एक नई कॉन्फिग फाइल बनाएं जिसमें निम्न कोड हो:
Rails.application.configure do
config.lograge.enabled = true
config.lograge.custom_options = lambda do |event|
{ time: event.time }
end
end
यह कॉन्फिग Lograge को सक्षम करता है और उस समय को परिभाषित करता है जब एक लॉग, जिसे फ्रेमवर्क द्वारा एक इवेंट माना जाता है, प्रिंट किया जाना है।
जब आप रेल्स ऐप शुरू करते हैं और पहले एंडपॉइंट को एक्सेस करते हैं, तो Lograge अनुरोध सारांश प्रिंट करेगा। Lograge सेटअप से पहले और बाद में लॉग्स की तुलना करने पर, क्रमशः, कुछ ऐसा परिणाम मिलता है जैसा नीचे दिखाया गया है:

फिर से, Lograge कोई सिल्वर बुलेट नहीं है; यह वास्तव में एक बहुत ही राय वाला फ्रेमवर्क है। इसलिए, आपको संभवतः इसका उपयोग बिल्ट-इन Logger (या आपकी पसंद के अन्य फ्रेमवर्क) के साथ करना होगा।
समेटना
अंत में, यह स्पष्ट हो जाता है कि लॉगिंग न केवल आपके प्रोजेक्ट्स का एक महत्वपूर्ण हिस्सा है बल्कि बहुत कम आंका जाता है। आपके द्वारा उपयोग किए जा रहे टूल्स को बेहतर ढंग से समझना, चाहे वे नेटिव हों, आपको बेहतर परिणाम प्राप्त करने में भी मदद करेगा।
एक नए फ्रेमवर्क को अपनाने से पहले बहुत सारे परीक्षण करना सुनिश्चित करें। कभी-कभी आपका प्लेटफॉर्म पहले से ही बेहतरीन बिल्ट-इन विकल्पों के साथ बंडल होता है। यदि ऐसा नहीं है, तो निर्धारित करें कि क्या यह पहले से अंदर वाले के साथ अन्य फ्रेमवर्क के उपयोग की अनुमति देता है।
शुभकामनाएं!