डायनामिक रूप से लॉग 4j लॉग स्तर बदल रहा है


127

लॉग 4 जे लॉग स्तर को गतिशील रूप से बदलने के लिए अलग-अलग दृष्टिकोण क्या हैं, ताकि मुझे एप्लिकेशन को फिर से तैयार न करना पड़े। क्या उन मामलों में परिवर्तन स्थायी होगा?



बहुत से मिलते-जुलते stackoverflow.com/questions/2115900/...
vsingh

3
Log4j2 के लिए अद्यतित प्रश्न: stackoverflow.com/questions/23434252/…
slaadvak

1
ध्यान दें कि (लगभग) इस पृष्ठ पर सब कुछ log4j के बारे में है, log4j2 नहीं। यह पूरा पृष्ठ इतना भ्रम और भ्रम से भरा है कि यह USELESS है। @Slaadvak अनुशंसा के अनुसार stackoverflow.com/questions/23434252/… पर जाएं ।
लैम्बार्ट

जवाबों:


86

लॉग स्तर बदलना सरल है; कॉन्फ़िगरेशन के अन्य भागों को संशोधित करने से गहराई दृष्टिकोण में अधिक वृद्धि होगी।

LogManager.getRootLogger().setLevel(Level.DEBUG);

के जीवन काल के माध्यम से परिवर्तन स्थायी हैं Logger । पुनर्निमाणीकरण पर कॉन्फ़िगरेशन को पढ़ा जाएगा और रनटाइम पर स्तर सेट करने के रूप में उपयोग किया जाता है जो स्तर परिवर्तन को जारी नहीं रखता है।

अद्यतन: यदि आप लॉग 4j 2 का उपयोग कर रहे हैं, तो आपको प्रलेखन केsetLevel अनुसार कॉल को हटा देना चाहिए क्योंकि इसे कार्यान्वयन कक्षाओं के माध्यम से प्राप्त किया जा सकता है।

एपीआई में logger.setLevel () या इसी तरह के तरीकों का समर्थन नहीं किया जाता है। अनुप्रयोगों को इन्हें हटा देना चाहिए। Log4j 2 कार्यान्वयन कक्षाओं में समतुल्य कार्यक्षमता प्रदान की गई है, लेकिन Log4j 2 इंटर्नल्स में परिवर्तन के लिए अतिसंवेदनशील अनुप्रयोग को छोड़ सकता है।


5
केवल रनटाइम निर्भरता के लिएLogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC

8
ध्यान दें कि log4j 2 एपीआई एक "सेटलेवल" विधि प्रदान नहीं करता है।
क्रिसकैंटरेल

5
लेकिन यह केवल रूट लकड़हारा सेट करता है, है ना? यदि रूट के तहत लॉगर के लिए अलग-अलग स्तर निर्धारित किए गए हैं, तो रूट लॉगर सेट करने से उन लॉगजीआर पर कोई प्रभाव नहीं पड़ेगा। क्या हमें root.getLoggerRepository ()। GetCurrentCategories () की तरह कुछ करना होगा, लकड़हारे के प्रत्येक उदाहरण पर पुनरावृति और प्रत्येक लकड़हारे के लिए LEVEL सेट करें? @AaronMcIver
TheMonkWhoSoldHisCode

8
@ChrisCantrell Log4j 2 ऐसा करने का एक तरीका प्रदान करता है , हालाँकि यह उतना सरल नहीं है।
CorayThan

2
Log4j2 दिए गए अंतराल पर log4j2.xml फ़ाइल (या समतुल्य) को स्कैन करके इसके कॉन्फ़िगरेशन को ताज़ा करने के लिए कॉन्फ़िगर किया जा सकता है। जैसे <विन्यास स्थिति = "चेतावनी" मॉनिटरइंटरवल = "5" नाम = "tryItApp" संकुल = "">
किमबॉल रॉबिन्सन

89

फ़ाइल वॉचडॉग

Log4j log4j.xmlकॉन्फ़िगरेशन परिवर्तन के लिए फ़ाइल देखने में सक्षम है । यदि आप log4j फ़ाइल को बदलते हैं, तो log4j आपके परिवर्तनों के अनुसार लॉग स्तर को स्वचालित रूप से ताज़ा कर देगा। का प्रलेखन देखेंorg.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,longविवरण के लिए )। चेक के बीच डिफ़ॉल्ट प्रतीक्षा समय 60 सेकंड है। ये परिवर्तन लगातार बने रहेंगे, क्योंकि आप सीधे फाइल सिस्टम पर विन्यास फाइल बदलते हैं। आपको बस एक बार DOMConfigurator.configureAndWatch () को लागू करना है।

सावधानी: थ्रेड लीक के कारण J2EE वातावरण में उपयोग के लिए configAndWatch विधि असुरक्षित है

JMX

JMX का उपयोग करके लॉग स्तर (या सामान्य रूप से पुन: कॉन्फ़िगर करने) को सेट करने का दूसरा तरीका है। Log4j अपने लॉगर्स को JMX MBeans के रूप में पंजीकृत करता है। एप्लिकेशन सर्वर MBeanServer कंसोल (या JDK का jconsole.exe) का उपयोग करके आप प्रत्येक व्यक्तिगत लॉगर को पुन: कॉन्फ़िगर कर सकते हैं। ये परिवर्तन लगातार नहीं होते हैं और आपके एप्लिकेशन (सर्वर) को पुनरारंभ करने के बाद कॉन्फ़िगरेशन फ़ाइल में सेट किए गए कॉन्फ़िगरेशन पर रीसेट हो जाएंगे।

स्वनिर्मित

जैसा कि आरोन द्वारा वर्णित है, आप लॉग स्तर को प्रोग्रामेटिक रूप से सेट कर सकते हैं। आप इसे अपने आवेदन में उस तरह से लागू कर सकते हैं जिस तरह से आप ऐसा करना चाहते हैं। उदाहरण के लिए, आपके पास एक GUI हो सकता है जहां उपयोगकर्ता या व्यवस्थापक लॉग स्तर को बदलता है और फिर लकड़हारे को setLevel()विधियों को कॉल करता है । चाहे आप कहीं पर भी सेटिंग बनाए रखें या नहीं।


8
Log4j वॉचडॉग दृष्टिकोण के बारे में सावधानी का एक शब्द: "क्योंकि configAndWatch एक अलग वॉचडॉग थ्रेड को लॉन्च करता है, और क्योंकि लॉग 4j 1.2 में इस थ्रेड को रोकने का कोई तरीका नहीं है, कॉन्फ़िगर AAndWatch विधि J2EE एनवायरनमेंट्स में उपयोग के लिए असुरक्षित है जहां अनुप्रयोगों को पुनर्नवीनीकरण किया जाता है"। संदर्भ: लॉग 4 जे एफएक्यू
सोमू

अगर मैं Log4j की कॉन्फ़िगरएंडवाच कार्यक्षमता का उपयोग करता था तो मैं उस वॉचडॉग थ्रेड को एक EJB की @PostDestroy विधि में बंद कर सकता था (यह कंटेनर बंद होने पर एक अच्छा पर्याप्त संकेतक है)? या और भी बहुत कुछ है जो मुझे याद आ रहा है ..!
रॉबिन बजाज

क्षमा करें, मेरा मतलब है @PreDestroy विधि
रॉबिन बजाज

" Log4j JMX एमबीन्स के रूप में अपने लॉगर्स को पंजीकृत करता है। " मेरा सर्वलेट log4j 1.2 का उपयोग करता है। मुझे कोई log4j MBeans दिखाई नहीं देता है।
अब्दुल

आपको बस एक बार DOMConfigurator.configureAndWatch () को लागू करना है। इसे कैसे प्राप्त किया जा सकता है ?
gstackoverflow

5

Log4j2 दिए गए अंतराल पर log4j 2 .xml फ़ाइल (या समतुल्य) को स्कैन करके इसके कॉन्फ़िगरेशन को ताज़ा करने के लिए कॉन्फ़िगर किया जा सकता है । बस अपने कॉन्फ़िगरेशन टैग में " मॉनिटरइंटरवल " पैरामीटर जोड़ें । नमूना log4j 2 .xml फ़ाइल की लाइन 2 देखें , जो अंतिम लॉग ईवेंट के बाद से 5 सेकंड से अधिक बीतने पर अपने कॉन्फ़िगरेशन को फिर से स्कैन करने के लिए log4j को बताता है।

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="warn" monitorInterval="5" name="tryItApp" packages="">

    <Appenders>
        <RollingFile name="MY_TRY_IT"
                     fileName="/var/log/tryIt.log"
                     filePattern="/var/log/tryIt-%i.log.gz">
            <Policies>
                <SizeBasedTriggeringPolicy size="25 MB"/>
            </Policies>
            ...
        </RollingFile>
    </Appenders>


    <Loggers>
        <Root level="error">
            <AppenderRef ref="MY_TRY_IT"/>
        </Root>
    </Loggers>

</Configuration>

इस कार्य को करने के लिए अतिरिक्त चरण हैं यदि आप एक टमेक उदाहरण के लिए, एक आईडीई के अंदर, या वसंत बूट का उपयोग करते समय तैनात कर रहे हैं। यह कुछ हद तक यहाँ से बाहर लगता है और शायद एक अलग सवाल है।


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

नमस्ते, मैंने इसे Jboss6.4 पर परीक्षण किया और मैंने उस स्थान के अंदर (.war फ़ाइल के अंदर) लॉग 4j2 कॉन्फिग फ़ाइल को अपडेट किया, जहाँ ऐप फ़ाइल को देख सकता है। हालांकि यह अभी भी काम नहीं किया। कोई उपाय?
MidTierDeveloper

3

यह उत्तर आपको लॉगिंग स्तर को गतिशील रूप से बदलने में मदद नहीं करेगा, आपको सेवा को पुनरारंभ करने की आवश्यकता है, यदि आप सेवा को फिर से शुरू कर रहे हैं, तो कृपया नीचे दिए गए समाधान का उपयोग करें

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

इसे JVM पैरामीटर के रूप में पारित किया (मैं जावा 1.7 का उपयोग करता हूं)

क्षमा करें, यह गतिशील रूप से लॉगिंग स्तर को नहीं बदलेगा, इसके लिए सेवा को पुनः आरंभ करना होगा

java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java

log4j.properties फ़ाइल में, मैंने यह प्रविष्टि जोड़ी है

log4j.rootLogger=${logging.level},file,stdout

मैंने कोशिश की

 java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=INFO-cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=OFF -cp xxxxxx.jar  xxxxx.java

यह सब काम कर गया। उम्मीद है की यह मदद करेगा!

मेरे pom.xml में इन निम्नलिखित निर्भरताएं हैं

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>apache-log4j-extras</artifactId>
    <version>1.2.17</version>
</dependency>

2
आपने जो भी उल्लेख किया है वह ठीक लग रहा है, लेकिन सवाल गतिशील रूप से लॉगिंग स्तर को बदलने के बारे में है।
अजीम

ऐसा करने के लिए, आपको सेवा को पुनरारंभ करना होगा। यह लॉगिंग स्तरों को गतिशील रूप से नहीं बदलता है।
केके।

2

Log4j 1.x के साथ मुझे सबसे अच्छा तरीका यह लगता है कि एक DOMConfigurator का उपयोग XML लॉग कॉन्फ़िगरेशन के पूर्वनिर्धारित सेट (सामान्य उपयोग के लिए एक और डीबगिंग के लिए) प्रस्तुत करने के लिए किया जाए।

इनका उपयोग करना कुछ इस तरह से किया जा सकता है:

  public static void reconfigurePredefined(String newLoggerConfigName) {
    String name = newLoggerConfigName.toLowerCase();
    if ("default".equals(name)) {
      name = "log4j.xml";
    } else {
      name = "log4j-" + name + ".xml";
    }

    if (Log4jReconfigurator.class.getResource("/" + name) != null) {
      String logConfigPath = Log4jReconfigurator.class.getResource("/" + name).getPath();
      logger.warn("Using log4j configuration: " + logConfigPath);
      try (InputStream defaultIs = Log4jReconfigurator.class.getResourceAsStream("/" + name)) {
        new DOMConfigurator().doConfigure(defaultIs, LogManager.getLoggerRepository());
      } catch (IOException e) {
        logger.error("Failed to reconfigure log4j configuration, could not find file " + logConfigPath + " on the classpath", e);
      } catch (FactoryConfigurationError e) {
        logger.error("Failed to reconfigure log4j configuration, could not load file " + logConfigPath, e);
      }
    } else {
      logger.error("Could not find log4j configuration file " + name + ".xml on classpath");
    }
  }

बस इसे उचित कॉन्फिग नाम से पुकारें, और सुनिश्चित करें कि आप टेम्प्लेट को क्लासपाथ पर रखें।


इस विधि का ट्रिगर बिंदु क्या है? यह कैसे जानता है कि जब भी log4j config में कोई बदलाव होता है, तो इस विधि को लागू करना पड़ता है
asgs

मुझे अभी भी वह नहीं मिला है जिसका अर्थ है "मांग पर"। क्या आप कृपया एक स्निपेट दिखा सकते हैं जहाँ आप इस विधि को पूरा करते हैं?
asgs

2
यहां आप जाते हैं: यह नियंत्रक का एक स्निपेट है जहां हम इसका उपयोग करते हैं। हमारे पास डायनामिक रूप से पुन: कॉन्फ़िगर लॉगिंग के लिए कुछ लिंक के साथ एक व्यवस्थापक पृष्ठ है, जो तब लिंक / व्यवस्थापक / setLogLevel के लिए एक GET बनाता है ? स्तर = त्रुटि और फिर हम इसे इस @RequestMapping (मान = "setLogLevel", विधि =) की
ISparkes

इसलिए, "ऑन डिमांड" का अर्थ है "जब उपयोगकर्ता बटन पर क्लिक करता है" मेरे मामले में
आईएसपीआरसी

आह, आपको मिल गया। तो आपके व्यवस्थापक कंसोल को इस विधि को लागू करने के लिए अनुरोध करना होगा।
asgs

0

मैंने "org.apache.http" लॉग की क्रियाशीलता को कम करने के लिए इस विधि का प्रयोग सफलता के साथ किया है:

ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.apache.http");
logger.setLevel(Level.TRACE);
logger.setAdditive(false);


-1

यदि आप सभी लॉगर्स के लॉगिंग स्तर को बदलना चाहते हैं तो नीचे दी गई विधि का उपयोग करें। यह सभी लकड़हारा को घेर लेगा और लॉगिंग स्तर को दिए गए स्तर में बदल देगा। कृपया सुनिश्चित करें कि आपके पास आपकी फ़ाइल में संपत्ति सेट नहीं है ।log4j.appender.loggerName.Threshold=DEBUGlog4j.properties

public static void changeLogLevel(Level level) {
    Enumeration<?> loggers = LogManager.getCurrentLoggers();
    while(loggers.hasMoreElements()) {
        Logger logger = (Logger) loggers.nextElement();
        logger.setLevel(level);
    }
}

-3

आप निम्नलिखित कोड स्निपेट का उपयोग कर सकते हैं

((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(packageName)).setLevel(ch.qos.logback.classic.Level.toLevel(logLevel));

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