Log4j, एक रिश्तेदार पथ का उपयोग करने के लिए एक वेब ऐप को कॉन्फ़िगर करना


80

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

ऐसा करने का सबसे अच्छा तरीका क्या है?


3
यह वास्तव में केवल आधा प्रश्न है। लॉग फ़ाइल के लिए एक डायनेमिक पथ होना बहुत अच्छा है, लेकिन कॉन्‍फ़िगर फ़ाइल के बारे में क्‍या है। यदि यह सिर्फ लॉग फ़ाइल स्थान है जो गतिशील है तो आपके पास सभी जगहों पर समान लॉग स्तर होंगे जो इसे तैनात किया गया है, और मुझे नहीं लगता कि यह वांछनीय है। मैं डायनामिक रूप से निर्दिष्ट करने के लिए सबसे अच्छा तरीका जानना चाहूंगा ताकि मेरे देव वातावरण DEBUG पर लॉग इन कर सके और INFO / WARN पर ठेस पहुंच सके। तुम क्या सोचते हो?
लुकास

जवाबों:


100

टॉमकैट एक कैटिना.होम सिस्टम गुण सेट करता है। आप अपने log4j गुण फ़ाइल में इसका उपयोग कर सकते हैं। कुछ इस तरह:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log

डेबियन पर (उबंटू सहित), ${catalina.home}काम नहीं करेगा क्योंकि उस बिंदु पर / usr / share / tomcat6 जिसका कोई लिंक / var / log / tomcat6 नहीं है। यहाँ सिर्फ उपयोग करें ${catalina.base}

यदि आपका अन्य कंटेनर का उपयोग कर रहा है, तो समान सिस्टम प्रॉपर्टी खोजने का प्रयास करें, या अपना स्वयं का परिभाषित करें। सिस्टम प्रॉपर्टी सेट करना प्लेटफ़ॉर्म और कंटेनर द्वारा अलग-अलग होगा। लेकिन लिनक्स / यूनिक्स पर टॉमकैट के लिए मैं CATALINA_HOME / बिन निर्देशिका में एक setenv.sh बनाऊंगा। इसमें शामिल होगा:

export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"

तब आपका log4j.properties होगा:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log

2
मैं ईमानदारी से यह नहीं देखता कि मेरे उत्तर में बताए गए श्रोता का उपयोग करने से इस दृष्टिकोण का क्या फायदा है। मुझे परवाह नहीं है कि यह कंटेनर क्या है, यह सिर्फ किसी भी मामले में काम नहीं करेगा जहां मैं इसे तैनात करता हूं जबकि आपके दृष्टिकोण में मुझे करना है यदि मैं पर्यावरण बदलता हूं तो एक मूल्य बदलें।
इकेर जिमेनेज़

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

54

मैंने आखिरकार इसे इस तरह से किया है।

एक ServletContextListener जोड़ा गया जो निम्नलिखित कार्य करता है:

public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    System.setProperty("rootPath", context.getRealPath("/"));
}

फिर log4j.properties फ़ाइल में:

log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log

इस तरह से करने से Log4j सही फ़ोल्डर में लिख देगा जब तक कि आप "rootPath" सिस्टम प्रॉपर्टी सेट होने से पहले इसका उपयोग नहीं करते हैं। इसका अर्थ है कि आप इसे सर्वलेटकोटेक्स्टलेनर से स्वयं उपयोग नहीं कर सकते हैं, लेकिन आपको इसे ऐप में कहीं और से भी उपयोग करने में सक्षम होना चाहिए।

इसे प्रत्येक वेब कंटेनर और OS पर काम करना चाहिए क्योंकि यह कंटेनर विशिष्ट सिस्टम गुण पर निर्भर नहीं है और यह OS विशिष्ट पथ समस्याओं से प्रभावित नहीं है। टॉमकैट और ओरियन वेब कंटेनर और विंडोज और लिनक्स पर परीक्षण किया गया और यह अब तक ठीक काम करता है।

तुम क्या सोचते हो?


4
यह एक अच्छा विचार है, लेकिन मुझे लगता है कि catalina.home का उपयोग करने के लिए सुरक्षित हो सकता है क्योंकि यह किसी भी log4j कोड को प्रारंभ करने से पहले हमेशा सेट / उपलब्ध रहेगा।
मैट बी

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

2
यह समाधान वेब अनुप्रयोगों के लिए काम कर सकता है जो सर्वलेट का उपयोग करते हैं, लेकिन स्टीव के समाधान ( stackoverflow.com/questions/216781/… ) Log4j का उपयोग करने वाले किसी भी अनुप्रयोग के लिए काम करता है।
डेरेक महार

2
स्पेंसर के का समाधान, सापेक्ष रास्तों के आधार पर भी, किसी भी अनुप्रयोग के लिए काम करता है जो लॉग 4j का उपयोग करता है, यह मानते हुए कि आप आधार निर्देशिका को एक अनुमानित पथ पर सेट करते हैं।
डेरेक महार

12
यह समाधान केवल तभी काम करता है जब आपके पास इसका उपयोग करने के लिए एक एकल WebApp कॉन्फ़िगर किया गया हो क्योंकि सिस्टम गुण एक दूसरे ऐप को शुरू करने के लिए वैश्विक हैं, पहला वेबैप सेट मान को अधिलेखित कर देगा। आप प्रत्येक webapp को एक विशिष्ट संपत्ति नाम दे सकते हैं लेकिन यदि आप ऐसा करने जा रहे हैं तो आप बस $ {catalina.home} का उपयोग कर सकते हैं और log4j.properties फ़ाइल में पथ का अद्वितीय भाग जोड़ सकते हैं क्योंकि यह कम त्रुटि वाला है। ।
3urdoch

14

यदि आप स्प्रिंग का उपयोग करते हैं तो आप कर सकते हैं:

1) एक log4j विन्यास फाइल बनाएं, जैसे "/WEB-INF/classes/log4j-myapp.properties" इसे "log4j.properties" नाम न दें।

उदाहरण:

log4j.rootLogger=ERROR, stdout, rollingFile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log
log4j.appender.rollingFile.MaxFileSize=512KB
log4j.appender.rollingFile.MaxBackupIndex=10
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.rollingFile.Encoding=UTF-8

हम "myWebapp-इंस्टेंस-रूट" को बाद में बिंदु (3) पर परिभाषित करेंगे

2) web.xml में विन्यास स्थान निर्दिष्ट करें:

<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>

3) अपने वेब के रूट के लिए एक अद्वितीय चर नाम निर्दिष्ट करें , जैसे "myWebapp-इंस्टेंस-रूट"

<context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>myWebapp-instance-root</param-value>
</context-param>

4) एक Log4jConfigListener जोड़ें:

<listener>
  <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

यदि आप एक अलग नाम चुनते हैं, तो इसे log4j-myapp.properties में भी बदलना याद रखें।

मेरा लेख देखें (केवल इतालवी ... लेकिन यह समझने योग्य होना चाहिए): http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring

अद्यतन (2009/08/01) मैंने अपना लेख अंग्रेजी में अनुवाद किया है: http://www.megadix.it/node/136


6

Iker के समाधान पर सिर्फ एक टिप्पणी ।

ServletContextआपकी समस्या का एक अच्छा समाधान है। लेकिन मुझे नहीं लगता कि यह रखरखाव के लिए अच्छा है। अधिकांश समय लॉग फ़ाइलों को लंबे समय तक सहेजने की आवश्यकता होती है।

चूंकि ServletContextफ़ाइल को परिनियोजित फ़ाइल के तहत बनाया जाता है, इसलिए सर्वर के पुन: उपयोग किए जाने पर इसे हटा दिया जाएगा। मेरा सुझाव है कि बच्चे के बजाय रूटपैथ के मूल फ़ोल्डर के साथ जाएं।


5

यदि आप अपने FileAppender की पथ संपत्ति में रूट निर्देशिका निर्दिष्ट नहीं करते हैं, तो क्या log4j केवल एप्लिकेशन रूट निर्देशिका का उपयोग नहीं करता है? तो आप का उपयोग करने में सक्षम होना चाहिए:

log4j.appender.file.File = लॉग / MyLog.log

जब से मैंने जावा वेब डेवलपमेंट किया है, तब से थोड़ी देर हो गई है, लेकिन यह सबसे सहज प्रतीत होता है, और यह अन्य दुर्भाग्य से नामांकित लॉग के साथ $ {catalina.home} / लॉग्स निर्देशिका में लिखने से भी नहीं टकराता है।


4
अगर मैंने देखा है कि यह उपयोगकर्ता के होम डायरेक्टरी, या कंटेनर के होम डायरेक्टरी का उपयोग कर सकता है यदि आप एक निरपेक्ष पथ नहीं देते हैं। अविश्वसनीय।
इकेर जिमेनेज़

1
@Iker: आप अपने कंटेनर या एप्लिकेशन कॉन्फ़िगरेशन में एप्लिकेशन रूट निर्देशिका को स्पष्ट रूप से सेट क्यों नहीं कर सकते? एक बार जब आप विकास और उत्पादन में एक बार कर लेते हैं, तो आप सापेक्ष रास्तों का मज़बूती से उपयोग कर सकते हैं। मान लें कि रूट डायरेक्टरी को सही तरीके से सेट किया गया है, सापेक्ष पथ सबसे पोर्टेबल (री-लोकेबल) समाधान हैं।
डेरेक महार

1
मुझे पता है कि यह एक पुरानी पोस्ट है लेकिन मैं दूसरों के लिए इस पर एक नोट बनाना चाहता था। टॉमकैट के लिए यदि एप्लिकेशन रूट डायरेक्टरी स्पष्ट रूप से सेट नहीं है, तो मेरा मानना ​​है कि जिस भी निर्देशिका से आपने टॉमकैट शुरू किया है, उसके लिए यह चूक है।
गेरियन व्हाइट

2

Https://stackoverflow.com/a/218037/2279200 पर एक और टिप्पणी के रूप में - यह टूट सकता है, यदि वेब ऐप अन्य सर्विसलेटकोटेक्स्टलेनर की शुरुआत करता है, जिसे पहले बुलाया जा सकता है और जो पहले से ही 4j का उपयोग करने की कोशिश करता है - इस मामले में, log4j कॉन्फ़िगरेशन को पढ़ा जाएगा और पहले से ही लॉग रूट निर्देशिका निर्धारित संपत्ति से पहले पार्स किया गया है => लॉग फाइलें वर्तमान निर्देशिका (टॉमकैट शुरू करते समय वर्तमान निर्देशिका) के नीचे कहीं दिखाई देंगी।

मैं केवल इस समस्या के समाधान के बारे में सोच सकता था: - अपनी log4j.properties (या logj4.xml) फ़ाइल का नाम कुछ ऐसी चीज़ों पर रख दें, जो log4j स्वचालित रूप से नहीं पढ़ेगी। - आपके संदर्भ फ़िल्टर में, संपत्ति सेट करने के बाद, DOM / PropertyConfigurator हेल्पर क्लास को कॉल करें ताकि यह सुनिश्चित किया जा सके कि आपका log4j - {xml, properties} पढ़ा गया है - log4j कॉन्फ़िगरेशन को रीसेट करें (IIRC ऐसा करने का एक तरीका है)

यह थोड़ा क्रूर बल है, लेकिन यह इसे वॉटरटाइट बनाने का एकमात्र तरीका है।


1

यदि आप मावेन का उपयोग कर रहे हैं तो मेरे पास आपके लिए एक बढ़िया उपाय है:

  1. निम्नलिखित पंक्तियों को शामिल करने के लिए अपनी pom.xml फ़ाइल संपादित करें:

    <profiles>
        <profile>
            <id>linux</id>
            <activation>
                <os>
                    <family>unix</family>
                </os>
            </activation>
            <properties>
                <logDirectory>/var/log/tomcat6</logDirectory>
            </properties>
        </profile>
        <profile>
            <id>windows</id>
            <activation>
                <os>
                    <family>windows</family>
                </os>
            </activation>
            <properties>
                <logDirectory>${catalina.home}/logs</logDirectory>
            </properties>
        </profile>
    </profiles>
    

    यहाँ आप परिभाषित करते हैं logDirectory विशेष रूप से ओएस परिवार के लिए संपत्ति हैं।

  2. फ़ाइल logDirectoryमें पहले से परिभाषित संपत्ति का उपयोग करें log4j.properties:

    log4j.appender.FILE=org.apache.log4j.RollingFileAppender
    log4j.appender.FILE.File=${logDirectory}/mylog.log
    log4j.appender.FILE.MaxFileSize=30MB
    log4j.appender.FILE.MaxBackupIndex=10
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n
    
  3. बस!

पुनश्च: मुझे यकीन है कि यह चींटी का उपयोग करके प्राप्त किया जा सकता है लेकिन दुर्भाग्य से मेरे पास इसके साथ पर्याप्त अनुभव नहीं है।


1

मेरा सुझाव है कि लॉग फ़ाइल को हमेशा webApp के मूल संदर्भ के ऊपर लॉग इन किया जाना चाहिए, इसलिए यदि हम webApp को फिर से तैयार करते हैं, तो हम मौजूदा लॉग फ़ाइलों को ओवरराइड नहीं करना चाहते हैं।


1

मेरा समाधान इकर जिमेन्ज़ के समाधान के समान है , लेकिन इसके बजाय System.setProperty(...)मैं उपयोग करता हूं org.apache.log4j.PropertyConfigurator.configure(Properties)। उसके लिए मुझे अपने स्वयं के कॉन्फ़िगरेशन को खोजने में असमर्थ होने के लिए लॉग 4 जे की भी आवश्यकता है और मैं इसे मैन्युअल रूप से लोड करता हूं (दोनों बिंदु वुल्फगैंग लिबिक के उत्तर में वर्णित हैं )।

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

विवरण:

  1. मेरे पास log4j-no-autoload.propertiesक्लासपाथ में फ़ाइल में मेरे गुण हैं (जैसे मेरे मावेन प्रोजेक्ट में यह मूल रूप से है src/main/resources, इसमें पैक हो जाता है WEB-INF/classes)
  2. इसमें फ़ाइल परिशिष्ट को कॉन्फ़िगर किया गया है जैसे:

    log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender
    log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
    ...
    
  3. और मेरे पास इस तरह का एक संदर्भ श्रोता है (जावा 7 के "ट्राय-विथ-रिसोर्स" सिंटैक्स के साथ बहुत कम मिलता है):

    @WebListener
    public class ContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(final ServletContextEvent event) {
            Properties props = new Properties();
            InputStream strm =
                ContextListener.class.getClassLoader()
                    .getResourceAsStream("log4j-no-autoload.properties");
            try {
                props.load(strm);
            } catch (IOException propsLoadIOE) {
                throw new Error("can't load logging config file", propsLoadIOE);
            } finally {
                try {
                    strm.close();
                } catch (IOException configCloseIOE) {
                    throw new Error("error closing logging config file", configCloseIOE);
                }
            }
            props.put("webAppRoot", event.getServletContext().getRealPath("/"));
            PropertyConfigurator.configure(props);
            // from now on, I can use LoggerFactory.getLogger(...)
        }
        ...
    }
    

1

आप कार्य निर्देशिका का उपयोग करके लॉग फ़ाइल के सापेक्ष पथ निर्दिष्ट कर सकते हैं :

appender.file.fileName = ${sys:user.dir}/log/application.log

यह सर्वलेट कंटेनर से स्वतंत्र है और सिस्टम वातावरण में कस्टम चर को पारित करने की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.