Java™ Logging API 入門

2008年01月29日

Logging API とは

Java™ Logging API (JSP 47) は Java2 SE 1.4 から標準機能となったログ出力用の API です。プログラムにログを仕込み、設定ファイルで出力先や書式を一括変更できるという一般的に想定されるロギングはこれでまかなうことができます。

しかし、標準構成の機能だけでは少人数開発で使える程度と言うのが実際のところです。チーム開発や運用要件などを考慮しなければならない大規模開発ではいくつかの Foundation なコードを追加で作らなければならないため Log4j に比べて不便さは否めません。

具体的には:

  • 出力フォーマットを変更したい場合、追加の Formatter クラスを作成しなければならない。このクラスは膨大な呼び出し回数をこなすため実装のパフォーマンスに神経質になる必要がある。
  • パッケージ単位などで出力ファイルを分けることは可能だが、標準の設定ファイルでは記述不可能。そう構成する処理のコード上で記述しなければならない。
  • 日付や時刻でログファイルをローリングする場合、追加の Handler クラスを作成しなければならない。これも Formatter と同様に膨大な呼び出しをこなすクラスである。
  • 担当ごとに設定をいくつかのファイルに分散して累積的に読み込めない。 1 つのファイルを読むと以前の状態がリセットされるため、全てを 1 ファイルに記述する必要がある。

などが挙げられます。

冒頭いきなり問題点から入ってしまいましたが、大規模開発ならフレームワーク担当者に任せておけば良いですし、ちょっとしたアプレットやツールなどで使用する分には十分でもあります。

一般的な使い方

プログラム内で Logging API を使用するには一般的に以下のように記述します。

import java.util.logging.*;

public class MyClass{

    // このクラスのログ出力先を取得。
    private static final Logger logger
        = Logger.getLogger(MyClass.class.getName());

    public void greeting(){
        logger.info("hello, world");  // ログ出力
        // ...
    }
}
実行結果
2008/01/30 16:13:11 MyClass greeting
情報: hello, world

まず各クラスで private static final 宣言した LoggerJava™ API リファレンス のクラス変数を作成し、後はそのクラスのメソッドなどで logger にログを出力します。

Logger#getLogger()Java™ API リファレンス に渡す名前はログの出力先やレベルを変更する時に使用します。この例のようにクラス名を指定した場合、後でパッケージやクラス単位での設定変更ができるようになります。クラスのデバッグではなくアクセスログや認証ログのような目的で使用する場合は別途適切な名前をつけてください。

ログ出力には以下の簡易メソッドが用意されています。これら以外にも log()logp() を使用して例外を出力したり、リソース名とパラメータを指定して Formatter で地域化されたメッセージを取得することもできます。

LevelJava™ API リファレンス LoggerJava™ API リファレンス 意味 デフォルト
(ConsoleHandler)
SEVERE severe() エラー 出力
WARNING warning() 警告 出力
INFO info() 一般情報 出力
CONFIG config() 環境構成
FINE fine() デバッグ
FINER finer()
entering()
exiting()
throwing()
デバッグ
(詳細)
FINEST finest() デバッグ
(トレース)

以前は System.out.println() に代わる簡易的な方法として Logger.globalJava™ API リファレンス という public なオブジェクトを使用するとしていましたが、これは Java SE 6 で推奨されなくなりました。振り替え手段として Logger.getLogger(Logger.GLOBAL_LOGGER_NAME) が用意されていますが、ここまで書くならクラス名で行った方が良いのは言うまでもありません。

簡単な設定ファイルの記述

コード上でログを使用しただけではコンソール (標準エラー) に出るだけで面白くありません。今度は設定ファイルでログファイルに出力するよう構成します。以下のようなプロパティファイルを作成して mylog.properties という名前で保存してください。

handlers = java.util.logging.FileHandler
java.util.logging.FileHandler.pattern = %h/mylogfile.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
.level = FINE

上記の例はすべてのログを FINE レベルで ${user.home}/mylogfile.log に出力します。

このファイルを Java 起動時のシステムプロパティ java.util.logging.config.file に指定します。

java -Djava.util.logging.config.file=mylog.properties MyClass

またはプログラムの一番最初 (サーブレットなら ServletListener など) で直接この設定ファイルを読み込ませることもできます。

String fileName = "mylog.properties";
InputStream in = new FileInputStream(fileName);
LogManager.getLogManager().readConfiguration(in);
in.close();

その他、クラスファイルと同じディレクトリに保存しておいてリソースとして読み込ませる事もできます。設定ファイルの置き場所に依存しないため、JAR ファイルにまとめて配布するならこちらが便利です。

String path = MyClass.class.getName();
path = "/" + path.replace('.', '/') + "/../mylog.properties";
InputStream in = MyClass.class.getResourceAsStream(path);
LogManager.getLogManager().readConfiguration(in);
in.close();

なお、{$JRE_HOME}/lib/logging.properties で設定を行えば何もしなくても自動的に読み込んでくれますが、同じ JRE を使用するすべての Java プログラムが同じ設定になってしまうためあまりお勧めできません。もし必要なら 後述のようにロガー名を限定して影響範囲を少なくしてください。

CVS 2008/02/28