まずはJDK1.4でログ出力してみます
java.util.loggingパッケージを使うと、ファイルIOの操作を自前でしなくてもログ出力を実現できます。
- 1.ログを出力するには?
- 2.ログをファイルに書き出すには?
- 3.ファイルの出力書式を読みやすくする
- 4.出力レベルを変更する
- 5.例外のスタックトレースを出力する
- 6.追加モードで出力する
- 7.関連リンク
1. ログを出力するには?
ちょっと長いのですが、以下のソースをご覧ください。この項で使うのはtest1( )メソッドです。
LoggerTester.java |
package ytp.test.logging;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.FileHandler;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* JDK1.4から導入されたログ出力機構をテストするクラスです。
* 単純に画面/ファイルに出力するだけです。
*/
public class LoggerTester {
/**
* ログファイル名です。
*/
public static final String LOGFILE = "LoggerTester.log";
/**
* JDKのロガー(ログ出力クラス)です。
*/
private Logger logger = null;
/**
* デフォルトコンストラクタです。
* 自分のインスタンスをもとにクラス名を取得し、
* そのクラス名によるLoggerオブジェクトを取得します。
*/
public LoggerTester() {
logger = Logger.getLogger(this.getClass().getName());
}
/**
* メインです。
* LoggerTesterインスタンスを生成し、
* 起動パラメータで指定されたメソッドを呼び出します。
*/
public static void main(String[] args) {
LoggerTester test = new LoggerTester();
try {
// 起動パラメータで指定されたメソッドを呼び出す
Method getter = test.getClass().getMethod(args[0], null);
getter.invoke(test, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 画面にのみ出力します。
*/
public void test1() {
// ログを出力する
this.out(logger);
}
/**
* 画面とファイルに出力します。
*/
public void test2() {
try {
// 出力ファイルを指定する
FileHandler fh = new FileHandler(LOGFILE);
logger.addHandler(fh);
} catch (IOException e) {
e.printStackTrace();
}
// ログを出力する
this.out(logger);
}
/**
* 人間が読みやすいフォーマットでファイルに出力します。
*/
public void test3() {
try {
// 出力ファイルを指定する
FileHandler fh = new FileHandler(LOGFILE);
// 出力フォーマットを指定する
fh.setFormatter(new java.util.logging.SimpleFormatter());
logger.addHandler(fh);
} catch (IOException e) {
e.printStackTrace();
}
// ログを出力する
this.out(logger);
}
/**
* 人間が読みやすいフォーマットで、
* さらに出力レベルをCONFIG以上に設定してファイルに出力します。
*/
public void test4() {
try {
// 出力ファイルを指定する
FileHandler fh = new FileHandler(LOGFILE);
// 出力フォーマットを指定する
fh.setFormatter(new java.util.logging.SimpleFormatter());
logger.addHandler(fh);
} catch (IOException e) {
e.printStackTrace();
}
// 出力レベルをCONFIG以上に設定する
logger.setLevel(Level.CONFIG);
// ログを出力する
this.out(logger);
}
/**
* 例外のスタックトレースを出力します。
*/
public void test5() {
try {
// 出力ファイルを指定する
FileHandler fh = new FileHandler(LOGFILE);
// 出力フォーマットを指定する
fh.setFormatter(new java.util.logging.SimpleFormatter());
logger.addHandler(fh);
} catch (IOException e) {
e.printStackTrace();
}
// 出力レベルをCONFIG以上に設定する
logger.setLevel(Level.CONFIG);
try {
makeException();
} catch (NullPointerException e) {
// スタックトレースも出力できます
logger.log(Level.SEVERE, "どうする〜", e);
}
}
/**
* 追加モードでファイルに出力します。
*/
public void test6() {
try {
// 出力ファイルを追加モードで指定する
FileHandler fh = new FileHandler(LOGFILE, true);
// 出力フォーマットを指定する
fh.setFormatter(new java.util.logging.SimpleFormatter());
logger.addHandler(fh);
} catch (IOException e) {
e.printStackTrace();
}
// 出力レベルをCONFIG以上に設定する
logger.setLevel(Level.CONFIG);
// ログを出力する
this.out(logger);
}
private void out(Logger logger) {
logger.log(Level.CONFIG, "デバッグ");
logger.log(Level.INFO, "単なるおまけ");
logger.log(Level.WARNING, "ちょっとまずいんちゃう?");
logger.log(Level.SEVERE, "えらいこっちゃ!!");
}
private void makeException() {
String s = null;
s.toString();
}
}
|
|
|
JDKログ出力機構の中心となるのがjava.util.logging.Loggerクラスです。
上記ソースのうち、基本部分は次のコードです。
Loggerの基本コード |
private Logger logger = null;
logger = Logger.getLogger(this.getClass().getName());
logger.log(Level.SEVERE, "えらいこっちゃ!!");
|
Logger.getLogger( )にて、デフォルトのLoggerオブジェクトを取得できます。
パラメータには、自分のクラス名を渡します。
実際にログを出力するのがlog( )メソッドで、出力レベルとログメッセージをパラメータで渡します。
test1( )を実行すると次のように画面表示されます。
test1( )の実行結果 |
|
C:\Source\Java>java ytp.test.logging.LoggerTester test1
2002/10/20 17:10:11 ytp.test.logging.LoggerTester out
情報: 単なるおまけ
2002/10/20 17:10:12 ytp.test.logging.LoggerTester out
警告: ちょっとまずいんちゃう?
2002/10/20 17:10:12 ytp.test.logging.LoggerTester out
致命的: えらいこっちゃ!!
C:\Source\Java>
|
日付時刻とともに、ログを出力しているクラス名とそのメソッド名が出力され、
それに続けてログのレベルとメッセージが出力されます。
およっ? メッセージの数が一つ足りませんねぇ。
ま、細かいことは気にせず次に行きましょう!!
2. ログをファイルに書き出すには?
画面に出すだけではあまり役に立ちませんよね。やっぱり男はファイルに出力!!
test2( )メソッドをご覧ください。
FileHandlerの指定 |
try {
// 出力ファイルを指定する
FileHandler fh = new FileHandler(LOGFILE);
logger.addHandler(fh);
} catch (IOException e) {
e.printStackTrace();
}
|
というコードが追加されています。
java.util.logging.FileHandlerクラスを使うことでファイルにも出力できるようになります。
この例では、実行ディレクトリのLoggerTester.logというファイルに書き出されます。
実行結果を見てみましょう。
LoggerTester.log |
<?xml version="1.0" encoding="MS932" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2002-10-20T16:36:06</date>
<millis>1035099366972</millis>
<sequence>0</sequence>
<logger>ytp.test.logging.LoggerTester</logger>
<level>INFO</level>
<class>ytp.test.logging.LoggerTester</class>
<method>out</method>
<thread>10</thread>
<message>単なるおまけ</message>
</record>
<record>
<date>2002-10-20T16:36:07</date>
<millis>1035099367102</millis>
<sequence>1</sequence>
<logger>ytp.test.logging.LoggerTester</logger>
<level>WARNING</level>
<class>ytp.test.logging.LoggerTester</class>
<method>out</method>
<thread>10</thread>
<message>ちょっとまずいんちゃう?</message>
</record>
<record>
<date>2002-10-20T16:36:07</date>
<millis>1035099367102</millis>
<sequence>2</sequence>
<logger>ytp.test.logging.LoggerTester</logger>
<level>SEVERE</level>
<class>ytp.test.logging.LoggerTester</class>
<method>out</method>
<thread>10</thread>
<message>えらいこっちゃ!!</message>
</record>
</log>
|
な、な、なんじゃこりゃー! XMLファイルになっとるやんけー!!
これではかえって何が書いてあるかわからんがなー・・・・
3. ファイルの出力書式を読みやすくする
JDKログの標準設定はXMLファイルになっていますが、普通のログ出力に切り替えるにはどうしたらいいのでしょうか?
test3( )メソッドをご覧ください。
SimpleFormatterの利用 |
// 出力フォーマットを指定する
fh.setFormatter(new java.util.logging.SimpleFormatter());
|
というコードが追加されています。
FileHandlerに対してjava.util.logging.SimpleFormatterクラスを設定することで、
画面と同じ書式でファイルに出力できるようになります。
LoggerTester.log |
2002/10/20 16:36:32 ytp.test.logging.LoggerTester out
情報: 単なるおまけ
2002/10/20 16:36:32 ytp.test.logging.LoggerTester out
警告: ちょっとまずいんちゃう?
2002/10/20 16:36:32 ytp.test.logging.LoggerTester out
致命的: えらいこっちゃ!!
|
でも、出力されるログの数がまだ足りませんねぇ・・・・
4. 出力レベルを変更する
先程まで、ファイルに出力されるログが3つだけでした。これは、ログの出力レベルが原因です。
出力レベルというのはそのログの重要度を表すもので、
java.util.logging.Levelクラスで規定されています。
高いものから順に
- SEVERE (最高値)
- WARNING
- INFO
- CONFIG
- FINE
- FINER
- FINEST (最低値)
となっています。
JDKの標準設定ではログの出力レベルがINFOまでになっていて、それより低いものは出力されません。
これを変更する方法は、test4( )メソッドをご覧ください。
出力レベルの変更 |
// 出力レベルをCONFIG以上に設定する
logger.setLevel(Level.CONFIG);
|
というコードが追加されています。
setLevel( )メソッドを使うことで、出力レベルの指定が可能です。
LoggerTester.log |
2002/10/20 16:36:56 ytp.test.logging.LoggerTester out
設定: デバッグ
2002/10/20 16:36:56 ytp.test.logging.LoggerTester out
情報: 単なるおまけ
2002/10/20 16:36:56 ytp.test.logging.LoggerTester out
警告: ちょっとまずいんちゃう?
2002/10/20 16:36:56 ytp.test.logging.LoggerTester out
致命的: えらいこっちゃ!!
|
ただし、これで変更されるのはファイルに対する出力レベルのみで、
画面への出力は変わりません。
5. 例外のスタックトレースを出力する
ログ出力が真価を発揮するのは、例外やエラーの発生時ですよね。
JDKログでも、この時のスタックトレースを書き出すことが当然可能です。
test5( )メソッドをご覧ください。
スタックトレースの出力 |
} catch (NullPointerException e) {
// スタックトレースも出力できます
logger.log(Level.SEVERE, "どうする〜", e);
}
|
というコードが追加されています。
log(Level, Throwable)メソッドを使うことで、
例外やエラーのスタックトレースを出力できます。
LoggerTester.log |
2002/10/20 16:37:28 ytp.test.logging.LoggerTester test5
致命的: どうする〜
java.lang.NullPointerException
at ytp.test.logging.LoggerTester.makeException(LoggerTester.java:144)
at ytp.test.logging.LoggerTester.test5(LoggerTester.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at ytp.test.logging.LoggerTester.main(LoggerTester.java:42)
|
ところがまだ問題が・・・
6. 追加モードで出力する
実は、今まで動かしたプログラムでは、実行するたびにファイルが上書きされてしまい、
過去のログが消えてしまいます。
これでは実用性に欠けるので、追加モードで書き込めるようにしたのがtest6( )メソッドです。
追加モードの設定 |
// 出力ファイルを追加モードで指定する
FileHandler fh = new FileHandler(LOGFILE, true);
|
という部分が変更されています。
2つパラメータのあるFileHandlerのコンストラクタを使い、
2番目のパラメータにtrueを設定することで、
出力ファイルに追加モードで書き込むようになります。test6( )の実行結果が以下です。
LoggerTester.log |
2002/10/21 0:10:08 ytp.test.logging.LoggerTester test5
致命的: どうする〜
java.lang.NullPointerException
at ytp.test.logging.LoggerTester.makeException(LoggerTester.java:165)
at ytp.test.logging.LoggerTester.test5(LoggerTester.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at ytp.test.logging.LoggerTester.main(LoggerTester.java:43)
2002/10/21 0:10:11 ytp.test.logging.LoggerTester out
設定: デバッグ
2002/10/21 0:10:11 ytp.test.logging.LoggerTester out
情報: 単なるおまけ
2002/10/21 0:10:11 ytp.test.logging.LoggerTester out
警告: ちょっとまずいんちゃう?
2002/10/21 0:10:11 ytp.test.logging.LoggerTester out
致命的: えらいこっちゃ!!
|
7.関連するJava2 SDKドキュメント
Loggerクラス
FileHandlerクラス
次はlogging.propertiesの設定です。
|