簡體   English   中英

如何在log4j默認初始化中找到使用的URL?

[英]How can you find what URL was used in log4j default initialization?

Log4j默認初始化通過一個過程來查找和使用URL進行配置。 之后,如何找出最終使用的URL,而無需自己編寫相同的程序? (如果你必須自己編寫代碼,你可能不會像log4j那樣完全相同,而且在將來的版本中也可能會改變它。)

使用的過程在LogManager中的靜態初始化程序塊中進行了硬編碼,因此似乎沒有辦法掛鈎它。 唯一能告訴你發生了什么的地方

LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");

但是LogLog本身是硬編碼的,因為這些消息使用System.out.println所以我唯一可以看到的是打開調試( -Dlog4j.debug=true )並在log4j初始化之前以某種方式掛鈎到System.setOut ,然后解析調試日志消息。 但這可能比自己編寫配置程序更加脆弱。

即使這樣,在默認配置過程之后可能還有其他編程配置(例如Spring Log4jConfigListener ) - 不一定有單個配置URL。

可能值得在log4j功能請求中將配置文件搜索代碼分解為可以從其他地方調用的靜態方法,但是當您可能必須處理早期版本的log4j時,這將無濟於事。

如果您願意使用AspectJ LTW(加載時編織),您可以查看Ian Roberts提到的LogManager的靜態初始化。 log4j 1.2.14中它看起來像這樣:

static {
    // (...)
    // if there is no default init override, then get the resource
    // specified by the user or the default config file.
    if (override == null || "false".equalsIgnoreCase(override)) {
        // (...)
        URL url = null;

        // (...)    
        // If we have a non-null url, then delegate the rest of the
        // configuration to the OptionConverter.selectAndConfigure method.
        if (url != null) {
            LogLog.debug("Using URL [" + url + "] for automatic log4j configuration.");
            OptionConverter.selectAndConfigure(
                url, configuratorClassName, LogManager.getLoggerRepository()
            );
        } else {
            LogLog.debug("Could not find resource: [" + configurationOptionStr + "].");
        }
    }
}

顯然,如果可以確定默認URL OptionConverter.selectAndConfigure(URL, ..)則將在靜態塊內的某一點調用OptionConverter.selectAndConfigure(URL, ..) ,以便使用該URL初始化log4j

通過AspectJ ,捕獲該方法調用非常簡單:

import java.net.URL;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.LogManager;

public aspect Log4jAspect {
    before(URL defaultURL) :
        within(LogManager) &&
        cflow(staticinitialization(LogManager)) &&
        call(* OptionConverter.selectAndConfigure(URL, ..)) &&
        args(defaultURL, ..)
    {
        System.out.println("log4j default URL = " + defaultURL);
    }
}

在散文中,此代碼表示:

  • 如果我們在類LogManager和
  • 在靜態類初始化的控制流程中
  • OptionConverter.selectAndConfigure
  • 然后捕獲第一個參數(URL)和
  • 將它打印到控制台(你也可以做其他事情)。

如果沒有默認URL,則不會打印任何內容。 您可以將其分配給任何類的靜態成員或您喜歡的任何內容,而不是打印URL。

這是你的問題的解決方案,我測試了它,它的工作原理。 我很樂意收到回答您問題的賞金,即使該解決方案可能使用了您沒有想到的技術。 但它解決了這個問題。 :-)


編輯:即使我認為沒有必要,也可以在沒有找到默認URL的情況下明確攔截日志調用。 我只是想提一下。

如果您可以設置自己的配置器,您可以執行以下操作:

設置JAVA系統屬性:-Dlog4j.configuratorClass = MyConfigurator然后讓配置器實例攔截doConfigure調用。

public class MyConfigurator implements Configurator
{
    public static URL url;

    @Override
    public void doConfigure(URL url, LoggerRepository repository)
    {
        this.url = url;
        new PropertyConfigurator().doConfigure(url, repository);
    }
}

將其插入到java調用中:

-Dlog4j.configDebug=true

就這樣。

暫無
暫無

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

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