一些 Log4j 配置程序使用configureAndWatch()
方法,启动一个线程以查看用于配置的文件(XML
文件或{{如果文件更改,则1}}文件)和触发重新配置。
但是,如果您依赖properties
默认初始化过程,则永远不会有机会致电Log4j
。您甚至不知道用于配置的文件(它甚至可能不是文件。)
是否有一种获得 configureAndWatch()
样式行为的好方法,允许动态更改日志配置,同时仍然使用默认初始化过程?我假设您的配置URL最终解析为可以观看的文件,因为另一台服务器上的URL可能不是您希望每隔 60秒拉出来的。
(由于单独的线程,我看到configureAndWatch()
方法在 Java EE 环境中不安全,我看到一些应用服务器有自己的机制来监视{ {1}}配置文件,但我目前正在处理的程序没有在 Java EE 中运行。)
答案 0 :(得分:9)
我之前已经废弃了答案中的所有内容,现在重新开始,我更了解你想要的内容。
以下段落描述了log4j用于确定log4j配置文件名的实际顺序。此代码尝试遵循这些规则。
http://logging.apache.org/log4j/1.2/manual.html#defaultInit
确定要使用的log4j配置文件,然后使用找到的文件设置PropertyConfigurator。这仅在文件位于文件系统上时才有效。如果文件位于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
}
答案 1 :(得分:1)
但是,如果您依赖Log4j 默认初始化过程 ,您将永远无法调用configureAndWatch()。您甚至不知道用于配置的文件(它甚至可能不是文件。)
您已在[1]和[2]中发布了一些我已经回答过的相关问题,因此这个答案是基于其他问题的解释。我再次使用AspectJ:
示例应用程序类:
import org.apache.log4j.Logger;
public class Log4jDemo {
private static Logger logger = Logger.getLogger("scrum-master.de");
public static void main(String[] args) throws InterruptedException {
while (true) {
logger.info("Log message");
Thread.sleep(2000);
}
}
}
Aspect捕获默认网址并将其移交给configureAndWatch
:
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.LogManager;
import org.apache.log4j.PropertyConfigurator;
import org.aspectj.lang.SoftException;
public aspect Log4jAspect {
after(URL defaultURL) returning :
within(LogManager) &&
cflow(staticinitialization(LogManager)) &&
call(* OptionConverter.selectAndConfigure(URL, ..)) &&
args(defaultURL, ..)
{
try {
PropertyConfigurator.configureAndWatch(new File(defaultURL.toURI()).getAbsolutePath(), 2000);
} catch (URISyntaxException e) {
throw new SoftException(e);
}
}
}
我使用Eclipse中的-Dlog4j.configDebug=true
测试它,将输出通道从System.log
(Eclipse控制台中的黑色)来回更改为System.err
(红色,此处不可见) log4j.properties ,它工作得很好。在日志输出中,您还会在检测到文件更改后看到重新配置的调试信息:
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
答案 2 :(得分:0)
在使用默认记录器和追加器之前,我已经完成了这项工作。您必须编写一个单独的处理程序来查看属性文件修改。发生更改时,只需重置记录器并重新添加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());
}