Log4j のデフォルトの初期化では、構成する URL を見つけて使用する手順が実行されます。その後、同じ手順を自分でコーディングせずに、最終的にどの URL が使用されたかを調べるにはどうすればよいでしょうか? (自分でコーディングする必要がある場合は、log4j とまったく同じように取得できない可能性があり、将来のリリースで変更される可能性もあります。)
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 の以前のバージョンに対処する必要がある場合は役に立ちません。
独自の 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);
}
}
AspectJ LTW (load-time weaving) を使用する場合は、LogManager
Ian 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 が見つからない場合は、ログ呼び出しを明示的に傍受することもできますが、必要ではないと思います。私はそれについて言及したかっただけです。
これを Java 呼び出しに挿入します。
-Dlog4j.configDebug=true
それで全部です。