【问题标题】:Is it possible to reload log4j.xml / log4j.properties file dynamically in Tomcat?是否可以在 Tomcat 中动态重新加载 log4j.xml / log4j.properties 文件?
【发布时间】:2011-01-08 02:58:18
【问题描述】:

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

【问题讨论】:

    标签: java tomcat log4j


    【解决方案1】:

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

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

    是的。 DOMConfigurator 和 PropertyConfigurator 支持自动 通过重新加载 configureAndWatch 方法。请参阅API documentation 了解更多信息 详情。

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

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

    【讨论】:

    • 在您的应用程序重新启动或重新部署几次之前,您可能不会注意到问题。线程或其他资源泄漏可能最终导致您的应用服务器瘫痪。
    【解决方案2】:

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

    • 收听“BEFORE_START_EVENT”,
    • 当事件发生时(每次 Tomcat 重启一次),使用 configureAndWatch 方法启动 log4j
    • 别忘了安装一个关闭钩子来清理观察者线程

    有关详细信息,请参阅此博客文章 - reload log4j configuration in tomcat

    他们还将其移至github

    【讨论】:

    • 支持您的答案作为解决方案对我最有用,但为了改进答案(并维护 SO 标准),我建议您在答案本身中添加一些细节。在这里,让我为您编辑该答案:)
    【解决方案3】:

    您可以创建一个支撑动作或一个重新加载属性文件的 servlet。所以在编辑完 log4j.properties 文件后,你需要调用 servlet 来重新加载它。

    例如:

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

    【讨论】:

    • 这是一种干净的方法。
    【解决方案4】:

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

    【讨论】:

    • 对生产没有帮助。从文档中,“警告:假设一个扩展的 WAR 文件”
    【解决方案5】:

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

    <configuration monitorInterval="30">
    

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

    【讨论】:

    • @PeterRader 确实,该属性仅在 log4j 2 中受支持
    • 配置应该是大写的,因为它是 log4j2
    【解决方案6】:

    更新:如果您使用的是 lg4j2.xml,配置是您在运行时管理 log4j 唯一需要的东西

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

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

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

    是的,您可以在运行时更改 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;
     }
    
    }
    

    然后对 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>
    

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

    Changing log4j Level dynamically

    【讨论】:

      【解决方案7】:

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

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

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

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

      【讨论】:

        【解决方案8】:

        Guido Garcia 的回答非常准确。

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

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

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

        (b) 看log4j给出的log4j log watch的实现。 当需要重新加载文件时,它的作用非常简单方便,如下所示:

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

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

        【讨论】:

          猜你喜欢
          • 2013-12-21
          • 1970-01-01
          • 1970-01-01
          • 2011-05-14
          • 2015-04-30
          • 2012-09-01
          • 2011-11-16
          • 2010-12-20
          • 2017-09-07
          相关资源
          最近更新 更多