简体   繁体   中英

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

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?

From 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 documentation for 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.

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

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

<configuration monitorInterval="30">

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

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

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

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

Yes you can change the log4j level at run time without the need to restart the server provided you are using 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.

<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

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

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

They also moved it to github .

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.

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");
    */

    }
}

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

The Guido Garcia answer is quite on target.

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

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

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

(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:

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

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

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

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

Reloading can be done using DOMConfigurator's APIs

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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