【问题标题】:Dynamically reload log4j.properties for grails application running in tomcat为在 tomcat 中运行的 grails 应用程序动态重新加载 log4j.properties
【发布时间】:2013-12-21 05:47:41
【问题描述】:

我有一个使用 log4j 部署到 tomcat 的 grails 应用程序。我希望能够在 tomcat 中更新 /webapps/WEB-INF/classes/log4j.properties,然后让应用程序动态获取更改而无需重新启动。我没有任何运气找到一个好方法来做到这一点。我发现的是:

我可以将文件作为流检索:

Thread.currentThread().getContextClassLoader().getResourceAsStream("log4j.properties")

不幸的是,这是在启动期间加载的类,我不确定是否/如何强制它从实际文件更新。如果可行,我可以读取每个属性并使用:

Logger.rootLogger.loggerRepository.getLogger(<key>).level = <new log level>

我见过关于 LogManager.resetConfiguration() 的事情,但这似乎也没有帮助。

另外,这就是我在 resources.groovy 中设置 log4j 的方式

beans = {
    // Setting up external configuration for log4j
    log4jConfigurer(org.springframework.beans.factory.config.MethodInvokingFactoryBean) {
        targetClass = "org.springframework.util.Log4jConfigurer"
        targetMethod = "initLogging"
        arguments = ["classpath:log4j.properties"]
    }
}

我对使用 configureAndWatch 方法不感兴趣,因为我已经了解了它的漏洞。

我看到您可以将 XML 和 JSON 属性用于 log4j,而我只是使用一个普通的 *.properties 文件,我不确定这是否是问题的一部分。

任何提示将不胜感激,在此先感谢!

【问题讨论】:

  • external-config-reload plugin 有帮助吗? -- 我从来没有使用过它,所以这更像是一个问题而不是一个认可;-)
  • 我曾尝试使用它,但 grails.plugins.reloadConfig.interval 属性似乎没有按预期刷新属性。虽然我承认很有可能我在插件中配置了其他错误。
  • 这与 webapp 文件夹中的属性有关吗?您是否尝试过将属性文件放在 webapp 之外?

标签: tomcat grails logging log4j


【解决方案1】:

以下是我解决此问题的方法,它需要 setUseCaches(false),以确保不使用文件的缓存版本(来自类加载器)。

def fileInputStream = null
// The method below is used to ensure that the file is read from disk every time, rather than using the previously loaded file from the ClassLoader
def classLoader = Thread.currentThread().getContextClassLoader()
def resource = classLoader.getResource("log4j.properties")
def connection = resource.openConnection()
connection.setUseCaches(false)
// Warning: do not read or log the fileInputStream, because it will close the connection
fileInputStream = (FileInputStream)connection.getInputStream().in
// Use the Properties object to prevent errors on comments (#)
def props = new Properties()
props.load(fileInputStream)
def config = new ConfigSlurper().parse(props)

然后我可以使用以下方法引用记录器属性:

config.log4j.logger.each {
    Logger.rootLogger.loggerRepository.getLogger(it.key).level = Level.toLevel(it.value)
}

您还可以检查现有的日志级别,并提供输出以说明哪些日志实际上已更改。

【讨论】:

    猜你喜欢
    • 2011-01-08
    • 2013-06-07
    • 2010-11-22
    • 2014-07-24
    • 2011-05-14
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 2015-05-05
    相关资源
    最近更新 更多