Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将log4j默认初始化与configureAndWatch()结合起来?_Java_Logging_Log4j - Fatal编程技术网

Java 如何将log4j默认初始化与configureAndWatch()结合起来?

Java 如何将log4j默认初始化与configureAndWatch()结合起来?,java,logging,log4j,Java,Logging,Log4j,一些Log4j配置程序有一个configureAndWatch()方法,该方法启动一个线程来监视用于配置的文件(XML文件或properties文件),并在文件更改时触发重新配置 但是,如果依赖于Log4j默认初始化过程,则永远不会有机会调用configureAndWatch()。您甚至不知道用于配置的文件(它甚至可能不是文件) 有没有一种好方法可以获得configureAndWatch()风格的行为,允许在仍然使用默认初始化过程的情况下动态更改日志配置?我假设您的配置URL最终解析为一个可以监

一些Log4j配置程序有一个
configureAndWatch()
方法,该方法启动一个线程来监视用于配置的文件(
XML
文件或
properties
文件),并在文件更改时触发重新配置

但是,如果依赖于
Log4j
默认初始化过程,则永远不会有机会调用
configureAndWatch()
。您甚至不知道用于配置的文件(它甚至可能不是文件)

有没有一种好方法可以获得
configureAndWatch()
风格的行为,允许在仍然使用默认初始化过程的情况下动态更改日志配置?我假设您的配置URL最终解析为一个可以监视的文件,因为另一台服务器上的URL可能不是您希望每60秒提取一次的内容


(我看到
configureAndWatch()
方法在Java EE环境中是不安全的,因为线程是分开的,我看到一些应用服务器有自己的机制来监视
log4j
配置文件,但我目前正在处理的程序没有在Java EE中运行。)

我以前已经放弃了答案中的所有内容,现在重新开始,以便更好地理解您的需求

下面的段落描述了log4j用来确定log4j配置文件名的实际顺序。此代码尝试遵循这些规则

它确定要使用的log4j配置文件,然后使用找到的文件设置PropertyConfiguration。这仅在文件位于文件系统上时才起作用。如果文件位于jar内或位于远程HTTP URL,则它将不起作用

    String prop = System.getProperty("log4j.configuration");
    if (prop == null) prop = "log4j.properties";
    URL log4jConfig = Loader.getResource(prop);
    if (log4jConfig.getProtocol().equalsIgnoreCase("file")) {
        PropertyConfigurator.configureAndWatch(log4jConfig.getFile().substring(1), 10000);
    }
    else {
        // cannot monitor if file changed because URL is not a file
    }

在使用默认记录器和附加器之前,我已经完成了这项工作。您必须编写一个单独的处理程序来监视属性文件修改。发生更改时,只需重置记录器并重新添加appender设置:

/**
 * Setup log4j appender.
 */
public static void setupLog4jAppender(Class appender) {
    getLogger();

    String rootLogger=(String)props.get("log4j.rootLogger");
    rootLogger+=",appname";
    getProps().setProperty("log4j.rootLogger", rootLogger);

    getProps().put("log4j.appender.appname", appender.getName());  // Our custom appender
    getProps().put("log4j.appender.appname.layout", "org.apache.log4j.PatternLayout"); 
    //See: http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
    getProps().put("log4j.appender.appname.layout.ConversionPattern", "%d{ABSOLUTE} %5p %c{1}:%L - %m%n");

    LogManager.resetConfiguration();
    PropertyConfigurator.configure(getProps());
}
但是,如果您依赖Log4j默认初始化过程,则永远不会有机会调用configureAndWatch()。您甚至不知道用于配置的文件(它甚至可能不是文件)

你已经发布了一些相关的问题,我已经在和中回答了这些问题,所以这个答案是建立在其他人的解释之上的。同样,我使用的是AspectJ:

示例应用程序类:

import org.apache.log4j.Logger;
公共类Log4jDemo{
私有静态记录器=Logger.getLogger(“scrum master.de”);
公共静态void main(字符串[]args)引发InterruptedException{
while(true){
logger.info(“日志消息”);
《睡眠》(2000年);
}
}
}
捕获默认URL并将其移交给
configureAndWatch

导入java.io.File;
导入java.net.URISyntaxException;
导入java.net.URL;
导入org.apache.log4j.helpers.OptionConverter;
导入org.apache.log4j.LogManager;
导入org.apache.log4j.propertyConfiguration;
导入org.aspectj.lang.SoftException;
公共方面日志4JASPECT{
(URL defaultURL)返回后:
内部(日志管理器)&&
cflow(静态初始化(日志管理器))&&
调用(*选项转换器。选择并配置(URL,…)&&
参数(默认URL,…)
{
试一试{
PropertyConfiguration.configureAndWatch(新文件(defaultURL.toURI()).getAbsolutePath(),2000);
}捕获(URISyntaxException e){
抛出新的软异常(e);
}
}
}
我使用Eclipse中的
-Dlog4j.configDebug=true
对它进行了测试,在log4j.properties中将输出通道从
System.log
(Eclipse控制台中的黑色)来回更改为
System.err
(红色,此处不可见),它工作得很好。在日志输出中,您还可以看到检测到文件更改后重新配置的调试信息:

log4j: Trying to find [log4j.xml] using context classloader sun.misc.Launcher$AppClassLoader@f4a24a.
log4j: Trying to find [log4j.xml] using sun.misc.Launcher$AppClassLoader@f4a24a class loader.
log4j: Trying to find [log4j.xml] using ClassLoader.getSystemResource().
log4j: Trying to find [log4j.properties] using context classloader sun.misc.Launcher$AppClassLoader@f4a24a.
log4j: Using URL [file:/C:/Dokumente%20und%20Einstellungen/Robin/Eigene%20Dateien/java-src/dummy2/bin/log4j.properties] for automatic log4j configuration.
log4j: Reading configuration from URL file:/C:/Dokumente%20und%20Einstellungen/Robin/Eigene%20Dateien/java-src/dummy2/bin/log4j.properties
log4j: Parsing for [root] with value=[debug, stdout].
log4j: Level token is [debug].
log4j: Category root set to DEBUG
log4j: Parsing appender named "stdout".
log4j: Parsing layout options for "stdout".
log4j: Setting property [conversionPattern] to [%d{ABSOLUTE} %5p %c{1}:%L - %m%n].
log4j: End of parsing for "stdout".
log4j: Setting property [target] to [System.err].
log4j: Parsed "stdout" options.
log4j: Finished configuring.
log4j: Parsing for [root] with value=[debug, stdout].
log4j: Level token is [debug].
log4j: Category root set to DEBUG
log4j: Parsing appender named "stdout".
log4j: Parsing layout options for "stdout".
log4j: Setting property [conversionPattern] to [%d{ABSOLUTE} %5p %c{1}:%L - %m%n].
log4j: End of parsing for "stdout".
log4j: Setting property [target] to [System.err].
log4j: Parsed "stdout" options.
log4j: Finished configuring.
17:48:20,944  INFO de:10 - Log message
17:48:22,944  INFO de:10 - Log message
17:48:24,944  INFO de:10 - Log message
17:48:26,944  INFO de:10 - Log message
log4j: Parsing for [root] with value=[debug, stdout].
log4j: Level token is [debug].
log4j: Category root set to DEBUG
log4j: Parsing appender named "stdout".
log4j: Parsing layout options for "stdout".
log4j: Setting property [conversionPattern] to [%d{ABSOLUTE} %5p %c{1}:%L - %m%n].
log4j: End of parsing for "stdout".
log4j: Setting property [target] to [System.out].
log4j: Parsed "stdout" options.
log4j: Finished configuring.
17:48:28,944  INFO de:10 - Log message
17:48:30,944  INFO de:10 - Log message
17:48:32,944  INFO de:10 - Log message
17:48:34,944  INFO de:10 - Log message
log4j: Parsing for [root] with value=[debug, stdout].
log4j: Level token is [debug].
log4j: Category root set to DEBUG
log4j: Parsing appender named "stdout".
log4j: Parsing layout options for "stdout".
log4j: Setting property [conversionPattern] to [%d{ABSOLUTE} %5p %c{1}:%L - %m%n].
log4j: End of parsing for "stdout".
log4j: Setting property [target] to [System.err].
log4j: Parsed "stdout" options.
log4j: Finished configuring.
17:48:36,944  INFO de:10 - Log message
17:48:38,944  INFO de:10 - Log message

考虑到log4j当前的限制,我认为这个解决方案是最好的。我看到的唯一问题是,如果您自己获取属性,您可能会错过检查与log4j在默认初始化中检查的完全相同的内容。重要提示:不要在linux上使用子字符串(1),因为这会导致路径错误。我还必须在运行OSX的Windows上删除子字符串(1),由于文件路径以\\psf(从OSX文件系统装入)开始,Watch创建了新的线程,对jee systemThank guy来说并不理想。我也有这样一个想法,即在不更改代码的情况下修改当前日志系统,我改用了Spring AOP。那么您一定用了另一种方法,因为Spring AOP既不支持
cflow()
也不支持
call()
。那么,您是如何实施您的解决方案的?