2011-04-18 17 views
54

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

public static void main(final String... args) throws Exception { 

    LOGGER.info("program started"); 
    try { 
     // try body codes 
    } catch (Exception ex) { 
     LOGGER.info("program start-up failed.",ex); 
    } 
} 

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

+0

यह कॉन्फ़िगरेशन समस्या या प्रारंभिक समस्या हो सकती है। आप लॉगर को कहां प्रारंभ करते हैं? क्या आप दो बार Logger.getLogger (SomeClass.class) को कॉल नहीं करते हैं? कुछ अतिरिक्त कोड हमें आपकी सहायता करने के लिए अधिक जानकारी दे सकते हैं। – MaSEL

उत्तर

75

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

इसे आपके लॉगर पर additivity सेट करके हल किया जा सकता है। Log4j manual परिशिष्ट और लेआउट अनुभाग में additivity का उल्लेख करता है। जांचें कि

+2

क्या यह आपको * इसे हल करना चाहिए, या एक बैंड-सहायता एक बड़ी कॉन्फ़िगरेशन समस्या मास्किंग करना है? –

+1

लॉगर के बिना, कुछ भी लॉग नहीं है। जब मैं लॉगर को वापस जोड़ता हूं, तो यह दो बार लॉग होता है। जब मैं झूठी बातों को जोड़ता हूं, तो यह एक बार लॉग होता है। यहाँ क्या चल रहा है? –

+0

@DanielKaplan यदि आपके लॉगर्स में कुछ पदानुक्रमिक संरचना है, हां। मैन्युअल लिंक से पैराफ्रेशिंग, कहें कि आप केवल फू को छोड़कर सभी कक्षाओं के लिए त्रुटि संदेश चाहते हैं, जिन्हें आप सभी संदेशों को देखना चाहते हैं। आप फू लॉगर योजकता को गलत पर सेट करेंगे, इसलिए कोई भी ERROR संदेश रूट तक जारी नहीं रहता है और फिर मुद्रित नहीं होता है। Additivity के बिना, विन्यास रास्ता अधिक जटिल और कम रखरखाव होगा, तो मैं कहूंगा कि यह सही है। – whrrgarbl

29

अटलांटिस से सहमत हैं।

log4j.rootCategory=INFO, console 
log4j.logger.org.hibernate=INFO 

उपरोक्त संपत्ति सेटिंग्स डबल लॉगिंग का कारण बन जाएगी।

हालांकि

log4j.additivity.org.hibernate=false 

जोड़ने समस्या का समाधान हो।

इस पुस्तक के पृष्ठ 62 को देखें। http://books.google.com/books?id=hZBimlxiyAcC&printsec=frontcover#v=onepage&q&f=false

+6

यह 'गलत' नहीं होना चाहिए, न कि 'सत्य'? –

+0

Google पुस्तकें यादृच्छिक रूप से कुछ पृष्ठों को छिपाने लगती हैं। [यहां है] (http://veerasundar.com/blog/2009/08/log4j-tutorial-additivity-what-and-why/) एक ब्लॉग पोस्ट जो मुझे उपयोगी पाया गया। इसमें कुछ ** log4j.category ... ** प्रविष्टियों सहित एक और व्यापक उदाहरण शामिल है –

28

उन उपयोग XML स्वरूप के लिए:

<logger name="package.class" additivity="false"> 
    <level value="info" /> 
    <appender-ref ref="file" /> 
    <appender-ref ref="console" /> 
</logger> 

नोट: डिफ़ॉल्ट रूप से, संग्रह करने वालों को अपने additivity झंडा सही पर सेट किया है।

2

यदि आप जावा डीबगर के साथ प्रोग्राम चला सकते हैं, तो प्रोग्राम में ब्रेकपॉइंट डालें जहां इनमें से एक डबल लॉगिंग कॉल होती है।

डीबगर में लॉगर ऑब्जेक्ट की जांच करें। यदि यह एक org.apache.log4j.Logger (v 1.2.x) है तो उसके पास एक AppenderAttachableImpl हो सकता है। आप एपेंडर सूची के लिए AppenderAttachableImpl से पूछ सकते हैं।

यदि आपको 1 से अधिक एपेंडर मिलते हैं, तो यह समस्या हो सकती है - और इसे ठीक करने के लिए एक सुराग।

2

बस बस अपने कोड (Reference) को

logger.setadditivity(false); 

जोड़ें।

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

0

additivity संपत्ति को समायोजित करने का एक संभावित विकल्प आपके लॉगर्स को सबसे सामान्य से सबसे सामान्य से जांचना है। निम्नलिखित उदाहरण में, हम foo.bar.LoggingExampleClass में होने वाली किसी भी लॉग इवेंट के लिए कंसोल में डबल लॉगिंग देखने की अपेक्षा करेंगे। Foo.bar से अतिरिक्त कंसोल एपेंडर को निकालना सुरक्षित होगा।LoggingExampleClass लॉगर के रूप में यह पहले से ही रूट लॉगर द्वारा कवर किया गया है।

<Logger name="foo.bar.LoggingExampleClass" level="DEBUG"> 
    <AppenderRef ref="Console" /> <!-- THIS APPENDER COULD BE REMOVED --> 
    <AppenderRef ref="FooBarPackageLogging" /> 
</Logger> 

<Root level="WARN"> 
    <AppenderRef ref="Console" /> 
    <AppenderRef ref="MainLogFile" /> 
</Root> 

दोनों additivity समायोजन दृष्टिकोण और एपेंडर समायोजन दृष्टिकोण दोनों के लिए ट्रेडऑफ हैं। Additivity को बंद करना अनजाने में एक वांछनीय जेनेरिक स्तर लॉगर के एपेंडर को इस्तेमाल होने से रोक सकता है। उपर्युक्त उदाहरण में, foo.bar.LoggingExampleClass लॉगर पर additivity="false" प्रॉपर्टी को सेट करने का अर्थ यह होगा कि लॉगिंग ईवेंट रूट लॉगर में संदर्भित MainLogFile में जोड़ा नहीं जाएगा।

दूसरी तरफ, अभिभावक परिशिष्टों पर भरोसा करना समस्याग्रस्त हो सकता है यदि अभिभावक परिशिष्ट अधिक बारीक लॉगर्स पर प्रभाव की जांच किए बिना बदले जाते हैं। उदाहरण के लिए, मान लीजिए कि एक आवश्यकता है कि foo.bar.LoggingExampleClass लॉगिंग ईवेंट कंसोल पर लिखा जाना चाहिए। वे वर्तमान में additivity के कारण उपरोक्त उदाहरण कॉन्फ़िगरेशन में हैं, भले ही foo.bar.LoggingExampleClass लॉगर का कंसोल एपेंडर हटा दिया गया हो। हालांकि, अगर किसी भी अतिरिक्त समायोजन के बिना रूट लॉगर से कंसोल एपेंडर को भी हटा दिया गया था, तो आवश्यकता पूरी नहीं होगी।