2.1 पहला लकड़हारा - log4j

जैसा कि आप पहले से ही जानते हैं, लॉग का इतिहास System.err.println()कंसोल पर रिकॉर्ड के आउटपुट के साथ शुरू हुआ। यह अभी भी डिबगिंग के लिए सक्रिय रूप से उपयोग किया जाता है, उदाहरण के लिए, Intellij IDEA इसका उपयोग कंसोल में त्रुटि संदेशों को प्रदर्शित करने के लिए करता है। लेकिन इस विकल्प की कोई सेटिंग नहीं है, तो चलिए आगे बढ़ते हैं।

पहला और सबसे लोकप्रिय लकड़हारा कहा जाता था Log4j। यह एक अच्छा और अत्यधिक अनुकूलन योग्य समाधान था। विभिन्न परिस्थितियों के कारण, यह निर्णय JDK में कभी नहीं आया, जिसने पूरे समुदाय को बहुत परेशान किया।

यह लकड़हारा केवल लॉग करने में सक्षम नहीं था, यह प्रोग्रामर द्वारा प्रोग्रामर के लिए बनाया गया था और उन्हें लॉगिंग के संबंध में लगातार उत्पन्न होने वाली समस्याओं को हल करने की अनुमति दी।

जैसा कि आप पहले से ही जानते हैं, लॉग को अंत में लिखा जाता है ताकि कोई व्यक्ति उन्हें पढ़ सके और यह समझने की कोशिश कर सके कि कार्यक्रम के संचालन के दौरान क्या हुआ - अपेक्षा के अनुरूप क्या और कब गलत हुआ।

इसके लिए तीन बातें थीं log4j:

  • सबपैकेज लॉगिंग;
  • परिशिष्टों का सेट (परिणाम);
  • गर्म पुनः लोड सेटिंग्स।

सबसे पहले, सेटिंग्स को log4jइस तरह से लिखा जा सकता है जैसे कि एक पैकेज में लॉगिंग को सक्षम करना और दूसरे में इसे अक्षम करना। उदाहरण के लिए, लॉग इन को सक्षम करना संभव था com.codegym.server, लेकिन इसे अक्षम करना com.codegym.server.payment। इससे लॉग से अनावश्यक जानकारी को जल्दी से निकालना संभव हो गया।

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

इस प्रकार प्रत्येक लॉग फ़ाइल को एक विशेष प्रकार की अपेक्षित समस्या के लिए ट्यून किया गया था। यह प्रोग्रामर के जीवन को बहुत सरल करता है जो गीगाबाइट लॉग फ़ाइलों को मैन्युअल रूप से देखने का आनंद नहीं लेते हैं।

और अंत में, तीसरा, log4jइसने प्रोग्राम को फिर से शुरू किए बिना सीधे लॉग सेटिंग्स को बदलने की अनुमति दी। जब किसी विशिष्ट त्रुटि पर अतिरिक्त जानकारी प्राप्त करने के लिए लॉग के कार्य को सही करना आवश्यक होता है तो यह बहुत आसान होता है।

महत्वपूर्ण! लॉग के दो संस्करण हैं log4j: 1.2.x और 2.xx , जो एक दूसरे के साथ असंगत हैं

आप कोड का उपयोग करके लकड़हारे को परियोजना से जोड़ सकते हैं:

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
  </dependency>
 
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
  </dependency>
</dependencies>

2.2 पहला आधिकारिक लकड़हारा - JUL: java.util.logging

जावा समुदाय में लकड़हारों का चिड़ियाघर दिखाई देने के बाद, डेवलपर्स ने JDKएक मानक लकड़हारा बनाने का फैसला किया, जिसका उपयोग हर कोई करेगा। लकड़हारा इस तरह दिखाई दिया JUL: पैकेज java.util.logging

हालाँकि, इसके विकास के दौरान, लकड़हारे के रचनाकारों ने एक आधार के रूप में नहीं log4j, बल्कि IBM के लकड़हारे के एक संस्करण को लिया, जिसने इसके विकास को प्रभावित किया। अच्छी खबर यह है कि लकड़हारा JULशामिल है JDK, बुरी खबर यह है कि बहुत कम लोग इसका इस्तेमाल करते हैं।

जुलाई

डेवलपर्स ने न केवल "एक और सार्वभौमिक मानक"JUL बनाया , उन्होंने इसके लिए अपने स्वयं के लॉगिंग स्तर भी बनाए, जो उस समय के लोकप्रिय लकड़हारों द्वारा स्वीकार किए गए स्तरों से भिन्न थे।

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

हालांकि लकड़हारा ही काफी अच्छा है। लकड़हारा बनाना कमोबेश एक जैसा है। ऐसा करने के लिए, आपको आयात करने की आवश्यकता है:


java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());

लॉगिंग कहां से आ रही है यह जानने के लिए कक्षा का नाम विशेष रूप से पास किया गया है।

केवल रिलीज़ के साथ, डेवलपर्स ने महत्वपूर्ण समस्याओं को हल किया, जिसके बाद इसका JULउपयोग करना वास्तव में सुविधाजनक है। इससे पहले, यह किसी प्रकार का दोयम दर्जे का लकड़हारा था।

यह लकड़हारा लैम्ब्डा एक्सप्रेशन और आलसी मूल्यांकन का भी समर्थन करता है। से शुरू करके Java 8आप पास हो सकते हैं Supplier<String>। यह केवल उस समय एक स्ट्रिंग को पढ़ने और बनाने में मदद करता है जब इसकी वास्तव में आवश्यकता होती है, और हर बार नहीं, जैसा कि पहले था।

एक तर्क के साथ तरीके Supplier<String> msgSupplierइस तरह दिखते हैं:

public void info(Supplier msgSupplier) {
   log(Level.INFO, msgSupplier);
}

2.3 पहला लॉगर रैपर - जेसीएल: जकार्ता कॉमन्स लॉगिंग

लंबे समय तक लकड़हारों के बीच कोई एकल मानक नहीं था, इसे JULएक हो जाना चाहिए था, लेकिन यह बदतर था log4j, इसलिए एकल मानक कभी प्रकट नहीं हुआ। लेकिन लकड़हारों का एक पूरा चिड़ियाघर दिखाई दिया, जिनमें से प्रत्येक एक जैसा बनना चाहता था।

जेसीएल

हालाँकि, साधारण जावा डेवलपर्स को यह पसंद नहीं आया कि लगभग हर लाइब्रेरी का अपना लकड़हारा होता है और उसे किसी विशेष तरीके से कॉन्फ़िगर करने की आवश्यकता होती है। इसलिए, समुदाय ने अन्य लकड़हारे पर एक विशेष आवरण बनाने का फैसला किया - यह हैJCL: jakarta commons logging

और फिर, एक नेता बनने के लिए बनाई गई परियोजना एक नहीं बन पाई। आप विजेता नहीं बना सकते, आप केवल विजेता बन सकते हैं। कार्यक्षमता JCLबहुत खराब थी और कोई भी इसका उपयोग नहीं करना चाहता था। लकड़हारा, जिसे सभी लकड़हारों को बदलने के लिए डिज़ाइन किया गया था, उसी भाग्य से मिला क्योंकि इसका JULउपयोग नहीं किया गया था।

हालाँकि इसे अपाचे समुदाय द्वारा जारी कई पुस्तकालयों में जोड़ा गया है, लकड़हारों का चिड़ियाघर केवल बढ़ा है।

2.4 पहला अंतिम लकड़हारा - लॉगबैक

लेकिन वह सब नहीं है। डेवलपर ने log4jफैसला किया कि वह सबसे चतुर था (आखिरकार, ज्यादातर लोगों ने उसके लकड़हारे का इस्तेमाल किया) और एक नया बेहतर लकड़हारा लिखने का फैसला किया जो log4jअन्य लकड़हारों के फायदों को मिलाएगा।

नए लकड़हारे को बुलाया गया Logback। यह वह लकड़हारा था जिसे भविष्य का एकल लकड़हारा बनना था जिसका उपयोग हर कोई करेगा। यह उसी विचार पर आधारित था जैसा कि में था log4j

आप इस लकड़हारे को कोड का उपयोग करके परियोजना से जोड़ सकते हैं:


<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.6</version>
</dependency>

मतभेद थे Logback:

  • बेहतर प्रदर्शन;
  • जोड़ा मूल समर्थन slf4j;
  • विस्तारित फ़िल्टरिंग विकल्प।

इस लकड़हारे का एक और फायदा यह था कि इसकी बहुत अच्छी डिफ़ॉल्ट सेटिंग्स थीं। और आपको लकड़हारे को तभी कॉन्फ़िगर करना था जब आप उनमें कुछ बदलना चाहते थे। साथ ही, सेटिंग फ़ाइल को कॉर्पोरेट सॉफ़्टवेयर के लिए बेहतर रूप से अनुकूलित किया गया था - इसके सभी कॉन्फ़िगरेशन xml/.

डिफ़ॉल्ट रूप से, Logbackइसे किसी भी सेटिंग की आवश्यकता नहीं होती है और स्तर DEBUGऔर ऊपर के सभी लॉग रिकॉर्ड करता है। यदि आपको अलग व्यवहार की आवश्यकता है, तो इसे xmlकॉन्फ़िगरेशन के माध्यम से कॉन्फ़िगर किया जा सकता है:

<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

2.5 नवीनतम सार्वभौमिक लकड़हारा - SLF4J: जावा के लिए सरल लॉगिंग मुखौटा

गोल्डन मीन खोजने में कितना समय लग सकता है...

2006 में, रचनाकारों में से एक ने log4jपरियोजना छोड़ दी और एक सार्वभौमिक लकड़हारा बनाने के लिए फिर से प्रयास करने का निर्णय लिया। लेकिन इस बार यह एक नया लकड़हारा नहीं था, बल्कि एक नया सार्वभौमिक मानक (आवरण) था जिसने अलग-अलग लकड़हारे को आपस में बातचीत करने की अनुमति दी थी।

इस लकड़हारे को बुलाया गया था , यह slf4j — Simple Logging Facade for Javaचारों ओर एक आवरण था log4j,। इस लकड़हारे ने एक वास्तविक समस्या का समाधान किया - लकड़हारों के एक चिड़ियाघर का प्रबंधन, इसलिए सभी ने तुरंत इसका उपयोग करना शुरू कर दिया।JULcommon-loggins and logback

हम वीरतापूर्वक उन समस्याओं का समाधान करते हैं जो हम अपने लिए पैदा करते हैं। जैसा कि आप देख सकते हैं, प्रगति इस बिंदु पर पहुंच गई है कि हमने रैपर के ऊपर एक आवरण बनाया है ...

रैप में ही दो भाग होते हैं:

  • API, जो अनुप्रयोगों में प्रयोग किया जाता है;
  • कार्यान्वयन जो प्रत्येक लकड़हारे के लिए अलग-अलग निर्भरता के रूप में जोड़े जाते हैं।

आप कोड का उपयोग करके लकड़हारे को परियोजना से जोड़ सकते हैं:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.2</version>
</dependency>

यह सही कार्यान्वयन को जोड़ने के लिए पर्याप्त है और वह यह है: पूरी परियोजना इसके साथ काम करेगी।

2.6 slf4j में अनुकूलन

Slf4jलॉगिंग के लिए स्ट्रिंग स्वरूपण जैसी सभी नई सुविधाओं का समर्थन करता है । इससे पहले ऐसी समस्या आई थी। मान लीजिए कि आप लॉग में एक संदेश प्रिंट करना चाहते हैं:

log.debug("User " + user + " connected from " + request.getRemoteAddr());

इस कोड में कोई समस्या है। मान लीजिए कि आपका एप्लिकेशन काम करता है productionऔर लॉग में कोई नहीं लिखता है DEBUG-messages, हालांकि, विधि log.debug()अभी भी कॉल की जाएगी, और जब इसे कॉल किया जाता है, तो निम्न विधियों को भी कॉल किया जाएगा:

  • user.toString();
  • request.getRemoteAddr();

इन विधियों को कॉल करने से एप्लिकेशन धीमा हो जाता है। डिबगिंग के दौरान ही उनकी कॉल की जरूरत होती है, लेकिन फिर भी उन्हें कॉल किया जाता है।

तर्क की दृष्टि से, इस समस्या को लॉगिंग लाइब्रेरी में ही हल किया जाना था। और log4j के पहले संस्करण में समाधान सामने आया:

if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}

लट्ठे के लिए एक पंक्ति के स्थान पर अब तीन लिखना आवश्यक था। जिसने नाटकीय रूप से कोड की पठनीयता को खराब कर दिया और log4j.

लकड़हारा slf4jस्मार्ट लॉगिंग की पेशकश करके स्थिति को थोड़ा सुधारने में सक्षम था। ऐसा दिखता था:

log.debug("User {} connected from {}", user, request.getRemoteAddr());

जहां {}विधि में पारित किए गए तर्कों के सम्मिलन को इंगित करें। अर्थात्, पहला {}उपयोगकर्ता से मेल खाता है, {}दूसरा request.getRemoteAddr().

लॉगिंग स्तर लॉगिंग की अनुमति देता है, तो इन मापदंडों को एक ही संदेश में जोड़ा जाएगा। संपूर्ण नहीं है, लेकिन अन्य सभी विकल्पों से बेहतर है।

उसके बाद, SLF4Jइसकी लोकप्रियता तेजी से बढ़ने लगी, फिलहाल यह सबसे अच्छा उपाय है।

इसलिए, हम बंडल के उदाहरण का उपयोग करके लॉगिंग पर विचार करेंगे slf4j-log4j12