繁体   English   中英

动态改变 log4j 日志级别

[英]Dynamically Changing log4j log level

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

文件看门狗

Log4j 能够查看log4j.xml文件以进行配置更改。 如果更改 log4j 文件,log4j 会根据您的更改自动刷新日志级别。 有关详细信息org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long请参阅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()方法。 您是否在某处保留设置取决于您。

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

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

这些更改在Logger整个生命周期中都是永久性的。 在重新初始化时,配置将被读取并用作在运行时设置级别不会持久化级别更改。

更新:如果您使用的是 Log4j 2,您应该根据文档删除对setLevel的调用,因为这可以通过实现类来实现。

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

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,则需要执行额外的步骤来完成这项工作。 这似乎有点超出了这里的范围,可能值得单独提出一个问题。

对于 log4j 2 API,您可以使用

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

对于 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 日志级别,它对我有用,我没有引用任何文档。 我使用这个系统属性值来设置我的日志文件名。 我也使用相同的技术来设置日志记录级别,并且有效

将此作为 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>

我成功地使用了这种方法来减少“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);

LogManager 可以通过配置来定义,或者我们可以在代码中集成合适的 xml 格式来解决这个问题。

如果您想更改所有记录器的日志记录级别,请使用以下方法。 这将枚举所有记录器并将日志记录级别更改为给定级别。 请确保您没有log4j.properties文件中设置log4j.appender.loggerName.Threshold=DEBUG属性。

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

您可以使用以下代码片段

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM