簡體   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