JBoss AS7のロギング事情
JBoss Advent Calendar 2012の3日目のエントリです。
ログというのはディスクなどのハードウェアリソースを使うものなので、基本的にデータベースコネクションやスレッド数などと同じように、ミドルウェアリソースに位置づけられ、アプリケーションサーバで一括管理できるようになっています。
と言いたいところですが、現実的にはLog4j, commons-logging, JUL(java.util.logging), SLF4J, Logbackなどログライブラリは乱立しており、各アプリでは異なるログライブラリが利用され、ログ出力設定もバラバラになされていて実際には一元管理するのはすごく大変でカオスな状態です。
JBoss ASは6までLog4jをログ実装として利用していましたが、AS7ではJBoss LogManagerというJULをベースとした実装に変更されました。これに伴い、どのメジャーなログインタフェースを利用してもJBoss LogManagerに出力されるようになったので、AS7からはモジュール化の恩恵もあり、キレイに一元管理できるようになりました。めでたし。
実際にどのようになっているか確かめてみましょう。(ひどいコードですが)とりあえず以下のようなJSPを作ってwarにしてデプロイします。
<p><%= java.util.logging.Logger.getLogger("foo") %></p> <p><%= java.util.logging.Logger.getLogger("foo").getClass() %></p> <p><%= java.util.logging.Logger.getLogger("foo").getClass().getClassLoader() %></p> <p><%= org.apache.log4j.Logger.getLogger("foo") %></p> <p><%= org.apache.log4j.Logger.getLogger("foo").getClass() %></p> <p><%= org.apache.log4j.Logger.getLogger("foo").getClass().getClassLoader() %></p> <p><%= org.slf4j.LoggerFactory.getLogger("foo") %></p> <p><%= org.slf4j.LoggerFactory.getLogger("foo").getClass() %></p> <p><%= org.slf4j.LoggerFactory.getLogger("foo").getClass().getClassLoader() %></p> <p><%= org.apache.commons.logging.LogFactory.getLog("foo") %></p> <p><%= org.apache.commons.logging.LogFactory.getLog("foo").getClass() %></p> <p><%= org.apache.commons.logging.LogFactory.getLog("foo").getClass().getClassLoader() %></p>
結果はこうなります。特にロギングライブラリをwarに入れてないのに全て自動的に利用可能になっています。逆に、ロギングライブラリをwarとかに入れてもさっくり無視されます(どうしても、という場合はごちゃごちゃ設定すればできますけど一元管理を破壊します)。
Logger 'foo' in context org.jboss.logmanager.LogContext@47cbe5dc class org.jboss.logmanager.Logger ModuleClassLoader for Module "org.jboss.logmanager:main" from local module loader @2b20bf2c (roots: /home/nekop/eap600/modules) org.apache.log4j.Logger@782be176 class org.apache.log4j.Logger ModuleClassLoader for Module "org.jboss.log4j.logmanager:main" from local module loader @2b20bf2c (roots: /home/nekop/eap600/modules) org.slf4j.impl.Slf4jLogger(foo) class org.slf4j.impl.Slf4jLogger ModuleClassLoader for Module "org.slf4j.impl:main" from local module loader @2b20bf2c (roots: /home/nekop/eap600/modules) org.apache.commons.logging.impl.SLF4JLocationAwareLog@253be03d class org.apache.commons.logging.impl.SLF4JLocationAwareLog ModuleClassLoader for Module "org.slf4j.jcl-over-slf4j:main" from local module loader @2b20bf2c (roots: /home/nekop/eap600/modules)
JULはJBoss LogManagerの実装クラスが返却されています。Log4jはlog4j-jboss-logmanager、SLF4Jはslf4j-jboss-logmanagerにそれぞれ経由されてJBoss LogManagerに。Commons LoggingはSLF4J添付されてるブリッジでSLF4Jにリダイレクトされるので、SLF4Jと同じパスを辿ります。LogbackはログインタフェースとしてSLF4Jが使われ、直接使われることは基本的にないのでここには出てきません。
こうしてAS7ではログインタフェースへの出力は全てJBoss LogManagerに集約され、ログ出力の制御が一元化できるようになっています。