第10章 JMXコンフィギュレーター
名前のとおり、JMXConfiguratorを使うとJMX経由でlogbackを設定することができます。つまり、デフォルトの設定ファイルで設定されたlogbackを、指定したパスやURLに配置した設定ファイルの内容で再設定したり、ロガーの一覧を取得したり、ロガーのレベルを変更することができるのです。
JMXコンフィギュレーターを使用する
サーバーを実行しているJVMがJDK1.6以降なら、コマンドラインからjconsoleコマンドを実行するだけで、実行中のサーバーのMBeanServerにアクセスすることができます。古いJVMで実行している場合はサーバーでJMXを有効化するのセクションを読んでおいてください。
次のように設定ファイルに1行追加するだけでJMXConfiguratorが有効になります。
<configuration>
<jmxConfigurator />
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%date [%thread] %-5level %logger{25} - %msg%n</Pattern>
</layout>
</appender>
<root level="debug">
<appender-ref ref="console" />
</root>
</configuration>
jconsoleでサーバーに接続すれば、MBeans タブに表示される "ch.qos.logback.classic.jmx.Configurator" フォルダの下にいろいろなコマンドがぶら下がっているのが確認できます。スクリーンショットを見てください。
jconsoleでJMXConfiguratorを表示している様子
次のような操作を実行することができます。
- デフォルトの設定ファイルを使用してlogbackを再設定します。
- URLに配置された設定ファイルを使用して再設定します。
- ファイルパスに配置された設定ファイルを使用して再設定します。
- 指定したロガーのレベルを設定します。nullを設定するには文字列"null"を指定します。
- 指定したロガーのレベルを取得します。nullになることがあります。
- 指定したロガーの有効レベルを取得します。
JMXConfiguratorはAttributesとして存在しているロガーの一覧と、ステータスの一覧を公開します。
ステータスの一覧は、logbackの内部状態を診断するのに役立ちます。
メモリリークを避ける
アプリケーションがWebサーバーやアプリケーションサーバにデプロイされているときは、JMXConfiguratorのインスタンスをJVMのMBeanサーバーに登録すると、システムクラスローダーの参照をアプリケーションが持つようになってしまいます。これはアプリケーションが停止したり再デプロイされたときにJMXConfiguratorがガベージコレクションされてしまうのを防ぐためですが、そのせいで深刻なメモリリークが生じてしまいます。
したがって、スタンドアローンなJavaアプリケーションではないときは、必ずJMXConfiguratorのインスタンスの登録をJVMのMBeanサーバーから解除しなければなりません。適切なLoggerContetextのreset()メソッドを呼べば、すべてのJMXConfiguratorのインスタンスは自動的に解除されるはずです。ロガーコンテキストを初期化するなら、javax.servlet.ServletContextListenerのcontextDestroyed()メソッドがちょうど良い場所です。サンプルコードを見てみましょう。
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
public class MyContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent sce) {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.stop();
}
public void contextInitialized(ServletContextEvent sce) {
}
}
複数のWebアプリケーションでJMXConfiguratorを使用する
複数のアプリケーションを同じサーバーにデプロイしている、コンテキストセレクタを上書きせずデフォルトのまま使っている、それぞれのアプリケーションのWEB-INF/libフォルダにlogback-*.jarとslf4j-api.jarを置いている、これらが全て当てはまるなら、それぞれのアプリケーションのJMXConfiguratorのインスタンスは同じ名前("ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator")で登録されてしまうでしょう。言い換えると、何もしなければそれぞれのアプリケーションのロガーコンテキストに関連付けられたJMXConfiguratorのインスタンスは衝突してしまうのです。
衝突を避けるには、単にアプリケーションのロガーコンテキストに名前を付けるだけでよいのです。そうすれば、JMXConfiguratorには自動的にその名前が設定されます。
たとえば、それぞれ"コアラ"と"コウモリ"という名前のアプリケーションをデプロイしているものとします。そして、コアラのlogback.xmlには次のような設定がされているとしましょう。
<configuration> <contextName>Koala</contextName> <jmxConfigurator/> ... <configuration>
また、コウモリのlogback.xmlには次のように設定がされていることにします。
<configuration> <contextName>Wombat</contextName>x <jmxConfigurator/> ... <configuration>
そうすると、jconsoleのMBeanタブには、次のように二つの独立したJMXConfiguratorのインスタンスが表示されるはずです。
MBeanサーバーに登録されるJMXConfiguratorの名前は、jmxConfigurator要素の"objectName"属性で指定することができます。
JMXを有効化する
JDK1.6以降のJVMでサーバーを実行している場合はデフォルトでJMXが有効になっています。
JDK1.6以前の古いJVMを使っている場合は、サーバーのJMX関連のドキュメントを確認することをおすすめします。たとえばTomcatやJettyにはドキュメントがあります。それはさておき、このドキュメントではTomcatとJettyの設定方法を簡単に説明していきます。
JettyでJMXを有効にする(JDK 1.5およびJDK 1.6で動作確認済み)
以降の設定はJDK1.5とJDK1.6で動作確認しています。JDK1.6以降のJVMでは、デフォルトでJMXが有効になっています。以降の設定をしてもよいですが、特に何も変わりません。JDK1.5のJVMで実行するJettyでJMXを有効にするには、設定ファイル$JETTY_HOME/etc/jetty.xmlにいくつか設定を追加する必要があります。追加するのは次の設定です。
<Call id="MBeanServer" class="java.lang.management.ManagementFactory"
name="getPlatformMBeanServer"/>
<Get id="Container" name="container">
<Call name="addEventListener">
<Arg>
<New class="org.mortbay.management.MBeanContainer">
<Arg><Ref id="MBeanServer"/></Arg>
<Call name="start" />
</New>
</Arg>
</Call>
</Get>
Jettyの公開するMBeanにjconsoleでアクセスしたいときは、Jettyを実行するJVMにシステムプロパティ"com.sun.management.jmxremote"を指定しておかなければなりません。
スタンドアローン版のJettyなら次のように実行します。
java -Dcom.sun.management.jmxremote -jar start.jar [config files]
MavenのプラグインからJettyを実行する場合は、システムプロパティ"com.sun.management.jmxremote"をシェル変数MAVEN_OPTSで指定しなければなりません。
MAVEN_OPTS="-Dcom.sun.management.jmxremote" mvn jetty:run
そうすれば、jconsoleでJettyの公開するMBeanとしてJMXConfiguratorにアクセスすることができます。
接続したら、前のスクリーンショットのようにJMXConfiguratorにアクセスできるはずです。
JettyにMX4Jを入れる(JDK 1.5およびJDK 1.6で動作確認済み)
MX4JのHTTPインターフェイスを経由してJMXConfiguratorにアクセスしたいときは、前に説明した設定ファイルに管理ポート番号の設定を追加します。MX4Jはすでにダウンロード済みであることにします。
<Call id="MBeanServer"
class="java.lang.management.ManagementFactory"
name="getPlatformMBeanServer"/>
<Get id="Container" name="container">
<Call name="addEventListener">
<Arg>
<New class="org.mortbay.management.MBeanContainer">
<Arg><Ref id="MBeanServer"/></Arg>
<Set name="managementPort">8082</Set>
<Call name="start" />
</New>
</Arg>
</Call>
</Get>
なお、mx4j-tools.jarはJettyのクラスパス上に配置しておいてください。
MavenのプラグインからJettyを実行する場合は、依存関係にmx4j-toolsを追加してください。
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<jettyConfig>path/to/jetty.xml</jettyConfig>
...
</configuration>
<dependencies>
<dependency>
<groupId>mx4j</groupId>
<artifactId>mx4j-tools</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
</plugin>
この設定でJettyを起動すると、ブラウザで次のURLからJMXConfiguratorにアクセスできるようになります。アクセスした後は "ch.qos.logback.classic" を探してください。
MX4Jにアクセスしているところのスクリーンショットです。
Tomcat用のJMXの設定(JDK 1.5およびJDK 1.6で動作確認済み)
JDK1.6以降のJVMを使用しているならJMXはデフォルトで有効になっているので以降の設定をする必要はありません。JDK1.5の場合は$TOMCAT_HOME/bin/catalina.sh(Windowsの場合はcatalina.bat)の適切な場所に次の設定を追加する必要があります。
CATALINA_OPTS="-Dcom.sun.management.jmxremote"
そうすれば、jconsoleを使ってTomcatの公開するMBeanとしてJMXConfiguratorにアクセスできるようになります。
接続したら、前のスクリーンショットのようにJMXConfiguratorにアクセスできるはずです。
TomcatにMX4Jを入れる(JDK 1.5およびJDK 1.6で動作確認済み)
MX4JのWebインターフェイスを使ってJMXのコンポーネントにアクセスしたくなるかもしれません。そうするために必要な設定方法を説明します。
MX4Jはすでにダウンロードしてあることにしましょう。mx4j-tools.jarを$TOMCAT_HOME/binフォルダーにおいてください。それから、$TOMCAT_HOME/bin/catalina.sh(Windowsの場合はcatalina.bat)の適切な場所に次の設定を追加します。
<!-- at the beginning of the file --> CATALINA_OPTS="-Dcom.sun.management.jmxremote" <!-- in the "Add on extra jar files to CLASSPATH" section --> CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/mx4j-tools.jar
最後に、$TOMCAT_HOME/conf/server.xmlで新しいConnector要素を宣言します。
<Connector port="0" handler.list="mx" mx.enabled="true" mx.httpHost="localhost" mx.httpPort="8082" protocol="AJP/1.3" />
Tomcatを起動したら、ブラウザで次のURLからJMXConfiguratorにアクセスできるようになります。アクセスした後は "ch.qos.logback.classic" を探してください。
MX4Jにアクセスしているところのスクリーンショットです。