2011-12-13 17 views
5

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

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

library = new library(Logger applicationsVeryOwnLogger); 

और फिर कि लकड़हारा का उपयोग करें, पुस्तकालय में सभी बयानों लॉग इन करने की:

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

क्या ऐसा करने के बेहतर तरीके हैं?

उत्तर

2

हमें हमारे पुराने अनुप्रयोगों में से एक में समान आवश्यकता थी। जिस समाधान के साथ हम आए थे वह एक संसाधन प्रबंधक था जो संसाधन (लॉगर, कॉन्फ़िगरेशन इत्यादि) को (संदर्भ) क्लासलोडर द्वारा पुनर्प्राप्त करेगा।

आमतौर पर ईएआर के रूप में तैनात हर एप्लिकेशन को अपना स्वयं का क्लासलोडर मिलता है और लाइब्रेरी केवल मौजूदा थ्रेड/एप्लिकेशन से जुड़े लॉगर को प्राप्त करने के लिए ResourceManager.getLogger() को कॉल कर सकती है। इस तरह आपको लाइब्रेरी में प्रत्येक विधि कॉल के साथ इसे पास करने की आवश्यकता नहीं है (इसके लिए आवश्यक है कि आप लाइब्रेरी को बदल सकें)।

Logger logger = Logger.getLogger([Application Logger Name]); 
ResourceManager.registerLogger(logger); 

पुस्तकालय में लॉगर पुनः प्राप्त (उपयोगिता विधि):

private Logger getLogger() 
    { 
     return ResourceManager.getLogger();  
    } 

import java.util.*; 
import java.util.logging.*; 

public class ResourceManager 
{ 
    private static final Map<ClassLoader, Map<String, Object>> resources = 
     Collections.synchronizedMap(new WeakHashMap<ClassLoader, Map<String, Object>>()); 
    public static final String LOGGER = Logger.class.getName(); 

    static 
    { 
     // adjust for log4j or other frameworks 
     final Logger logger = Logger.getLogger("logging.default"); 
     logger.setLevel(Level.ALL); 
     logger.addHandler(new ConsoleHandler() 
     { 
      { 
       setOutputStream(System.out); 
       setLevel(Level.ALL); 
      } 
     }); 
     registerResource(null, LOGGER, logger); 
    } 

    private static ClassLoader getApplicationScope() 
    { 
     return Thread.currentThread().getContextClassLoader(); 
    } 

    public static void registerResource(final String name, final Object resource) 
    { 
     registerResource(getApplicationScope(), name, resource); 
    } 

    public static synchronized void registerResource(final ClassLoader scope, final String name, final Object resource) 
    { 
     Map<String, Object> hm = null; 
     hm = resources.get(scope); 
     if (hm == null) 
     { 
      hm = Collections.synchronizedMap(new HashMap<String, Object>()); 
      resources.put(scope, hm); 
     } 
     hm.put(name, resource); 
    } 

    public static Object getResource(final String name) 
    { 
     for(ClassLoader scope = getApplicationScope();;scope = scope.getParent()) 
     { 
      final Map<String, Object> hm = resources.get(scope); 
      if ((hm != null) && hm.containsKey(name)) 
      { 
       return hm.get(name); 
      } 
      if (scope == null) break; 
     } 
     return null; 
    } 

    public static void registerLogger(final Logger logger) 
    { 
     registerResource(LOGGER, logger); 
    } 

    public static Logger getLogger() 
    { 
     return (Logger)getResource(LOGGER); 
    }  
} 

रजिस्टर EJB/WebApp की init चरण में लॉगर (getLogger के लिए किसी भी कॉल करने से पहले पंजीकृत होना आवश्यक है)

यह वर्तमान थ्रेड से जुड़े एप्लिकेशन (ईएआर) के लिए लॉगर वापस करेगा।

लॉगर्स तक सीमित नहीं है यह अन्य संसाधनों के लिए भी काम करता है जिन्हें आप साझा करना चाहते हैं।

सीमाएं:

  • अभ्यस्त काम अगर आप तैनात EAR

  • संसाधनप्रबंधक और लॉगिंग पुस्तकालय प्रति एक से अधिक आवेदन/EJBs पैकेज एक ही या पुस्तकालय और आवेदन की तुलना में अधिक classloader पर होने की जरूरत है। यदि बंडल करने का कोई विकल्प है तो अलेक्जेंडर्स दृष्टिकोण क्लीनर है। (हम java.util.logging का उपयोग करते हैं जो सर्वर स्तर पर डिफ़ॉल्ट रूप से होता है, इसलिए उसका दृष्टिकोण काम नहीं करता है)

+0

एक साइड नोट के रूप में इस समाधान का उपयोग सभी प्रकार के संसाधनों को साझा करने के लिए भी किया जा सकता है, न केवल लॉगर्स। – Stefan

+0

यदि भविष्य में लिंक मर जाता है, तो आप अपने उत्तर में कोड के प्रासंगिक अनुभाग पेस्ट करना चाहेंगे। – rouble

+0

इस विधि के बारे में ध्यान देने योग्य एक अन्य बात यह है कि लाइब्रेरी तत्काल होने से पहले ResourceManager.registerLogger() को कॉल किया जाना चाहिए। अन्यथा, क्लास लॉगर्स डिफ़ॉल्ट लॉगर का उपयोग करके सेट किए जाएंगे। यह कुछ कार्यान्वयन के लिए एक सौदा ब्रेकर हो सकता है। – rouble

3

आपने log4j टैग के साथ अपना प्रश्न चिह्नित किया है, इसलिए मुझे लगता है कि आप इसका उपयोग कर रहे हैं।

मुझे आशा है कि आपकी लाइब्रेरी एक अद्वितीय पैकेज नाम का उपयोग कर रही है।

यदि ऐसा है, तो आप वास्तव में उस पैकेज के लिए केवल लॉगजर सेट कर सकते हैं।

log4j.category.my.lib.package = INFO, libFileAppender 
log4j.rootLogger = INFO, rootFileAppender 

ऐसा करने से दोनों libFileAppender और rootFileAppender लिए अपनी लाइब्रेरी से संदेशों प्रवेश करेंगे।

आप rootFileAppender में प्रदर्शित करने के लिए अपनी लाइब्रेरी से संदेशों के लिए नहीं करना चाहते, तो आप, कि लकड़हारा additivity बंद कर सकते हैं इस तरह:

log4j.category.my.lib.package = INFO, libFileAppender 
log4j.additivity.my.lib.package = false 
log4j.rootLogger = INFO, rootFileAppender 
इस के साथ

, आप केवल संदेश libFileAppender में देखेंगे

+0

मुझे नहीं लगता कि यह आवश्यकताओं को पूरा करता है। इसके साथ पुस्तकालय से प्रत्येक लॉग को एक ही स्थान पर रीडायरेक्ट किया जा सकता है। हालांकि, हमें पुस्तकालय से प्रत्येक लॉग की आवश्यकता है जो एक विशिष्ट एप्लिकेशन द्वारा एक स्थान पर जाने के लिए उत्पन्न होता है (जो एप्लिकेशन की लॉग फ़ाइल है)। – rouble

+0

@prmatta। इस फ़ाइल को वेब-आईएनएफ/कक्षाओं और सेटअप एपेंडर में फेंक दें जो उस एप्लिकेशन के लिए विशिष्ट है और प्रत्येक एप्लिकेशन उस ऐपेंडर को लाइब्रेरी कॉल लॉग करेगा। मैं नहीं देखता कि यह आपकी आवश्यकताओं को पूरा नहीं करता है। –

+0

लॉग 4j के लिए लॉगर्स/परिशिष्ट को JVM स्तर पर प्रबंधित किया गया है? और यदि आप सभी लॉगर्स के लिए समान नाम का उपयोग करते हैं (जो आपको करना है क्योंकि लाइब्रेरी को नाम की आवश्यकता है) तो आप एक ही लॉगर को पंजीकृत करते रहेंगे। – Stefan

संबंधित मुद्दे