动态改变log4j的级别(level)

转载:http://stackoverflow.com/questions/4598702/dynamically-changing-log4j-log-level


Changing the log level is simple; modifying other portions of the configuration will pose a more in depth approach.

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

The changes are permanent through the life cyle of the Logger. On reinitialization the configuration will be read and used as setting the level at runtime does not persist the level change.

UPDATE: If you are using Log4j 2 you should remove the calls to setLevel per the documentationas this can be achieved via implementation classes.

Calls to logger.setLevel() or similar methods are not supported in the API. Applications should remove these. Equivalent functionality is provided in the Log4j 2 implementation classes but may leave the application susceptible to changes in Log4j 2 internals.

share improve this answer
 
3 
For only runtime dependencies LogManager.getLogger(Class.forName("org.hibernate.util.JDBCE‌​xceptionReporter")).‌​setLevel(Level.FATAL‌​); –  CelinHC  Oct 16 '11 at 18:38
2 
Note that the log4j 2 API does not provide a "setLevel" method. –  ChrisCantrell  Oct 29 '13 at 20:36
2 
But this only sets the root logger , isn't it? If individual levels are set for loggers under root, setting the root logger will have no effect on those LOGGER's. Wouldn't we have to do something like root.getLoggerRepository().getCurrentCategories(), iterate over each instance of the logger and set LEVELs for each logger? @AaronMcIver –  Vishal P  Jul 11 '14 at 9:17
4 
@ChrisCantrell Log4j 2 does provide a way to do this, although it's not as simple. –  CorayThan  Jul 21 '14 at 17:38
1 
Log4j2 can be configured to refresh its configuration by scanning the log4j2.xml file (or equivalent) at given intervals. E.g. <Configuration status="warn" monitorInterval="5" name="tryItApp" packages=""> –  Kimball Robinson  Aug 31 '15 at 16:56

File Watchdog

Log4j is able to watch the log4j.xml file for configuration changes. If you change the log4j file, log4j will automatically refresh the log levels according to your changes. See the documentation of org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long) for details. The default wait time between checks is 60 seconds. These changes would be persistent, since you directly change the configuration file on the filesystem. All you need to do is to invoke DOMConfigurator.configureAndWatch() once.

Caution: configureAndWatch method is unsafe for use in J2EE environments due to a Thread leak

JMX

Another way to set the log level (or reconfiguring in general) log4j is by using JMX. Log4j registers its loggers as JMX MBeans. Using the application servers MBeanServer consoles (or JDK's jconsole.exe) you can reconfigure each individual loggers. These changes are not persistent and would be reset to the config as set in the configuration file after you restart your application (server).

Self-Made

As described by Aaron, you can set the log level programmatically. You can implement it in your application in the way you would like it to happen. For example, you could have a GUI where the user or admin changes the log level and then call the setLevel() methods on the logger. Whether you persist the settings somewhere or not is up to you.

share improve this answer
 
6 
A word of caution regarding log4j watchdog approach: "Because the configureAndWatch launches a separate watchdog thread, and because there is no way to stop this thread in log4j 1.2, the configureAndWatch method is unsafe for use in J2EE envrironments where applications are recycled". Reference: Log4J FAQ –  Somu  Nov 29 '11 at 19:29
 
If i was to use configureAndWatch functionality of Log4j I could stop that watchdog thread in an EJB's @PostDestroy method (that's a good enough indicator of when the container is shutting down) That's it ? Or is there more to it that I am missing..! –  robin bajaj  Sep 27 '13 at 20:08 
 
sorry I meant @PreDestroy method –  robin bajaj  Sep 27 '13 at 20:14 
 
"Log4j registers its loggers as JMX MBeans.". My servlet uses log4j 1.2 I don't see any log4j MBeans. –  Abdull  Jan 18 at 13:39
 
All you need to do is to invoke DOMConfigurator.configureAndWatch() once. How can I achieve this ? –  gstackoverflow  Sep 5 at 10:22

Log4j2 can be configured to refresh its configuration by scanning the log4j2.xml file (or equivalent) at given intervals. Just add the "monitorInterval" parameter to your configuration tag. See line 2 of the sample log4j2.xml file, which tells log4j to to re-scan its configuration if more than 5 seconds have passed since the last log event.

<?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>
share improve this answer
 
 
Does not seem to work in log4j2 –  vsingh  Mar 3 at 18:53

With log4j 1.x I find the best way is to use a DOMConfigurator to submit one of a predefined set of XML log configurations (say, one for normal use and one for debugging).

Making use of these can be done with something like this:

  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");
    }
  }

Just call this with the appropriate config name, and make sure that you put the templates on the classpath.

share improve this answer
 
 
what is the triggering point of this method? how does it know this method has to be invoked whenever there's a change in the log4j config? –  asgs  Mar 31 at 20:24
 
No, it is on demand. –  Ian Sparkes  Apr 1 at 20:45
 
I still don't get what you mean "on demand". Can you please show a snippet where you hook this method up?–  asgs  Apr 2 at 5:42
1 
Here you go: This is a snippet from the Controller where we use it. We have an admin page with some links to dynamically reconfigure logging, which then makes a GET to the link /admin/setLogLevel?level=Error and then we catch this in the controller like this @RequestMapping(value = "setLogLevel", method = RequestMethod.GET) public ModelAndView setLogLevel(@RequestParam(value = "level", required = true) String level) { Log4jReconfigurator.reconfigureExisting(level); –  Ian Sparkes  Apr 5 at 9:49 
 
So, "on demand" means "when the user clicks the button" in my case –  Ian Sparkes  Apr 5 at 9:55

I did this to dynamically Change log4j log level and it worked for me, I have n't referred any document. I used this system property value to set my logfile name. I used the same technique to set logging level as well, and it worked

passed this as JVM parameter (I use Java 1.7)

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

in the log4j.properties file, I added this entry

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

I tried

 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

It all worked. hope this helps!

I have these following dependencies in my 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>
share improve this answer
 
 
Whatever you mentioned seems to be fine, but the question is about dynamically changing the logging level.–  Azim  Jul 13 at 12:11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值