动态更改log4j日志级别


127

有什么不同的方法可以动态更改log4j日志级别,这样我就不必重新部署应用程序。在这种情况下,更改是否是永久性的?





1
请注意,该页面上的(几乎)所有内容都是关于log4j的,而不是关于log4j2的。整个页面充满了混乱和误导,以至于毫无用处。按照@slaadvak的建议,转到stackoverflow.com/questions/23434252/…
兰伯特

Answers:


86

更改日志级别很简单;修改配置的其他部分将构成更深入的方法。

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

这些变化在生命周期中是永久的Logger。重新初始化时,将读取配置并将其用作运行时设置级别,而不保留级别更改。

更新:如果您正在使用Log4j 2,则应删除setLevel文档的调用,因为可以通过实现类来实现。

API不支持调用logger.setLevel()或类似方法。应用程序应删除这些。Log4j 2实现类中提供了等效的功能,但可能会使应用程序容易受到Log4j 2内部的更改的影响。


5
对于仅运行时依赖项LogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC 2011年

8
请注意,log4j 2 API不提供“ setLevel”方法。
ChrisCantrell

5
但这仅设置了根记录器,不是吗?如果为root下的记录器设置了单独的级别,则设置root记录器将不会影响那些LOGGER的记录器。我们是否不必做类似root.getLoggerRepository()。getCurrentCategories()的操作,遍历记录器的每个实例并为每个记录器设置LEVEL?@AaronMcIver
TheMonkWhoSoldHisCode 2014年

8
@ChrisCantrell Log4j 2 确实提供了一种方法,尽管它并不那么简单。
CorayThan

2
可以将Log4j2配置为通过以给定的间隔扫描log4j2.xml文件(或等效文件)来刷新其配置。例如<Configuration status =“ warn” monitorInterval =“ 5” name =“ tryItApp” package =“”>
Kimball Robinson

89

文件看门狗

Log4j能够查看log4j.xml文件中的配置更改。如果更改log4j文件,log4j将根据您的更改自动刷新日志级别。有关org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long详细信息,请参见的文档。检查之间的默认等待时间为60秒。这些更改将是持久的,因为您可以直接在文件系统上更改配置文件。您要做的就是一次调用DOMConfigurator.configureAndWatch()。

警告:由于线程泄漏,configureAndWatch方法在J2EE环境中使用是不安全的

JMX

设置日志级别(或通常重新配置)log4j的另一种方法是使用JMX。Log4j将其记录器注册为JMX MBean。使用应用程序服务器MBeanServer控制台(或JDK的jconsole.exe),您可以重新配置每个单独的记录器。这些更改不是永久性的,将在重新启动应用程序(服务器)后重置为配置文件中设置的配置。

自制

如Aaron所述,您可以通过编程方式设置日志级别。您可以按照自己希望的方式在应用程序中实现它。例如,您可能有一个GUI,用户或管理员可以在其中更改日志级别,然后setLevel()在记录器上调用方法。是否将设置持久化取决于您自己。


8
关于log4j看门狗方法的警告:“因为configureAndWatch启动了一个单独的看门狗线程,并且由于无法在log4j 1.2中停止该线程,所以configureAndWatch方法在回收应用程序的J2EE环境中使用是不安全的”。参考:Log4J FAQ
Somu

如果我要使用Log4j的configureAndWatch功能,则可以在EJB的@PostDestroy方法中停止该看门狗线程(这足以表明容器何时关闭)。是吗?还是我想念的还有更多..!
robin bajaj 2013年

抱歉,我的意思是@PreDestroy方法
robin bajaj 2013年

Log4j将其记录器注册为JMX MBean。 ”。我的servlet使用log4j 1.2,但没有看到任何log4j MBean。
阿卜杜勒

您要做的就是一次调用DOMConfigurator.configureAndWatch()。我该如何实现?
gstackoverflow

5

可以将Log4j2配置为通过以给定的间隔扫描log4j 2 .xml文件(或等效文件)来刷新其配置。只需将“ monitorInterval ”参数添加到您的配置标签中即可。请参阅示例log4j 2 .xml文件的第2行,该文件告诉log4j如果自上次日志事件以来已过去5秒以上,则重新扫描其配置。

<?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>

如果要部署到tomcat实例,在IDE内或使用spring boot时,还有一些额外的步骤可以使此工作正常进行。这似乎有点超出范围,可能值得提出一个单独的问题。


@vsingh,您是在spring boot,tomcat或容器中部署还是在IDE中部署?在这种情况下,有时可能需要采取额外的步骤(不是log4j2的错误)-基本上,应用程序看不到文件更改,因为文件已通过框架或工具复制到其他位置。
金博尔·鲁滨逊

嗨,我在Jboss6.4上进行了测试,并更新了app可以在其中查看文件的位置(.war文件内部)下的log4j2配置文件。但是它仍然没有用。有什么建议吗?
MidTierDeveloper

3

此答案不会帮助您动态更改日志记录级别,需要重新启动服务,如果可以很好地重新启动服务,请使用以下解决方案

我这样做是为了更改log4j日志级别,它对我有用,但我没有引用任何文档。我使用此系统属性值来设置我的日志文件名。我也使用相同的技术来设置日志记录级别,并且它有效

将此作为JVM参数传递(我使用Java 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
无论您提到什么内容都不错,但问题是关于动态更改日志记录级别。
阿西姆(Azim)2016年

为此,您需要重新启动服务。这不会动态更改日志记录级别。
kk。

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配置发生更改时必须调用此方法?

我仍然不明白您的意思是“按需”。您能否在使用此方法的地方显示一个代码段?
asgs'Apr

2
您可以执行以下操作:这是Controller所使用的代码段。我们有一个管理页面,其中包含一些用于动态重新配置日志记录的链接,该链接随后将GET链接到 / admin / setLogLevel?level = Error ,然后像这样 @ControllerMapping(value =“ setLogLevel”,method = RequestMethod.GET)公共ModelAndView setLogLevel(@RequestParam(value =“ level”,required = true)字符串级别){Log4jReconfigurator.reconfigureExisting(level);
ISparkes'Apr

因此,在我的情况下,“按需”是指“当用户单击按钮时”
ISparkes

啊,明白了。因此,您的管理控制台必须发出请求以调用此方法。
asgs 2016年

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

0

对于log4j 2 API,可以使用

Logger logger = LogManager.getRootLogger();
Configurator.setAllLevels(logger.getName(), Level.getLevel(level));

-1

如果要更改所有记录器的记录级别,请使用以下方法。这将枚举所有记录器,并将记录级别更改为给定级别。请确保你不要log4j.appender.loggerName.Threshold=DEBUG属性设置你的log4j.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 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.