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 宣言した
Logger
のクラス変数を作成し、後はそのクラスのメソッドなどで logger にログを出力
します。
Logger#getLogger()
に渡す名前はログの出力先やレベルを変更する時に使用します。この例のようにクラス名を
指定した場合、後でパッケージやクラス単位での設定変更ができるようになります。
クラスのデバッグではなくアクセスログや認証ログのような目的で使用する場合は
別途適切な名前をつけてください。
ログ出力には以下の簡易メソッドが用意されています。これら以外にも log()
や logp() を使用して例外を出力したり、リソース名とパラメータを指定して
Formatter で地域化されたメッセージを取得することもできます。
Level
|
Logger
|
意味 |
デフォルト
(ConsoleHandler) |
SEVERE |
severe() |
エラー |
出力 |
WARNING |
warning() |
警告 |
出力 |
INFO |
info() |
一般情報 |
出力 |
CONFIG |
config() |
環境構成 |
- |
FINE |
fine() |
デバッグ |
- |
FINER |
finer() entering() exiting() throwing() |
デバッグ (詳細) |
- |
FINEST |
finest() |
デバッグ (トレース) |
- |
以前は System.out.println() に代わる簡易的な方法として
Logger.global
という 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 プログラムが
同じ設定になってしまうためあまりお勧めできません。もし必要なら
後述のようにロガー名を限定して影響範囲を少なく
してください。