तार्किक रूप से Log4j2 में लॉग स्तर बदलें


109

मैं तार्किक रूप से Log4j2 में लॉग स्तर को बदलने में रुचि रखता हूं। मैंने उनके विन्यास दस्तावेज को देखने की कोशिश की, लेकिन ऐसा कुछ भी नहीं लगा। मैंने पैकेज में भी देखने की कोशिश की: org.apache.logging.log4j.core.configलेकिन वहां कुछ भी मददगार नहीं लगा।


2
यदि आपको उत्तर नहीं मिलता है, तो मेल सूची आज़माएं, मुख्य लेखकों द्वारा 2 दिनों में एक बार देखा जाता है। फिर वापस आकर अपने स्वयं के प्रश्न का उत्तर दें :-)
tgkprog

जवाबों:


139

Log4j2 संस्करण 2.4 FAQ के अनुसार संपादित करें

आप Log4j Core से वर्ग विन्यासकर्ता के साथ एक लकड़हारा का स्तर निर्धारित कर सकते हैं। लेकिन पता होना चाहिए कि विन्यासकर्ता वर्ग सार्वजनिक एपीआई का हिस्सा नहीं है।

// org.apache.logging.log4j.core.config.Configurator;
Configurator.setLevel("com.example.Foo", Level.DEBUG);

// You can also set the root logger:
Configurator.setRootLevel(Level.DEBUG);

स्रोत

Log4j2 संस्करण 2.0.2 में शुरू किए गए एपीआई में परिवर्तनों को प्रतिबिंबित करने के लिए

यदि आप रूट लकड़हारा स्तर बदलना चाहते हैं, तो कुछ इस तरह से करें:

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); 
loggerConfig.setLevel(level);
ctx.updateLoggers();  // This causes all Loggers to refetch information from their LoggerConfig.

यहाँ LoggerConfig के लिए javadoc है।


3
सही और यदि आप किसी विशेष लकड़हारे (एक वर्ग / पैकेज के लिए) को बदलना चाहते हैं, तो उस लकड़हारे, सेटलेवल और अपडेटलॉगर्स का संदर्भ प्राप्त करें।
tgkprog

34
लॉगिंग स्तर को सेट करने के लिए इस तरह का एक जटिल तरीका। मुझे यकीन है कि log4j के पिछले संस्करणों में मूल एक पंक्ति के बजाय कोड की पांच पंक्तियों के साथ ऐसा करने का एक कारण है, लेकिन मैं अभी इसे स्वीकार नहीं करता हूं। किसी भी मामले में, इसके लिए धन्यवाद @slaadvak!
स्टर्म

1
.updateLoggers () आवश्यक प्रतीत नहीं होता है। ऐसा लगता है कि .setLevel () के साथ किए गए परिवर्तन तुरंत लागू होते हैं।
zbyszek

1
अपडेट करने के लिए कॉल करेंलॉगर्स की हमेशा आवश्यकता होती है, भले ही आप एक नया LoggerConfig जोड़ दें। UpdateLoggers सभी लॉगर्स को LoggerConfigs के साथ खुद को फिर से इकट्ठा करने और अपने लॉग लॉगरकॉन्ग के लिए अपने लॉग स्तर को बदलने का कारण बनता है। यदि आप एक नया LoggerConfig जोड़ते हैं तो कोई भी लकड़हारा जो नए LoggerConfig पैटर्न से मेल खाता है, उसे पुनर्निर्देशित किया जाएगा। "दृढ़" तरीके की आवश्यकता है क्योंकि लॉगर और उनके कॉन्फ़िगरेशन को लॉग 4j2 में अलग किया गया है।
'14:56 पर rgoers

1
यहां एक उत्तर है जो
लॉग

37

@Sadadvak द्वारा स्वीकृत उत्तर मुझे Log4j2 2.8.2 के लिए काम नहीं आया । निम्नलिखित ने किया।

Level सार्वभौमिक रूप से उपयोग को बदलने के लिए:

Configurator.setAllLevels(LogManager.getRootLogger().getName(), level);

Levelकेवल वर्तमान वर्ग के लिए लॉग बदलने के लिए, उपयोग करें:

Configurator.setLevel(LogManager.getLogger(CallingClass.class).getName(), level);

1
मेरा वोट मिल गया क्योंकि आपने एक स्ट्रिंग के रूप में नाम को कोड करने के बजाय लकड़हारे से लकड़हारा नाम खुद ही खींच लिया।
DWoldrich

18

यदि आप एकल विशिष्ट लकड़हारा स्तर बदलना चाहते हैं (कॉन्फ़िगरेशन फ़ाइल में रूट लकड़हारा या लकड़हारा कॉन्फ़िगर नहीं किया गया है) तो आप यह कर सकते हैं:

public static void setLevel(Logger logger, Level level) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();

    LoggerConfig loggerConfig = config.getLoggerConfig(logger.getName());
    LoggerConfig specificConfig = loggerConfig;

    // We need a specific configuration for this logger,
    // otherwise we would change the level of all other loggers
    // having the original configuration as parent as well

    if (!loggerConfig.getName().equals(logger.getName())) {
        specificConfig = new LoggerConfig(logger.getName(), level, true);
        specificConfig.setParent(loggerConfig);
        config.addLogger(logger.getName(), specificConfig);
    }
    specificConfig.setLevel(level);
    ctx.updateLoggers();
}

3
यह मेरे लकड़हारे को बिल्कुल प्रभावित नहीं करता था। मैंने उपयोग किया setLevel(logger, Level.ERROR);और logger.debug स्टेटमेंट अभी भी प्रिंट किए हैं। मेरा log4j2.xml फ़ाइल pastebin.com/fcbV2mTW
Noumenon

मैंने कोड अपडेट किया। अगर इसके साथ कोई समस्या है तो मुझे बताएं।
जार्ज फ्रेडरिक

4
Log4j 2.7 में LoggerContext एक getConfiguration () विधि नहीं है, logging.apache.org/log4j/2.x/log4j-api/apidocs/index.html?org// पर
maxxyme

log4j-core-2.7.jar है और अंतिम LoggerContext ctx = (LoggerContext) LogManager.getContext (झूठी) के रूप में इस्तेमाल किया जा सकता है; अंतिम विन्यास विन्यास = ctx.getConfiguration ();
jprism

3
इसे देखने के बाद, मैं सोच रहा हूं .. "शायद वे नहीं चाहते कि हम रनटाइम में स्तर बदल सकें?"
कोरे तुगे

13

मुझे यहाँ एक अच्छा उत्तर मिला: https://garygregory.wordpress.com/2016/01/11/changing-log-levels-in-log4j2/

आप एक विशेष लकड़हारे के लिए स्तर निर्धारित करने के लिए org.apache.log.log4j.core.config.Configurator का उपयोग कर सकते हैं।

Logger logger = LogManager.getLogger(Test.class);
Configurator.setLevel(logger.getName(), Level.DEBUG);

2
यह उत्तर एक ही समाधान दिखाता है, साथ ही इसे रूट लॉगर के लिए कैसे सेट किया जाता है - जो कभी-कभी उपयोगी होता है: stackoverflow.com/a/44678752/1339923
लैम्बर्ट

4

प्रोग्रामेटिक दृष्टिकोण बल्कि घुसपैठ है। शायद आपको लॉग 4 जे 2 द्वारा दिए गए जेएमएक्स समर्थन की जांच करनी चाहिए:

  1. अपने एप्लिकेशन स्टार्ट में JMX पोर्ट को सक्षम करें:

    -Dcom.sun.management.jmxremote.port = [port_num]

  2. किसी भी उपलब्ध JMX क्लाइंट का उपयोग करें (JVM आपके एप्लिकेशन को निष्पादित करते समय JAVA_HOME / बिन / jconsole.exe में एक प्रदान करता है)।

  3. JConsole में "org.apache.log.log4j2.Loggers" बीन देखें

  4. अंत में अपने लकड़हारे का स्तर बदलें

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

अधिक जानकारी: http://log.apache.org/log4j/2.x/manual/jmx.html


बहुत मददगार, धन्यवाद!
डैरेन पार्कर

3

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

    public class LogConfigManager {

    public void setLogLevel(String loggerName, String level) {
        Level newLevel = Level.valueOf(level);
        LoggerContext logContext = (LoggerContext) LogManager.getContext(false);
        Configuration configuration = logContext.getConfiguration();
        LoggerConfig loggerConfig = configuration.getLoggerConfig(loggerName);
        // getLoggerConfig("a.b.c") could return logger for "a.b" if there is no logger for "a.b.c"
        if (loggerConfig.getName().equalsIgnoreCase(loggerName)) {
            loggerConfig.setLevel(newLevel);
            log.info("Changed logger level for {} to {} ", loggerName, newLevel);
        } else {
            // create a new config.
            loggerConfig = new LoggerConfig(loggerName, newLevel, false);
            log.info("Adding config for: {} with level: {}", loggerConfig, newLevel);
            configuration.addLogger(loggerName, loggerConfig);


            LoggerConfig parentConfig = loggerConfig.getParent();
            do {
                for (Map.Entry<String, Appender> entry : parentConfig.getAppenders().entrySet()) {
                    loggerConfig.addAppender(entry.getValue(), null, null);
                }
                parentConfig = parentConfig.getParent();
            } while (null != parentConfig && parentConfig.isAdditive());
        }
        logContext.updateLoggers();
    }
}

उसी के लिए एक परीक्षण मामला

public class LogConfigManagerTest {
    @Test
    public void testLogChange() throws IOException {
        LogConfigManager logConfigManager = new LogConfigManager();
        File file = new File("logs/server.log");
        Files.write(file.toPath(), new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
        Logger logger = LoggerFactory.getLogger("a.b.c");
        logger.debug("Marvel-1");
        logConfigManager.setLogLevel("a.b.c", "debug");
        logger.debug("DC-1");
        // Parent logger level should remain same
        LoggerFactory.getLogger("a.b").debug("Marvel-2");
        logConfigManager.setLogLevel("a.b.c", "info");
        logger.debug("Marvel-3");
        // Flush everything
        LogManager.shutdown();

        String content = Files.readAllLines(file.toPath()).stream().reduce((s1, s2) -> s1 + "\t" + s2).orElse(null);
        Assert.assertEquals(content, "DC-1");
    }
}

लॉग 4j2.xml के बाद मान लेना क्लासपाथ में है

<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">

    <Appenders>
        <File name="FILE" fileName="logs/server.log" append="true">
            <PatternLayout pattern="%m%n"/>
        </File>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n"/>
        </Console>
    </Appenders>

    <Loggers>
        <AsyncLogger name="a.b" level="info">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="FILE"/>
        </AsyncLogger>

        <AsyncRoot level="info">
            <AppenderRef ref="STDOUT"/>
        </AsyncRoot>
    </Loggers>

</Configuration>

2

एक ऐसा सामान्य तरीका जो मुझे करने के लिए मिला है वह है अलग लॉगिंग स्तर के साथ दो अलग फ़ाइल बनाना।
उदाहरण के लिए। log4j2.xml और log4j-debug.xml अब इस फ़ाइलों से कॉन्फ़िगरेशन बदलें।
नमूना कोड:

ConfigurationFactory configFactory = XmlConfigurationFactory.getInstance();
            ConfigurationFactory.setConfigurationFactory(configFactory);
            LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = classloader.getResourceAsStream(logFileName);
            ConfigurationSource configurationSource = new ConfigurationSource(inputStream);

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