技術空間

log4j

log4j設定ファイルのファイル名や読み込み先を変える方法


TOP > log4j > log4j設定ファイルのファイル名や読み込み先を変える方法



■log4j設定ファイルの読み込み順

log4j(log4j-1.2.17の場合)は、下記の順に設定ファイルを探し、最初に見つけたファイルを読み込む。 なお設定ファイルはクラスパスの直下に配置しなければならない。


  1. log4j.xml(カレントスレッドのクラスローダ上)
  2. log4j.xml(org.apache.log4j.helpers.Loaderのクラスローダ上)
  3. log4j.xml(ClassLoader.getSystemResource())
  4. log4j.properties(カレントスレッドのクラスローダ上)
  5. log4j.properties(org.apache.log4j.helpers.Loaderのクラスローダ上)
  6. log4j.properties(ClassLoader.getSystemResource())


基本的にxml→プロパティファイルの順に検索し、また自分に近いクラスローダから検索する。

以下は設定ファイルを配置しなかった際のlog4j自身のデバッグログである。設定ファイルを順番に探している様子がわかる。
赤字のエラーメッセージは設定ファイルが見つからなかった際に表示されるログである。

出力結果
log4j: Trying to find [log4j.xml] using context classloader sun.misc.Launcher$AppClassLoader@1d9f953d.
log4j: Trying to find [log4j.xml] using sun.misc.Launcher$AppClassLoader@1d9f953d class loader.
log4j: Trying to find [log4j.xml] using ClassLoader.getSystemResource().
log4j: Trying to find [log4j.properties] using context classloader sun.misc.Launcher$AppClassLoader@1d9f953d.
log4j: Trying to find [log4j.properties] using sun.misc.Launcher$AppClassLoader@1d9f953d class loader.
log4j: Trying to find [log4j.properties] using ClassLoader.getSystemResource().
log4j: Could not find resource: [null].
log4j:WARN No appenders could be found for logger (test.Sample).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
■log4j設定ファイルのファイル名や読み込み先を変える方法

前述のとおり、log4jは自動で設定ファイルを検索する仕組みがあるが、これにより開発者の意図しない設定ファイルを読み込んでしまうことがある。 そのような問題を回避するには、設定ファイルのファイル名や配置先を明示的に指定すればよい。その方法はいくつかある。


■設定ファイルがクラスパス外にある場合

方法1:PropertyConfigurator、DOMConfiguratorを使用する

まず設定ファイルがプロパティ形式(*.properties)の場合、PropertyConfiguratorを使用する。

コード
PropertyConfigurator.configure("resources/mylog4j.properties");

ログを出力するまでの流れは以下のような感じ。

コード
package test;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class Sample {

    private static Logger logger = Logger.getLogger(Sample.class);
    
    public static void main(String[] args){
        PropertyConfigurator.configure("resources/mylog4j.properties");
        logger.debug("sampleのログ");
    }
}

設定ファイルがxml形式(*.xml)の場合、PropertyConfiguratorをDOMConfiguratorに変更する。

コード
DOMConfigurator.configure("resources/mylog4j.xml");

但し、PropertyConfigurator/DOMConfiguratorを使うと、クラスパス直下にlog4j.propertiesやlog4j.xmlが存在するとそれも読みこんでしまう(二重にログがでたりする)。 これはgetLogger()を呼んだタイミングでLogManagerがlog4j設定ファイルを読み込んでしまうことが原因。 この問題を回避する方法として、システムプロパティを利用する方法がある。

方法2:システムプロパティを使用する

どの設定ファイルを読み込むかをシステムプロパティに指定することができる。この場合、getLoggerのタイミングはシステムプロパティ設定後でなければならない。

プロパティ形式(*.properties)の場合、下記のように設定する。

コード
package test;

import org.apache.log4j.Logger;

public class Sample {

    private static Logger logger;
    
    public static void main(String[] args){
        System.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.properties");
        logger = Logger.getLogger(Sample.class);
        logger.debug("sampleのログ");
    }
}

xml形式(*.xml)の場合、さらにlog4j.configuratorClassを指定する。指定しないとデフォルトでPropertyConfiguratorを使ってしまうため。

コード
package test;

import org.apache.log4j.Logger;

public class Sample {

    private static Logger logger;
    
    public static void main(String[] args){
        System.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.xml");
        System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator");
        logger = Logger.getLogger(Sample.class);
        logger.debug("sampleのログ");
    }
}

方法3:起動オプションを使用する

システムプロパティの応用だが、javaの起動オプションで-Dlog4j.configuration=file:/C:/tmp/mylog4j.propertiesのようにすればシンプルになる。getLoggerのタイミングも考慮する必要はない。

xmlの場合は、-Dlog4j.configuration=file:/C:/tmp/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfiguratorのようにする。

コード
package test;

import org.apache.log4j.Logger;

public class Sample {

    private static Logger logge = Logger.getLogger(Sample.class);
    
    public static void main(String[] args){
        logger.debug("sampleのログ");
    }
}

設定ファイルがクラスパス内にある場合

方法1:PropertyConfigurator、DOMConfiguratorを使用する

設定ファイルがプロパティ形式(*.properties)の場合、PropertyConfiguratorを使用するのはクラスパス外のときと同様。 但し、引数にクラスローダから取得したURLクラスを渡す。

コード
URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.properties");
PropertyConfigurator.configure(url);

ログを出力するまでの流れは以下のような感じ。

コード
package test;

import java.net.URL;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class Sample {

    private static Logger logger = Logger.getLogger(Sample.class);
    
    public static void main(String[] args){
        URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.properties");
        PropertyConfigurator.configure(url);
        logger.debug("sampleのログ");
    }
}

xml形式(*.xml)の場合、PropertyConfiguratorをDOMConfiguratorに書き換える。

コード
URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.xml");
DOMConfigurator.configure(url);

インスタンスメソッド内であれば、下記の記述も可能。

コード
URL url = this.getClass().getClassLoader().getResource("test/mylog4j.properties");
PropertyConfigurator.configure(url);
-------------------------------------------------------------------------------
URL url = this.getClass().getClassLoader().getResource("test/mylog4j.xml");
DOMConfigurator.configure(url);

方法2:システムプロパティを使用する

システムプロパティに設定する方法はクラスパス外のときと同じ記述でよい。なお外部ファイルが見つからない場合、クラスパスから検索する。

コード
package test;

import org.apache.log4j.Logger;

public class Sample {

    private static Logger logger;
    
    public static void main(String[] args){
        System.setProperty("log4j.configuration", "test/mylog4j.properties");
        logger = Logger.getLogger(Sample.class);
        logger.debug("sampleのログ");
    }
}

xmlの場合は、log4j.configuratorClassも指定する。

System.setProperty("log4j.configuration", "test/mylog4j.xml");
System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator");
logger = Logger.getLogger(Sample.class);

方法3:起動オプションを使用する

プロパティ形式の場合は、-Dlog4j.configuration=test/mylog4j.properties

xml形式の場合は、-Dlog4j.configuration=test/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator

コード
package test;

import org.apache.log4j.Logger;

public class Sample {

    private static Logger logge = Logger.getLogger(Sample.class);
    
    public static void main(String[] args){
        logger.debug("sampleのログ");
    }
}
■まとめ

実現方式がたくさんあるので、最後に一覧にまとめておく。

配置先方式ファイル形式コード備考
クラスパス外ConfiguratorプロパティPropertyConfigurator.configure("resources/mylog4j.properties")クラスパス直下に設定ファイルがあると二重にログがでたりする。
XMLDOMConfigurator.configure("resources/mylog4j.xml");クラスパス直下に設定ファイルがあると二重にログがでたりする。
システムプロパティプロパティSystem.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.properties")getLoggerはシステムプロパティ設定後に使う。
XMLSystem.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.xml")
System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator")
getLoggerはシステムプロパティ設定後に使う。
起動オプションプロパティ-Dlog4j.configuration=file:/C:/tmp/mylog4j.properties
XML-Dlog4j.configuration=file:/C:/tmp/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator
クラスパス内ConfiguratorプロパティURL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.properties")
PropertyConfigurator.configure(url)
クラスパス直下に設定ファイルがあると二重にログがでたりする。
XMLURL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.xml")
DOMConfigurator.configure(url);
クラスパス直下に設定ファイルがあると二重にログがでたりする。
システムプロパティプロパティSystem.setProperty("log4j.configuration", "test/mylog4j.properties")getLoggerはシステムプロパティ設定後に使う。
XMLSystem.setProperty("log4j.configuration", "test/mylog4j.xml")
System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator")
getLoggerはシステムプロパティ設定後に使う。
起動オプションプロパティ-Dlog4j.configuration=test/mylog4j.properties
XML-Dlog4j.configuration=test/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator



TOP > log4j > log4j設定ファイルのファイル名や読み込み先を変える方法

Tweet ̃Gg[͂ĂȃubN}[Nɒlj
技術空間