4

Log4j のデフォルトの初期化では、構成する URL を見つけて使用する手順が実行されます。その後、同じ手順を自分でコーディングせずに、最終的にどの URL が使用されたかを調べるにはどうすればよいでしょうか? (自分でコーディングする必要がある場合は、log4j とまったく同じように取得できない可能性があり、将来のリリースで変更される可能性もあります。)

4

4 に答える 4

4

使用されるプロシージャは、 の静的イニシャライザ ブロックにハードコードされているLogManagerため、それにフックする方法はないようです。何が起こっているかを伝える唯一の場所は

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

しかし、LogLogそれ自体はこれらのメッセージに使用するようにハードコーディングされているSystem.out.printlnため、デバッグをオンにして ( )、 log4j が初期化-Dlog4j.debug=trueされる前に何らかの方法でフックしてから、デバッグ ログ メッセージを解析するしかありません。System.setOutしかし、それはおそらく構成手順を自分でコーディングするよりもさらに脆弱です。

それでも、デフォルトの構成手順 (例: Spring Log4jConfigListener) の後に適用された他のプログラム構成が存在する可能性があります。そのような構成 URL は必ずしも 1 つではありません。

構成ファイルの検索コードを、他の場所から呼び出すことができる静的メソッドに分解するために、log4j 機能要求を入れる価値があるかもしれませんが、log4j の以前のバージョンに対処する必要がある場合は役に立ちません。

于 2012-08-30T16:04:06.767 に答える
4

独自の Configurator をセットアップできる場合は、次のようなことができます。

JAVA システム プロパティをセットアップします。

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);
    }
}
于 2012-09-03T04:33:51.130 に答える
4

AspectJ LTW (load-time weaving) を使用する場合は、LogManagerIan Roberts が言及した静的初期化を参照してください。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 を決定できれば、その URL でlog4jOptionConverter.selectAndConfigure(URL, ..)を初期化するために、静的ブロック内のある時点で呼び出されます。

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 が見つからない場合は、ログ呼び出しを明示的に傍受することもできますが、必要ではないと思います。私はそれについて言及したかっただけです。

于 2012-08-30T23:01:02.803 に答える
1

これを Java 呼び出しに挿入します。

-Dlog4j.configDebug=true

それで全部です。

于 2012-08-31T11:47:23.070 に答える