[Java How To Programming] [Home on 246net] [Home on Alles net]
Powered by SmartDoc

log4jを使う

2010/12/01 GMT
TAKAHASHI,Toru
log4jは、デバッグ情報、エラー情報などをプログラム内からコンソール、ファイル、その他ログサーバ等ヘ出力するオープンソースのロギング・ライブラリです。まだJavaの標準ロギングが作成される以前にCeki Gulcu氏により開発され、広く使われたほか、C++をはじめとする他のプログラミング言語にも移植されています。開発者のGulcu氏はlog4jの開発を離れ、新たにlogbackというライブラリの開発をしていますが、log4jは現在もApacheプロジェクトにおいて保守されています。

目次

概要

入手先

log4jの入手先は次です。バージョン1.2系列の入手

上記ページから、Downloadのリンクを辿り、入手します。

目的

ログ機能は、アプリケーションの性能を低下させたり、ログ出力が膨大になって見えなくなってしまうことがあります。そこで、log4jは、性能を高め、柔軟性を持つように設計されました。また、理解しやすく使いやすいAPIを設けました。

経緯

もともとはIBMのAlphaworksから公開されていたが、開発者のGulcu氏がIBM(チューリッヒ研究所)を離れた後は、オープンソースとなっており、現在Apacheの下でメンテナンスされています。

log4jがIBMから離れたあと、IBMのAlphaworksでは、log4jとは別にThe Logging Toolkit for Java (JLog)というアプリケーション・アプレットのログ用ツールを開発しています。このアーキテクチャはloggers, handlers, filters, and formattersという概念から構成されます。Java2 SE 1.4で搭載するためのロギングAPIの仕様検討がJSR 47で進められましたが、その時点で普及していたlog4jの成果が取り込まれることはなく、独自に仕様化されました。このJSR 47の仕様は、IBMのThe Logging Toolkit for Javaをベースにしているように見えます。

log4jの開発者Gulcu氏は、log4jの開発からフェードアウトし、現在は別なロギングライブラリlogbackの開発に携わっています。

どのロギング・ライブラリを使うべきか

2010年現在、選択肢に上がるよく知られているロギング・ライブラリは次の3つに大別されます。

  1. java.util.logging (java標準ロギングライブラリ)
  2. log4j
  3. logback

機能的には大同小異で、使い方も似ていることから、アプリケーションで必要とするログ機能を備えているか、Java標準のRuntime以外に追加のライブラリを一緒に配布できるか、といった観点で好ましいものをその都度選択すればよいと思います。

なお、ロギングAPIにはJava2 SE 5.0(Tiger)で追加された可変長引数の対応等が望まれるのですが、上記にはいずれも互換性から採用の見込みは少ないようです。

特徴

簡単なAPIで実現され、実行時にログレベルを選択可能。ログ出力先はコンソール、ファイル、GUI、リモートマシンのソケット、NTイベントログ、リモートのUNIX Syslogデーモンなどが提供されています。ログの設定は、APIからも外部の設定ファイルからも可能で、特にログ出力内容の記述を外部の設定ファイルで柔軟にできる点は秀逸です。

使用

設定

ダウンロードしたアーカイブを展開し、中に含まれるjarファイル(log4j-バージョン.jar)を、クラスパスに含めます。

使い方

簡単な使用例

外部の設定ファイルを使わず、BasicConfiguratorクラスを使ったデフォルトのログ出力設定であるコンソール(標準出力)で初期化して使用する例を示します。初期化は、アプリケーションのどこか一箇所(たとえばmainメソッド)で初期化します。

初期化
import org.apache.log4j.BasicConfigurator;

public class Main {
        
    public static void main(String[] args) {
        BasicConfigurator.configure(); // log4jの初期化

        MyApp app = new MyApp(123);
        app.doSomeThing();
        app.end();
    }      
}

ログの出力は以下のようにLoggerクラスを使ってレベルに応じたログ出力メソッドを呼び出します。

ログの出力
import org.apache.log4j.Logger;

public class MyApp  {
    private static Logger logger; // Loggerインスタンスはクラス変数で保持

    public MyApp(int value) {
        logger = Logger.getLogger(MyApp.class);
        logger.debug("MyApp created with value:" + value);
    }    
    void doSomeThing() {
        logger.info("do something");
    }
    void end() {
        logger.error("end");
    }
}

この実行結果は、次のようになります。

ログ出力例
0 [main] DEBUG MyApp - MyApp created with value:123
0 [main] INFO  MyApp - do something
16 [main] ERROR MyApp - end

ログのレベルと対応するLoggerには次の種類があります。

ログのレベル
ログのレベル 代表的な用途
TRACE ループ内でのログ、メソッドのイン・アウト、通過点の記録など
DEBUG バグ原因の切り分けに必要な情報の出力など
INFO 正常系の処理の開始・完了など
WARN 運用に支障のないエラーの記録など
ERROR 運用上対処の必要なエラーの通知など
FATAL 運用が継続できない致命的なエラーの通知など

各ログのレベルに対応するログメソッドがLoggerクラスに用意されています。

引数を見ると、出力するメッセージはObject型なら何でもよく、引数に指定したオブジェクトのtoString()メソッドが返す文字列がログに出力されます。また、エラー時のログでは例外オブジェクトをログ出力できるよう引数にThrowableが指定できるオーバーロード版メソッドも用意されています。

初期化方法

初期化方法は、先に紹介したBasicConfiguratorを含め、大きくは3つ存在します。

ログの初期化方法
No 方法 内容
1 BasicConfigurator 出力先(Appender)を1つ使用する。デフォルト出力先はコンソール
2 PropertyConfigurator Javaプロパティ形式のテキストファイルに記述した内容で初期化する。
3 DOMConfigurator XML形式のテキストファイルに記述した内容で初期化する。

また、これ以外にJavadocを見ると、ReloadingPropertyConfiguratorやDefaultLF5Configuratorなるものがあります。

PropertyConfiguratorの設定例

Javaプロパティ形式のテキストファイルに設定を記述し、それを実行時に読み込みログの設定を行います。

PropertyConfiguratorの初期化
import org.apache.log4j.PropertyConfigurator;

public class Main {
    public static void main(String[] args) {
        String filePath = args[0];
        PropertyConfigurator.configure(filePath);
        // ...
    }
    // ...
}
設定ファイルの記述例
log4j.rootLogger = INFO, stdout, file

log4j.appender.stdout = org.apache.log4j.ConsoleHandler
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %C %M%n %p %m%n

log4j.appender.file = org.apache.log4j.FileAppender
log4j.appender.file.File = C:\\temp\\myapp.log
log4j.appender.file.encoding = UTF-8
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %C %M%n %p %m%n

rootLoggerでは、ログ階層の最上位での優先度、アペンダーの指定をします。ここでは、優先度はINFO以上、"stdout"および"file"という名の2つのアペンダーを設定しています。アペンダーは続いて定義しています。

stdoutアペンダーは、ConsoleHandlerで、ログ出力文のフォーマットにはPatternLayoutを使用し、そのレイアウトは、%d %C %M%n %p %m%nを指定しています。

fileアペンダーは、FileHandlerで、ログ出力先ファイル名にC:\temp\myapp.logを指定し、エンコーディングにUTF-8を指定しています。レイアウトについてはstdoutと同様です。

アペンダーには、ほかにも一定サイズ毎にログローテーションするRollingFileAppender、日々でログローテーションするDailyRollingFileAppender、OSのログに出力するNTEventLogAppender、SyslogAppender、メールに出すSMTPAppender、ネットワークに出すSocketAppender、SocketHubAppender、TelnetAppender、その他があります。

実行中のログレベルの変更

Java標準ログは、プログラムの実行中にJMX経由でログレベルを変更することができます。(JDK付属のJConsoleツールを使うと簡単に確認できます)

log4jにも、これに類することができるHierarchyDynamicMBeanが用意されています。使用するには、ログ初期化時に、MBeanServerに登録します。

JMX用の初期化コード
import java.lang.management.ManagementFactory;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.OperationsException;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.jmx.HierarchyDynamicMBean;

public class Main {
    public static void main(String[] args) 
            throws OperationsException, MBeanRegistrationException {
        PropertyConfigurator.configure(args[0]);
        HierarchyDynamicMBean dynamicMBean = new HierarchyDynamicMBean();
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        ObjectName dynamicMBeanName = new ObjectName("log4j:type=HierarchyDynamicMBean");
        server.registerMBean(dynamicMBean, dynamicMBeanName);
        // ...
    }
    // ...
}