Java 是否可以在 Tomcat 中动态重新加载 log4j.xml / log4j.properties 文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2115900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:42:04  来源:igfitidea点击:

Is it possible to reload log4j.xml / log4j.properties file dynamically in Tomcat?

javatomcatlog4j

提问by Rakesh Juyal

The problem is, whenever you change the log4j.properties/log4j.xml, you need to restart the tomcat [ or say any other server ]. Is there any workaround of reloading the log4j configuration?

问题是,无论何时更改 log4j.properties/log4j.xml,都需要重新启动 tomcat [或说任何其他服务器]。是否有重新加载 log4j 配置的解决方法?

回答by Guido

From http://logging.apache.org/log4j/1.2/faq.html#3.6

来自http://logging.apache.org/log4j/1.2/faq.html#3.6

Is there a way to get log4j to automatically reload a configuration file if it changes?

Yes. Both the DOMConfigurator and the PropertyConfigurator support automatic reloading through the configureAndWatch method. See the API documentationfor more details.

Because the configureAndWatch launches a separate wathdog 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.

如果配置文件发生变化,有没有办法让 log4j 自动重新加载配置文件?

是的。DOMConfigurator 和 PropertyConfigurator 都支持通过configureAndWatch 方法自动重新加载 。有关更多详细信息,请参阅API 文档

因为 configureAndWatch 启动一个单独的 wathdog 线程,并且因为在 log4j 1.2 中没有办法停止这个线程,所以 configureAndWatch 方法在应用程序被回收的 J2EE 环境中使用是不安全的。

Said that, I've successfully used PropertyConfigurator#configureAndWatch method in a Java EE environment (Sun One Web Server, not Tomcat).

也就是说,我已经在 J​​ava EE 环境(Sun One Web Server,而不是 Tomcat)中成功使用了 PropertyConfigurator#configureAndWatch 方法。

回答by Kieren Dixon

You can write a little initializer code with the following short steps:

您可以通过以下简短步骤编写一些初始化程序代码:

  • listen for the "BEFORE_START_EVENT",
  • when the event happens (once per Tomcat restart), start log4j using the configureAndWatch method
  • also don't forget to install a shutdown hook to cleanup the watcher thread
  • 听“BEFORE_START_EVENT”,
  • 当事件发生时(每次 Tomcat 重启一次),使用 configureAndWatch 方法启动 log4j
  • 也不要忘记安装一个关闭钩子来清理观察者线程

See this blog post for details - reload log4j configuration in tomcat

有关详细信息,请参阅此博客文章 -在 tomcat 中重新加载 log4j 配置

They also moved it to github.

他们还把它移到了github

回答by Remy Mellet

You can create a strut action or a servlet which reload the properties file. So after editing the log4j.properties file, you will need to call the servlet to reload it.

您可以创建重新加载属性文件的 strut 操作或 servlet。因此,在编辑 log4j.properties 文件后,您将需要调用 servlet 来重新加载它。

For example:

例如:

public class Log4JServlet extends HttpServlet{
  private static final long serialVersionUID = 1L;
  protected static Logger log = Logger.getLogger(Log4JTestServlet.class);

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("Reload Log4J prop file");
    String path = "C:\GlassFishESBv22\glassfish\domains\domain1\config\log4j.properties";
    PropertyConfigurator.configure(path);

    /*
    log.debug("debug message");
    log.info("info message");
    log.warn("warn message");
    log.error("error message");
    log.fatal("fatal message");
    */

    }
}

回答by Prashant Bhate

Another way is to configure Spring Framework's Log4jConfigListenerin web.xml

另一种方式是在Spring Framework的Log4jConfigListener中配置web.xml

回答by Cristian M?gheru?an-Stanciu

As of log4j 2.x you can reload the config periodically, in this example every 30 seconds:

从 log4j 2.x 开始,您可以定期重新加载配置,在此示例中每 30 秒一次:

<configuration monitorInterval="30">

Please take a look herefor more information on log4j 2.x configuration:

有关 log4j 2.x 配置的更多信息,请查看此处

回答by vsingh

Update:If you are using lg4j2.xml, the configuration is the only thing you will need for log4j to be managed at runtime

更新:如果您使用的是 lg4j2.xml,那么配置是您在运行时管理 log4j 所需的唯一内容

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="30">
  <Loggers>
-------
  </Loggers>
</Configuration>

Monitor interval 30 loads the log4j changes every 30 seconds.

监视器间隔 30 每 30 秒加载一次 log4j 更改。

Below solution is if you are on older version of log4j.

下面的解决方案是如果您使用的是旧版本的 log4j。

Yes you can change the log4j level at run time without the need to restart the server provided you are using spring.

是的,您可以在运行时更改 log4j 级别,而无需重新启动服务器,前提是您使用的是 spring。

public class OptionalLog4jConfigurer extends Log4jConfigurer implements
 InitializingBean {

public static final Long DEFAULT_REFRESH = 30000L;
 private static final Log LOG = LogFactory
 .getLog(OptionalLog4jConfigurer.class);

private String configLocation;
 private Long refreshInterval;

public OptionalLog4jConfigurer(final String configLocation,
 final Long refreshInterval) {
 this.configLocation = configLocation;

if (refreshInterval == null) {
 this.refreshInterval = DEFAULT_REFRESH;
 }
 else {
 this.refreshInterval = refreshInterval;
 }
 }


 public void afterPropertiesSet() throws Exception {
 if (!StringUtils.isEmpty(this.configLocation)) {
 LOG.info("Log4J configuration is being customized.");

this.initLoggingInternal();
 }
 else {
 LOG
 .info("Using default Log4J configuration. No customization requested");
 }
 }

public String getConfigLocation() {
 return this.configLocation;
 }

public Long getRefreshInterval() {
 return this.refreshInterval;
 }

}

Then do these changes to applicationContext.

然后对 applicationContext 进行这些更改。

<bean id="optionalLog4jInitialization"  class="com.skg.jetm.OptionalLog4jConfigurer">
<constructor-arg index="0" type="java.lang.String"  value="${log4j.configuration}" />
<constructor-arg index="1" type="java.lang.Long" value="100" />
 </bean>

Full code and explanation can be found here

完整的代码和解释可以在这里找到

Changing log4j Level dynamically

动态更改 log4j 级别

回答by Ramesh Ponnada

Another Method is to configure a file watcher using Java File WatcherService as explained below link and reload Log4J configuration on any file Modifications.

另一种方法是使用 Java File WatcherService 配置文件观察器,如下所述链接并在任何文件修改上重新加载 Log4J 配置。

https://dzone.com/articles/how-watch-file-system-changes

https://dzone.com/articles/how-watch-file-system-changes

Reloading can be done using DOMConfigurator's APIs

可以使用 DOMConfigurator 的 API 来完成重新加载

https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/DOMConfigurator.html

https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/DOMConfigurator.html

回答by 99Sono

The Guido Garcia answer is quite on target.

Guido Garcia 的回答非常准确。

Log4j 1 offers a way of reloading log4j configuration in a non JEE thread safe maner.

Log4j 1 提供了一种以非 JEE 线程安全方式重新加载 log4j 配置的方法。

So if you are in a JEE continer, you can solve your problem trivially by:

因此,如果您在 JEE 容器中,您可以通过以下方式轻松解决您的问题:

(A) Create your @Singleton ejb timer to periodically scan your log4j.properties file

(A) 创建您的 @Singleton ejb 计时器以定期扫描您的 log4j.properties 文件

(b) Look at the implementaiton of the log4j log watch given by log4j. What it does when it is time to relaoad a file is quite simply and conveniently, the following:

(b) 看log4j给出的log4j日志观察的实现。当需要重新加载文件时,它所做的事情非常简单方便,如下所示:

new PropertyConfigurator().doConfigure(filename,LogManager.getLoggerRepository());

新的 PropertyConfigurator().doConfigure(filename,LogManager.getLoggerRepository());

Just do the same, if the time stamp on you configuration file changes. That is it.

如果配置文件上的时间戳发生更改,请执行相同操作。这就对了。