ということを調べました。
調べてみるとlog4jには、そういうことをやるMBeanが既にあってそれを登録するだけで出来るということでした。
ということでさっそくやってみました。
プロジェクト作成/セットアップ
今回は、NetBeans6.7 RC1で作っていきます。
事前に準備するもの。
- log4j-1.2.15.jar
新規作成から、Javaアプリケーションを作成します。名前はDynaLoggingにしました。
次に、ライブラリを追加します。
事前に準備していたlog4jのjarファイルをライブラリとして作成して、プロジェクトに追加します。
プログラム
ということで書いていきます。
ログを延々と出し続けるだけのプログラムです。
package dynalogging;
import java.util.Date;
import org.apache.log4j.Logger;
public class Main {
public static void main(String[] args) throws Exception {
Logger log = Logger.getLogger(Main.class);
while (true) {
log.info("いんふぉ: " + new Date());
Thread.sleep(1000);
}
}
}
そして、単純なlog4jの定義ファイルlog4j.xmlをデフォルトパッケージに作成します。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" >
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="stdout"/>
</root>
</log4j:configuration>
実行して、延々と出力ウィンドウにログが出続けるか確認します。
MBeanの登録
log4jにはorg.apache.log4j.jmx.HierarchyDynamicMBeanというクラスがあって、こいつがログレベルとかを動的に変えてくれる良い奴なんです。
このMBeanをmainの最初でMBeanServerに登録します。
package dynalogging;
import java.lang.management.ManagementFactory;
import java.util.Date;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.apache.log4j.Logger;
import org.apache.log4j.jmx.HierarchyDynamicMBean;
public class Main {
public static void main(String[] args) throws Exception {
// MBeanの登録
HierarchyDynamicMBean dynamicMBean = new HierarchyDynamicMBean();
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName dynamicMBeanName = new ObjectName("log4j:type=HierarchyDynamicMBean");
server.registerMBean(dynamicMBean, dynamicMBeanName);
Logger log = Logger.getLogger(Main.class);
while (true) {
log.info("いんふぉ: " + new Date());
Thread.sleep(1000);
}
}
}
登録したら、起動時のオプションにMBeanServerが有効になるオプションをつけます。
JDK5を使ってる人は、VMオプションに
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
の2つを追加します。
この状態で、アプリケーションを起動します。
さっきmainの最初で登録した、HierarchyDynamicMBeanクラス関係のログが出る以外は、さっきと同じように延々と同じログが流れていきます。
jconsole
アプリケーションが起動したらJAVE_HOME\binの下にあるjconsoleを起動します。jconsoleを起動すると新規接続のところに、今NetBeansで起動しているアプリケーションが表示されるはずなので、それを選択して接続ボタンを押します。
jconsoleのMBeanタブにさっき登録したクラスがいることを確認します。
ここにあるrootというのがlog4jのルートロガーになります。rootの属性を見てみると、priorityがDEBUGになっています。
こいつをWARNに書き換えると…
WARNにしたとたん、NetBeansのログウィンドウに延々と流れていたログがぴたりと止まります。また、INFOに切り替えると、ログが流れていきます。
出力ウィンドウの選択してる箇所を見ると8秒ほどログが止まってたことがわかります。
ここで気になるのは、ルートロガー以外は、どうなの?という部分ですが、これはHierarchyDynamicMBeanの操作にあるaddLoggerMBeanにロガー名を入れることで表示させることができます。
addLoggerMBeanボタンを押すと、dynalogging.Mainがツリーに追加されて、それの属性を見たりすることが出来ます。
こいつのpriorityを編集することで、dynaloggin.Mainロガーだけの設定を切り替えることもできます。
おまけ
これで色々操作をしていると、Appenderを作成したり色々出来ちゃいます。
しかし、色々いじった結果作ったものを消す方法が多分無い…!!
そんなときのために、こんなMBeanを作って登録しておくと、設定ファイルの状態にリセットすることが出来ます。
package dynalogging;
public interface Log4jManagerMBean {
void reset(String classPath);
}
package dynalogging;
import org.apache.log4j.LogManager;
import org.apache.log4j.xml.DOMConfigurator;
public class Log4jManager implements Log4jManagerMBean {
public void reset(String classPath) {
// 設定をリセットして読み込みなおす
LogManager.resetConfiguration();
DOMConfigurator.configure(ClassLoader.getSystemResource(classPath));
}
}
そして、これをMBeanServerに登録します。
// リセットしてくれる人も登録
Log4jManager manager = new Log4jManager();
ObjectName managerMBeanName = new ObjectName("log4j:type=Log4jManager");
server.registerMBean(manager, managerMBeanName);
こういうのを用意してると、さくっと設定ファイルの内容に切り替えが出来ます。
log4j.xml, log4j-debug.xml, log4j-none.xmlとか何パターンかクラスパスにあらかじめ登録しておけば、さくっと状況に応じて切り替えれるかもしれん。