Java.util.log का उपयोग क्यों नहीं किया जाता है?


351

अपने जीवन में पहली बार मैं अपने आप को एक ऐसी स्थिति में पाता हूँ जहाँ मैं एक जावा एपीआई लिख रहा हूँ जो कि खुला हुआ होगा। उम्मीद है कि कई अन्य परियोजनाओं में शामिल किया जाएगा।

लॉगिंग के लिए मैंने (और वास्तव में मैं जिन लोगों के साथ काम करता हूं) हमेशा JUL (java.util.log) का उपयोग किया है और इसके साथ कभी कोई समस्या नहीं थी। हालाँकि अब मुझे और अधिक विस्तार से समझने की आवश्यकता है कि मुझे अपने एपीआई विकास के लिए क्या करना चाहिए। मैंने इस पर कुछ शोध किया है और मुझे जो जानकारी मिली है उससे मैं और अधिक भ्रमित हो गया हूं। इसलिए यह पद।

चूँकि मैं JUL से आता हूँ, मैं उस पर पक्षपाती हूँ। बाकी मेरा ज्ञान इतना बड़ा नहीं है।

मैंने जो शोध किया है उससे मैं इन कारणों से सामने आया हूं कि लोग JUL को पसंद क्यों नहीं करते हैं:

  1. "मैंने जावा में विकसित करना शुरू कर दिया था, जब सूरज ने JUL को रिलीज़ किया था, उससे पहले यह मेरे लिए आसान था कि मैं कुछ नया सीखने के बजाय लॉगिंग-फ्रेमवर्क-एक्स को जारी रखूं" । हम्म। मैं मजाक नहीं कर रहा, यह वास्तव में लोग क्या कहते हैं। इस तर्क के साथ हम सभी COBOL कर सकते हैं। (हालांकि मैं निश्चित रूप से यह खुद को एक आलसी दोस्त होने से संबंधित कर सकता हूं)

  2. "मुझे JUL में लॉगिंग स्तरों के नाम पसंद नहीं हैं" । ठीक है, गंभीरता से, यह सिर्फ एक नई निर्भरता को पेश करने के लिए पर्याप्त कारण नहीं है।

  3. "मुझे JUL से आउटपुट का मानक प्रारूप पसंद नहीं है" । हम्म। यह सिर्फ कॉन्फ़िगरेशन है। आपको कुछ भी कोड-वार करने की आवश्यकता नहीं है। (सच है, पुराने दिनों में वापस आपको इसे सही करने के लिए अपना फॉर्मैटर क्लास बनाना पड़ा होगा)।

  4. "मैं अन्य पुस्तकालयों का उपयोग करता हूं जो लॉगिंग-फ्रेमवर्क-एक्स का भी उपयोग करते हैं, इसलिए मैंने सोचा कि बस उस एक का उपयोग करना आसान है" । यह एक गोल तर्क है, है ना? 'सब लोग' लॉगिंग-फ्रेमवर्क-एक्स का उपयोग क्यों करता है और JUL का नहीं?

  5. "हर कोई लॉगिंग-फ्रेमवर्क-एक्स का उपयोग कर रहा है" । यह मेरे लिए सिर्फ उपरोक्त का एक विशेष मामला है। बहुमत हमेशा सही नहीं होता है।

तो असली बड़ा सवाल यह है कि JUL क्यों नहीं? । यह क्या है मुझे याद किया? लॉगिंग facades (SLF4J, JCL) के लिए raison d'être यह है कि कई लॉगिंग कार्यान्वयन ऐतिहासिक रूप से मौजूद हैं और इसका कारण वास्तव में JUL से पहले के युग में वापस जाता है जैसा कि मैं इसे देखता हूं। यदि JUL सही था, तो लॉगिंग facades मौजूद नहीं होगा, या क्या? मामलों को और अधिक भ्रामक बनाने के लिए JUL कुछ हद तक स्वयं एक मुखौटा है, जिससे हैंडलर, फॉर्मेटर्स और यहां तक ​​कि LogManager को स्वैप किया जा सकता है।

एक ही चीज़ (लॉगिंग) करने के कई तरीकों को अपनाने के बजाय, हमें यह सवाल नहीं करना चाहिए कि वे पहली जगह में क्यों आवश्यक थे? (और देखें कि क्या वे कारण अभी भी मौजूद हैं)

ठीक है, अब तक के मेरे शोध से कुछ चीजें सामने आई हैं, जिन्हें मैं देख सकता हूं कि JUL के साथ वास्तविक मुद्दे हो सकते हैं :

  1. प्रदर्शन । कुछ का कहना है कि SLF4J में प्रदर्शन बाकी के मुकाबले बेहतर है। यह मुझे समयपूर्व अनुकूलन का मामला लगता है। यदि आपको प्रति सेकंड सैकड़ों मेगाबाइट लॉग इन करने की आवश्यकता है, तो मुझे यकीन नहीं है कि आप वैसे भी सही रास्ते पर हैं। JUL भी विकसित हुआ है और आपने जावा 1.4 पर जो परीक्षण किए हैं वे अब सच नहीं होंगे। आप इसके बारे में यहां पढ़ सकते हैं और इस फिक्स ने इसे जावा 7 में बना दिया है। कई लोग लॉगिंग विधियों में स्ट्रिंग कॉन्फैटन के ओवरहेड के बारे में भी बात करते हैं। हालाँकि टेम्पलेट आधारित लॉगिंग इस लागत से बचा जाता है और यह JUL में भी मौजूद है। व्यक्तिगत रूप से मैं वास्तव में कभी भी टेम्पलेट आधारित लॉगिंग नहीं लिखता। उसके लिए बहुत आलसी। उदाहरण के लिए अगर मैं JUL के साथ ऐसा करता हूं:

    log.finest("Lookup request from username=" + username 
       + ", valueX=" + valueX
       + ", valueY=" + valueY));

    मेरी आईडीई मुझे चेतावनी देगी और अनुमति मांगेगी कि इसे इसे बदलना चाहिए:

    log.log(Level.FINEST, "Lookup request from username={0}, valueX={1}, valueY={2}", 
       new Object[]{username, valueX, valueY});

    .. जिसे मैं निश्चित रूप से स्वीकार करूंगा। अनुमति प्रदान की गई ! आपके सहयोग के लिए धन्यवाद।

    इसलिए मैं वास्तव में ऐसे बयान खुद नहीं लिखता, जो आईडीई द्वारा किया जाता है।

    प्रदर्शन के मुद्दे पर निष्कर्ष में मुझे ऐसा कुछ भी नहीं मिला जो यह सुझाव दे कि प्रतियोगिता की तुलना में JUL का प्रदर्शन ठीक नहीं है।

  2. वर्गपथ से विन्यास । आउट-ऑफ-द-बॉक्स JUL क्लासपाथ से कॉन्फ़िगरेशन फ़ाइल लोड नहीं कर सकता है। यह ऐसा करने के लिए कोड की कुछ पंक्तियाँ है । मैं देख सकता हूं कि यह कष्टप्रद क्यों हो सकता है लेकिन समाधान छोटा और सरल है।

  3. आउटपुट हैंडलर्स की उपलब्धता । जूल 5 आउटपुट हैंडलर आउट-ऑफ-द-बॉक्स के साथ आता है: कंसोल, फ़ाइल स्ट्रीम, सॉकेट और मेमोरी। इन्हें बढ़ाया जा सकता है या नए लिखे जा सकते हैं। उदाहरण के लिए यह UNIX / Linux Syslog और Windows इवेंट लॉग में लिखा जा सकता है। मुझे व्यक्तिगत रूप से इसकी आवश्यकता कभी नहीं थी और न ही मैंने इसका उपयोग देखा है, लेकिन मैं निश्चित रूप से इससे संबंधित हूं कि यह एक उपयोगी विशेषता क्यों हो सकती है। लॉगबैक उदाहरण के लिए Syslog के लिए एक परिशिष्ट के साथ आता है। फिर भी मैं यह तर्क दूंगा कि

    1. आउटपुट गंतव्यों की जरूरतों का 99.5% JUL के आउट-ऑफ-द-बॉक्स में शामिल है।
    2. JUL के शीर्ष पर कस्टम हैंडलर द्वारा विशेष जरूरतों को पूरा किया जा सकता है, बजाय इसके कि कुछ और के ऊपर। मेरे लिए ऐसा कुछ नहीं है जो यह बताता है कि JUL के लिए Syslog आउटपुट हैंडलर लिखने में अधिक समय लगता है, क्योंकि यह किसी अन्य लॉगिंग फ्रेमवर्क के लिए है।

मैं वास्तव में चिंतित हूँ कि कुछ ऐसा है जिसकी मैंने अनदेखी की है। JUL के अलावा लॉगिंग facades और लॉगिंग कार्यान्वयन का उपयोग इतना व्यापक है कि मुझे इस निष्कर्ष पर आना होगा कि यह मुझे है जो अभी समझ में नहीं आता है। यह पहली बार नहीं होगा, मुझे डर है। :-)

तो मुझे अपने एपीआई के साथ क्या करना चाहिए? मैं चाहता हूं कि यह सफल हो। मैं निश्चित रूप से सिर्फ "प्रवाह के साथ जा सकता हूं" और SLF4J (जो इन दिनों सबसे लोकप्रिय लगता है) को लागू करता है, लेकिन अपने स्वयं के लिए मुझे अभी भी ठीक से समझने की आवश्यकता है कि आज के जूल के साथ क्या गलत है जो सभी फ़ज़ल को वारंट करता है? क्या मैं अपनी लाइब्रेरी के लिए JUL चुनकर खुद को तोड़फोड़ करूंगा?

परीक्षण प्रदर्शन

(07- JUL-2012 पर nolan600 द्वारा जोड़ा गया अनुभाग)

SLF4J के पैराड्राइज़ेशन के बारे में Ceki से एक संदर्भ नीचे है जो कि JUL की तुलना में 10 गुना या अधिक तेज़ है। इसलिए मैंने कुछ सरल परीक्षण करना शुरू कर दिया है। पहली नज़र में दावा निश्चित रूप से सही है। यहाँ प्रारंभिक परिणाम हैं (पर पढ़ें!):

  • निष्पादन समय SLF4J, बैकएंड लॉगबैक: 1515
  • निष्पादन समय SLF4J, बैक JUL: 12938
  • निष्पादन समय JUL: 16911

ऊपर दिए गए नंबर msecs हैं इसलिए कम बेहतर है। तो 10 गुना प्रदर्शन अंतर पहले वास्तव में बहुत करीब है। मेरी प्रारंभिक प्रतिक्रिया: यह बहुत कुछ है!

यहाँ परीक्षण का मूल है। जैसा कि एक पूर्णांक देखा जा सकता है और एक स्ट्रिंग को लूप में कस दिया जाता है जिसका उपयोग लॉग स्टेटमेंट में किया जाता है:

    for (int i = 0; i < noOfExecutions; i++) {
        for (char x=32; x<88; x++) {
            String someString = Character.toString(x);
            // here we log 
        }
    }

(मैं चाहता था कि लॉग स्टेटमेंट दोनों में एक आदिम डेटा प्रकार (इस मामले में एक int) और एक अधिक जटिल डेटा प्रकार (इस मामले में एक स्ट्रिंग) होना चाहिए। सुनिश्चित करें कि यह मायने रखता है लेकिन आपके पास वहाँ है।)

SLF4J के लिए लॉग स्टेटमेंट:

logger.info("Logging {} and {} ", i, someString);

JUL का लॉग स्टेटमेंट:

logger.log(Level.INFO, "Logging {0} and {1}", new Object[]{i, someString});

जेवीएम को वास्तविक मापी से पहले एक बार निष्पादित एक ही परीक्षण के साथ 'वार्म अप' किया गया था। विंडोज 1.7 पर जावा 1.7.03 का उपयोग किया गया था। SLF4J (v1.6.6) और लॉगबैक (v1.0.6) के नवीनतम संस्करणों का उपयोग किया गया था। Stdout और Stderr को null डिवाइस पर रीडायरेक्ट किया गया था।

हालाँकि, अब सावधान, यह पता चलता है कि JUL अपना अधिकांश समय व्यतीत कर रहा है getSourceClassName()क्योंकि JUL डिफ़ॉल्ट रूप से आउटपुट में स्रोत वर्ग के नाम को प्रिंट करता है, जबकि Logback नहीं। इसलिए हम सेब और संतरे की तुलना कर रहे हैं। मुझे फिर से परीक्षण करना होगा और लॉगिंग कार्यान्वयन को समान तरीके से कॉन्फ़िगर करना होगा ताकि वे वास्तव में उसी सामान का उत्पादन करें। मुझे हालांकि इस बात पर संदेह है कि SLF4J + लॉगबैक अभी भी शीर्ष पर बाहर आएगा, लेकिन ऊपर दिए गए प्रारंभिक नंबरों से। बने रहें।

Btw: परीक्षण पहली बार मैं वास्तव में SLF4J या Logback के साथ काम किया है। एक सुखद अनुभव। जब आप शुरू कर रहे हों तो JUL निश्चित रूप से बहुत कम स्वागत योग्य है।

परीक्षण प्रदर्शन (भाग 2)

(08-जुलाई -2018 को nolan600 द्वारा जोड़ा गया अनुभाग)

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

java.util.logging.SimpleFormatter.format="%4$s: %5$s [%1$tc]%n"

और इससे उपरोक्त समय बिल्कुल भी नहीं बदला। मेरे प्रोफाइलर ने बताया कि लकड़हारा अभी भी कॉल में बहुत समय बिताता है, getSourceClassName()भले ही यह मेरे पैटर्न का हिस्सा न हो। पैटर्न कोई फर्क नहीं पड़ता।

इसलिए मैं प्रदर्शन के मुद्दे पर निष्कर्ष निकाल रहा हूं कि कम से कम परीक्षण किए गए टेम्पलेट आधारित लॉग स्टेटमेंट के लिए JUL (स्लो) और SLF4J + लॉगबैक (क्विक) के बीच वास्तविक प्रदर्शन अंतर में लगभग 10 का कारक लगता है। जैसे कैकेई ने कहा।

मैं एक और बात भी देख सकता हूं कि SLF4J की getLogger()कॉल JUL के डिट्टो की तुलना में बहुत अधिक महंगी है। (95 एमएस बनाम 0.3 एमएस अगर मेरा प्रोफाइल सही है)। यह समझ में आता है। SLF4J को अंतर्निहित लॉगिंग कार्यान्वयन के बंधन पर कुछ समय देना होगा। यह मुझे डराता नहीं है। ये कॉल किसी एप्लिकेशन के जीवनकाल में कुछ दुर्लभ होनी चाहिए। तेजी वास्तविक लॉग कॉल में होनी चाहिए।

अंतिम निष्कर्ष

(08-जुलाई -2018 को nolan600 द्वारा जोड़ा गया अनुभाग)

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

  1. यह तैनाती के समय लॉग कार्यान्वयन का चयन करने के लिए लचीलापन देता है।

  2. अनुप्रयोग सर्वर के अंदर चलने पर JUL के विन्यास के लचीलेपन की कमी के मुद्दे।

  3. SLF4J निश्चित रूप से बहुत तेजी से ऊपर विस्तृत रूप से विस्तृत है यदि आप इसे लॉगबैक के साथ जोड़ते हैं। यहां तक ​​कि अगर यह सिर्फ एक मोटा परीक्षण था, तो मुझे यह विश्वास करने का कारण है कि JUL की तुलना में SLF4J + लॉगबैक पर बहुत अधिक प्रयास अनुकूलन में चले गए हैं।

  4. प्रलेखन। SLF4J के लिए प्रलेखन बहुत अधिक व्यापक और सटीक है।

  5. पैटर्न लचीलापन। जैसा कि मैंने परीक्षण किया था कि मैंने JUL की लॉगबैक से डिफ़ॉल्ट पैटर्न की नकल की थी। इस पैटर्न में थ्रेड का नाम शामिल है। यह पता चला है कि JUL इस बॉक्स से बाहर नहीं कर सकता है। ठीक है, मैं इसे अब तक याद नहीं किया है, लेकिन मुझे नहीं लगता कि यह एक ऐसी चीज है जिसे लॉग फ्रेमवर्क से गायब होना चाहिए। अवधि!

  6. अधिकांश (या कई) जावा परियोजनाएं आज मावेन का उपयोग करती हैं, इसलिए एक निर्भरता जोड़ना बहुत बड़ी बात नहीं है, खासकर अगर वह निर्भरता स्थिर हो, यानी लगातार अपने एपीआई को नहीं बदलती है। यह SLF4J के लिए सही प्रतीत होता है। इसके अलावा SLF4J जार और दोस्त आकार में छोटे हैं।

तो अजीब बात यह है कि SLF4J के साथ थोड़ा काम करने के बाद मैं वास्तव में JUL से काफी परेशान हो गया था। मुझे अभी भी अफसोस है कि यह JUL के साथ इस तरह से होना चाहिए। JUL एकदम सही है, लेकिन इस तरह का काम करता है। बस बहुत अच्छी तरह से पर्याप्त नहीं है। Propertiesउदाहरण के बारे में भी यही कहा जा सकता है लेकिन हम अमूर्तता के बारे में नहीं सोचते हैं कि लोग अपने स्वयं के विन्यास पुस्तकालय में प्लग कर सकते हैं और आपके पास क्या है। मुझे लगता है कि इसका कारण Propertiesबार के ठीक ऊपर आता है जबकि विपरीत आज के JUL के लिए सही है ... और अतीत में यह शून्य पर आया था क्योंकि यह मौजूद नहीं था।


8
मैं एक समापन नहीं पूछूंगा, क्योंकि यह अच्छी तरह से प्रस्तुत प्रश्न दिलचस्प है, लेकिन अगर आप अक्सर पूछे जाने वाले प्रश्न को पढ़ते हैं तो यह सीमा रेखा है: यह एक निश्चित अद्वितीय जवाब खोजने के लिए कठिन होगा जो राय पर आधारित नहीं है।
डेग सैगुरेट

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

3
यह लोकप्रिय लॉगिंग फ्रेमवर्क (s) पूर्ववर्ती जूल के संदर्भ में सामान्य शब्द "लॉगिंग-फ्रेमवर्क-एक्स" का उपयोग करने के लिए भ्रामक है। आपको इस मामले में "log4j" का उपयोग करना चाहिए। अन्य लोकप्रिय चौखटे जैसे SLF4J और लॉगबैक जूल जारी होने के बाद अच्छी तरह से आ गए।
सेकी

1
@Acuariano। नेट्टी प्रोजेक्ट केवल क्लासपैथ पर लॉगिंग फ्रेमवर्क उपलब्ध है, यह परखने के लिए परावर्तन का उपयोग कर रहा है। स्रोत के लिए यहां देखें देख लो InternalLoggerFactory.java
peterh

1
@xenoterracide और भी महत्वपूर्ण जावा 9 के लिए एक अद्यतन होगा, क्योंकि यह पेश किया गया था java.lang.System.Logger, जो कि एक इंटरफ़ेस है , जिसे आप जो भी वास्तविक लॉगिंग फ्रेमवर्क चाहते हैं, उस तक रीडायरेक्ट किया जा सकता है, जब तक कि वह फ्रेमवर्क पकड़ा गया और उस इंटरफ़ेस का कार्यान्वयन प्रदान करता है। संशोधन के साथ संयुक्त, आप एक JRE युक्त बंडल के साथ एक आवेदन भी कर सकते हैं java.util.logging, अगर आप एक अलग रूपरेखा पसंद करते हैं।
होल्गर

जवाबों:


207

अस्वीकरण : मैं log4j, SLF4J और लॉगबैक परियोजनाओं का संस्थापक हूं।

SLF4J को प्राथमिकता देने के उद्देश्यपूर्ण कारण हैं। एक के लिए, SLF4J अंत-उपयोगकर्ता को अंतर्निहित लॉगिंग ढांचे को चुनने की स्वतंत्रता देता है । इसके अलावा, savvier उपयोगकर्ता लॉगबैक पसंद करते हैं, जो लॉग 4j से परे क्षमताओं की पेशकश करता है , जिसमें पीछे गिरने का रास्ता होता है। फ़ीचर-वार जूल कुछ उपयोगकर्ताओं के लिए पर्याप्त हो सकता है लेकिन कई अन्य लोगों के लिए यह बस नहीं है। संक्षेप में, यदि लॉगिंग आपके लिए महत्वपूर्ण है, तो आप अंतर्निहित कार्यान्वयन के रूप में लॉगबैक के साथ SLF4J का उपयोग करना चाहेंगे। यदि लॉगिंग महत्वहीन है, तो जूल ठीक है।

हालांकि, एक oss डेवलपर के रूप में, आपको अपने उपयोगकर्ताओं की प्राथमिकताओं को ध्यान में रखना होगा और न कि केवल अपने ही। यह इस प्रकार है कि आपको SLF4J को अपनाना चाहिए न कि इसलिए कि आप आश्वस्त हैं कि SLF4J जूल से बेहतर है लेकिन क्योंकि वर्तमान में अधिकांश जावा डेवलपर्स (जुलाई 2012) SLF4J को अपने लॉगिंग एपीआई के रूप में पसंद करते हैं। यदि अंततः आप लोकप्रिय राय की परवाह नहीं करने का निर्णय लेते हैं, तो निम्नलिखित तथ्यों पर विचार करें:

  1. जो लोग जूल पसंद करते हैं वे सुविधा से बाहर हो जाते हैं क्योंकि जद को JDK के साथ जोड़ दिया जाता है। मेरी जानकारी के अनुसार, जूल के पक्ष में कोई अन्य वस्तुनिष्ठ तर्क नहीं हैं
  2. जूल के लिए आपकी अपनी प्राथमिकता सिर्फ एक प्राथमिकता है

इस प्रकार, जनमानस के ऊपर "कठोर तथ्य" रखना, जबकि प्रतीत होता है कि बहादुर, इस मामले में एक तार्किक गिरावट है।

यदि अभी भी आश्वस्त नहीं हैं, तो जेबी निज़ेट एक अतिरिक्त और शक्तिशाली तर्क देता है:

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

यदि किसी भी कारण से आप SLF4J API से घृणा करते हैं और इसका उपयोग करने से आपके काम का मज़ा खत्म हो जाएगा, तो हर तरह से जूल के लिए जाएंआखिरकार, SLF4J में जूलरी रीडायरेक्ट करने के साधन हैं

वैसे, एसएलएफ 4 जे की तुलना में जुल पैराट्रिजेशन कम से कम 10 गुना धीमा है, जो ध्यान देने योग्य अंतर बनाता है।


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

2
क्या इस दावे के लिए कुछ समर्थन है कि अधिकांश जावा डेवलपर्स SLF4J को अपने लॉगिंग एपीआई के रूप में पसंद करते हैं?
ओलिवियर Cailloux

3
मेरी पोस्ट का सार यह है कि विभिन्न डेवलपर्स की अलग-अलग प्राथमिकताएं हैं जो विवाद से परे लगती हैं। हाँ?
सेकेई

1
ईमानदारी से, मैं जावा 11 (या जो कुछ भी समाप्त होता है) पर 2018 बेंचमार्क देखना पसंद करूंगा, और async मोड में log4j2 के खिलाफ।
xenoterracide

5
यहां मैं SLF4J का उपयोग कर रहा हूं, और मुझे अभी भी अन्य सभी लॉगिंग फ्रेमवर्क के साथ अन्य पुस्तकालयों का उपयोग करना है। SLF4J का उपयोग करने से विषम लॉगर्स की समस्या का समाधान नहीं होता है, यह सिर्फ इसे बदतर बनाता है। xkcd.com/927
चार्ली

34
  1. java.util.loggingजावा 1.4 में पेश किया गया था। इससे पहले लॉगिंग के लिए उपयोग किए गए थे, यही कारण है कि कई अन्य लॉगिंग एपीआई मौजूद हैं। उन एपीआई जहां जावा 1.4 से पहले भारी उपयोग किया गया था और इस तरह एक महान मार्केटशेयर था जो 1.4 रिलीज होने पर सिर्फ 0 पर नहीं गिरा था।

  2. JUL ने उन सभी महानों को शुरू नहीं किया, जिनमें से कई चीजें आपने बताईं, जहां 1.4 में बहुत बुरा है और केवल 1.5 में बेहतर हुआ (और मुझे 6 में भी अनुमान है, लेकिन मुझे यकीन नहीं है)।

  3. JUL एक ही JVM में विभिन्न कॉन्फ़िगरेशन के साथ कई अनुप्रयोगों के लिए अच्छी तरह से अनुकूल नहीं है (कई वेब एप्लिकेशन जो बातचीत नहीं करनी चाहिए सोचें)। टॉमकैट को उस कार्य को प्राप्त करने के लिए कुछ हुप्स के माध्यम से कूदने की जरूरत है (प्रभावी रूप से JUL को फिर से लागू करना अगर मुझे सही ढंग से समझ में आया)।

  4. आप हमेशा यह प्रभावित नहीं कर सकते कि आपके पुस्तकालयों में लॉगिंग फ्रेमवर्क का क्या उपयोग है। इसलिए SLF4J का उपयोग करना (जो वास्तव में अन्य पुस्तकालयों के ऊपर बहुत पतली एपीआई परत है) पूरे लॉगिंग दुनिया की कुछ हद तक सुसंगत तस्वीर रखने में मदद करता है (इसलिए आप एक ही सिस्टम में लाइब्रेरी लॉगिंग होने के दौरान अंतर्निहित लॉगिंग ढांचे को तय कर सकते हैं)।

  5. पुस्तकालय आसानी से नहीं बदल सकते हैं। यदि लाइब्रेरी के पिछले संस्करण का उपयोग लॉगिंग-लाइब्रेरी-एक्स का उपयोग करने के लिए किया जाता है, तो यह लॉगिंग-लाइब्रेरी-वाई (उदाहरण के लिए JUL) पर आसानी से स्विच नहीं कर सकता है, भले ही उत्तरार्द्ध स्पष्ट रूप से सुपरियस हो: उस लाइब्रेरी के किसी भी उपयोगकर्ता को सीखने की आवश्यकता होगी नए लॉगिंग ढांचे और (कम से कम) उनके लॉगिंग को फिर से कॉन्फ़िगर करें। यह एक बड़ा नहीं-नहीं है, खासकर जब यह ज्यादातर लोगों के लिए कोई स्पष्ट लाभ नहीं लाता है।

सभी ने कहा कि मुझे लगता है कि JUL इन दिनों अन्य लॉगिंग फ्रेमवर्क के लिए कम से कम एक वैध विकल्प है।


1
धन्यवाद जोआचिम, मैं आपके पोस्ट की सराहना करता हूं। आपका (1) और (2) मेरे लिए सिर्फ इतिहास हैं। बहुत समय पहले। आपका (4) उसी का परिणाम है और फिर मैं एक चक्रीय तर्क कहता हूं। आपका (3) हालांकि वास्तव में दिलचस्प है। शायद आप किसी चीज़ पर हैं? लेकिन यह केवल उन लोगों को प्रभावित करेगा जो आवेदन कंटेनरों का निर्माण कर रहे हैं जो दिन के अंत में बहुत कम लोग हैं। और क्या?
पीटर जू

3
खैर, जो इतिहास को अनदेखा करता है, उसे दोहराने के लिए बर्बाद किया जाता है ;-) सॉफ्टवेयर विकास में इतिहास बहुत प्रासंगिक है। लोग बहुत तेजी से आगे नहीं बढ़ते हैं और मौजूदा API वाले मौजूदा तृतीय-पक्ष पुस्तकालयों को प्रतिस्थापित करना केवल तभी अच्छा काम करता है जब मानक API कम से कम तीसरे पक्ष के पुस्तकालयों के रूप में अच्छा काम करते हैं। और वे शुरू में नहीं थे (और यकीनन अभी भी कुछ मामलों में नहीं है)।
जोकिम सॉर

जोआचिम, मुझे उन लोगों में दिलचस्पी है "यकीनन अभी भी कुछ मामलों में नहीं है" जिसका आप उल्लेख करते हैं। यही कारण है कि मांस हो गया है। अपने मौजूदा कोड में एक लकड़हारा पुस्तकालय को बदलना बहुत तुच्छ है और इन दिनों स्वचालित किया जा सकता है। SLF4J के पास इसके लिए एक उपकरण है जो मेरी बात को साबित करता है। इसलिए मुझे लगता है कि log4j के साथ 2002 में लिखे गए एक विशाल पुस्तकालय को एक स्वचालित उपकरण के साथ मिनटों के मामले में JUL में परिवर्तित किया जा सकता है। (मुझे नहीं पता कि क्या मौजूद है, हालांकि)। तो ऐसा क्यों नहीं होता है?
पीटर जू

3
@ nolan6000: मैं उस वाक्यांश के बारे में विवरण में जाने के लिए बारीकियों के बारे में पर्याप्त नहीं जानता हूं, और यह वास्तव में वह बिंदु नहीं है जो मैं बना रहा हूं। भले ही JUL अब थर्ड-पार्टी फ्रेमवर्क के साथ है, जड़ता और मौजूदा बुनियादी ढांचा अभी भी स्विच नहीं करने का एक मजबूत कारण है। उदाहरण के लिए अगर लाइब्रेरी X ने संस्करण 1.1 में slf4j का उपयोग किया है, तो 1.2 (या यहां तक ​​कि 2.0) में JUL पर स्विच करना कई उपयोगकर्ताओं के लिए एक बड़ी समस्या होगी (जो पहले से ही पुरानी प्रणाली को सही ढंग से कॉन्फ़िगर करते हैं और बिना किसी स्पष्ट लाभ के फिर से करना होगा) ।
जोकिम सॉर

@ nolan6000 यहां तक ​​कि अगर आप इतिहास की परवाह नहीं करते हैं, तो आपके द्वारा अपने अनुप्रयोगों में उपयोग किए जाने वाले पुस्तकालय सबसे निश्चित रूप से करते हैं। लाइब्रेरी को त्यागने में कोई मज़ा नहीं है क्योंकि यह आपके मुकाबले एक अलग लॉगिंग फ्रेमवर्क का उपयोग करता है।
Thorbjørn रावन एंडरसन

29

IMHO, slf4j की तरह एक लॉगिंग मुखौटा का उपयोग करने में मुख्य लाभ यह है कि आप लाइब्रेरी के अंत-उपयोगकर्ता को यह चुनने दें कि वह कौन सा ठोस लॉगिंग कार्यान्वयन चाहता है, बजाय अपनी पसंद के अंतिम उपयोगकर्ता को थोपने के।

हो सकता है कि उसने जूल को कॉन्फ़िगर करने के बजाय Log4j या LogBack (विशेष फॉर्मेटर्स, एपेंडर्स आदि) में समय और पैसा लगाया हो और Log4j या LogBack का उपयोग जारी रखना पसंद करता हो। कोई समस्या नहीं: slf4j कि अनुमति देता है। क्या जूल के ऊपर Log4j का उपयोग करना एक समझदारी भरा विकल्प है? शायद शायद नहीं। लेकिन आप परवाह नहीं करते। अंतिम उपयोगकर्ता को चुनें कि वह क्या पसंद करता है।


धन्यवाद जेबी मेरा सवाल यह है कि क्या मैं वास्तव में उस पर JUL को मजबूर करके अपनी लाइब्रेरी के उपयोगकर्ता / कार्यान्वयनकर्ता पर बहुत अधिक प्रभाव डाल रहा हूं? यदि वह उदाहरण के लिए JUL के मानक आउटपुट हैंडलर से नाखुश है, तो वह उन्हें तैनाती के समय स्वयं के लिए स्वैप कर सकता है जैसा कि मैं देख रहा हूं। मैं वास्तव में JUL को स्ट्रेटजैकेट के रूप में नहीं देखता। ऐसा लगता है कि यह बाकी की तरह लचीला और विस्तारित है।
पेट्र

12
अंतिम उपयोगकर्ता को छोड़कर यह अनुकूलन पहले से ही अपने कोड के लिए किया जा सकता है, या एक अन्य पुस्तकालय जो लॉग 4 जे या लॉगबैक का उपयोग करता है। jul एक्स्टेंसिबल है, लेकिन LogBack, jul, log4j और भगवान का विस्तार करने के लिए केवल अन्य लॉगिंग फ्रेमवर्क को जानता है क्योंकि वह 4 पुस्तकालयों का उपयोग करता है जो 4 अलग लॉगिंग फ़्रेमवर्क का उपयोग करता है जो बोझिल है। Slf4j का उपयोग करके, आप उसे लॉगिंग फ्रेमवर्क को कॉन्फ़िगर करने की अनुमति देते हैं जो वह चाहता है। वह नहीं जिसे आपने चुना है। याद रखें कि विशिष्ट परियोजनाएं पुस्तकालयों के असंख्य उपयोग करती हैं, और न केवल आपकी।
जेबी निज़ेट

6

मैंने शुरू किया, जैसे आप मुझे संदेह है, JUL का उपयोग कर क्योंकि यह तुरंत जाने के लिए सबसे आसान था। इन वर्षों में, मैं चाहता हूं कि मैं कुछ और समय चुनकर आया हूं।

मेरा मुख्य मुद्दा अब यह है कि हमारे पास पर्याप्त मात्रा में 'लाइब्रेरी' कोड है जो कई अनुप्रयोगों में उपयोग किया जाता है और वे सभी JUL का उपयोग करते हैं। जब भी मैं एक वेब-सेवा प्रकार ऐप में इन उपकरणों का उपयोग करता हूं तो लॉगिंग गायब हो जाती है या कहीं अप्रत्याशित या अजीब हो जाती है।

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

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

हमने मुखौटा बनाने के लिए slf4j का उपयोग किया।


1
किसी भी कारण से आपने slf4j वितरण में सिर्फ "redirect java.util.log to slf4j" पैकेज का उपयोग नहीं किया?
थोरबजोरन रावन एंडरसन

2
हमने किया, लेकिन कम मूल्य पर क्योंकि slf4j पर जाने का प्राथमिक लाभ कुशल पैरामीटराइज़्ड लॉगिंग है। अगर हम इसका इस्तेमाल करते हैं तो शुरू से ही हमारे पास अब ऐसा करने के लिए कोई काम नहीं होगा।
ओल्डकुरमुडीगन

1
मैं मानता हूं कि यह slf4j का कम लटका हुआ फल है।
थोरबजोरन रावन एंडरसन

3

मैं logf-1.1.7 पर slf4j-1.7.21 के खिलाफ दौड़ गया, एक SSD, जावा 1.8, Win64 को आउटपुट

जूल 48449 एमएस, लॉगबैक 27185 एमएस 1 एम लूप के लिए चला।

फिर भी, थोड़ी अधिक गति और थोड़ा अच्छा एपीआई मेरे लिए 3 पुस्तकालयों और 800K के लायक नहीं है।

package log;

import java.util.logging.Level;
import java.util.logging.Logger;

public class LogJUL
{
    final static Logger logger = Logger.getLogger(LogJUL.class.getSimpleName());

    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            Object[] o = { lc };

            logger.log(Level.INFO,"Epoch time {0}", o);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }
}

तथा

package log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogSLF
{
    static Logger logger = LoggerFactory.getLogger(LogSLF.class);


    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            logger.info("Epoch time {}", lc);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }

}

3
आप की तरह के लिए तुलना नहीं कर रहे हैं। आप स्पष्ट रूप से जूल के लिए एक सरणी क्यों बना रहे हैं? मुझे लगता है कि यह है क्योंकि slf4j में एक-तर्क के अधिभार का अभाव है logger.info()। इसलिए आप जानबूझकर slf4j के इंटरफेस में कमी की भरपाई करने के लिए जूल प्रदर्शन को अपंग कर रहे हैं। आपको इसके बजाय दोनों तरीकों को कोड करना चाहिए जिस तरह से वे मुहावरेदार हैं।
क्लिटोस काइराकौ

2
आपने इसे गलत समझा। आपको अतिरिक्त 800K का उपयोग करने की आवश्यकता नहीं है। आम सहमति यह है कि बहुत पतली SLF4J एपि का उपयोग करने के लायक है क्योंकि तब आप (या अन्य जो शायद आपके कोड का पुनः उपयोग करते हैं!) JUL, लॉगबैक, Log4j आदि के बीच स्वतंत्र रूप से स्विच कर सकते हैं SLF4J केवल ~ 28K है। SLF4J से JUL पुल (slf4j-jdk ... जार) केवल ~ 9K है।
जोखिम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.