簡體   English   中英

如何將log4j默認初始化與configureAndWatch()結合起來?

[英]How can you combine log4j default initialization with configureAndWatch()?

某些Log4j配置程序具有configureAndWatch()方法,該方法啟動Thread以查看用於配置的文件( XML文件或properties文件),並在文件更改時 觸發重新配置。

但是,如果依賴於Log4j 默認初始化過程,則永遠不會有機會調用configureAndWatch() 您甚至不知道用於配置的文件(它甚至可能不是文件。)

是否有一種獲得configureAndWatch()樣式行為的好方法,允許動態更改日志配置,同時仍然使用默認初始化過程? 我假設你的配置URL最終解析為一個可以觀看的文件,因為另一台服務器上的URL可能不是你想要每60秒拉一次的東西。

(我看到configureAndWatch()方法在Java EE環境中是不安全的,因為單獨的線程,我看到一些應用服務器有自己的機制來觀看log4j配置文件,但是我正在處理的程序片刻沒有在Java EE中運行。)

我之前已經廢棄了答案中的所有內容,現在重新開始,我更了解你想要的東西。

以下段落描述了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
    }

但是,如果依賴於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捕獲默認URL並將其交給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控制台中的黑色)來回更改為log4j.properties中的 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

我在使用默認記錄器和appender之前完成了這個。 您必須編寫一個單獨的處理程序來查看屬性文件修改。 發生更改時,只需重置記錄器並重新添加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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM