連載
» 2008年01月08日 00時00分 公開

プログラマーの常識をJavaで身につける(10):入門から実践までJavaで学べる「ログ」の常識 (2/4)

[伊賀敏樹,株式会社 NTTデータ ビジネスブレインズ]

【入門1】はじめてのロギング

 まずは、java.util.loggingパッケージを使ったロギングを体験してみましょう。最も原始的なjava.util.loggingの利用例は下記のようになります。

SampleLogging1.java(最も原始的なjava.util.logingパッケージを使ったロギングの例)
import java.util.logging.Logger;

public class SampleLogging1 {
    public static void main(final String[] args) {
        final Logger logger = Logger.getLogger("SampleLogging");
        logger.info("隣の客は良く柿食う客だ。");
    }
}

 ソースコードを細かく見ていきましょう。

        final Logger logger = Logger.getLogger("SampleLogging");

 SampleLoggingという名前付きサブシステムのロガー(ログを出力するクラスのインスタンス)を取得します(ロガーには何か名前を付ける必要があります。ロガーに与える名前として、伝統的にFQCN(完全修飾クラス名)を利用することが多いです)。

        logger.info("隣の客は良く柿食う客だ。");

 ロガーに対して「INFOレベルでログメッセージを出力します(ログのレベルについては後述します)。

 このプログラムを実行すると、(Java実行環境インストールのデフォルト状態では)標準エラー出力に下記のようなメッセージが出力されます(ここでは、Eclipseのコンソールを例に取っています。標準エラー出力なので、赤色でメッセージが表示されています)。

図4 Eclipseコンソールへの標準エラー出力の表示例 図4 Eclipseコンソールへの標準エラー出力の表示例

 なお、ここで示した例では、ログファイルにはロギングされていません。ここでは、標準エラー出力のみにログ内容が出力されているにすぎないのです。

「ログレベル」って何?

 前の例では、ロギングのために何げなくinfoメソッドを呼び出していました。実は、このメソッドは「ログレベル」と関連付けられています。

 ログレベルは、文字通りログ出力制御のレベルを指定するために利用されます。ログ出力の際には、指定されたレベルによってフィルターが掛かる(指定されたレベルより下のログが出力されない)ような仕組みになっています。

 java.util.loggingパッケージでは、標準ログレベルのセットがjava.util.logging.Levelクラスで定義されています。ログレベルと対応するjava.util.logging.Loggerクラスの簡易メソッド、そしてそれぞれの意味は下記のような対応付けになっています。

表1 ログレベルの種類(※レベルを昇順で並べています)
Levelクラスの定数 対応するLoggerクラスの簡易メソッド名
(intValue)
日本語地域での文字列名 補足説明
Level.FINEST finest 300 詳細レベル(高)  
Level.FINER finer 400 詳細レベル(中) entering
exiting
throwing
はFINERレベルでロギングされる
Level.FINE fine 500 詳細レベル(小)  
Level.CONFIG config 700 設定  
Level.INFO info 800 情報  
Level.WARNING warning 900 警告  
Level.SEVERE severe 1000 致命的  

【入門2】info以外のメソッドも使うには?

 それでは、info以外のメソッドを使ってみます。先ほどのログレベルの表で出てきたメソッドをすべて呼び出してみます。

SampleLogging2.java
import java.util.logging.Logger;

public class SampleLogging2 {
    public static void main(final String[] args) {
        final Logger logger = Logger.getLogger("SampleLogging");
        logger.finest("隣の客はよく柿食う客だ。");
        logger.finer("東京都特許許可局。");
        logger.fine("かえるぴょこぴょこ。");
        logger.config("庭には二羽鶏が。");
        logger.info("生麦生米生卵。");
        logger.warning("あかまきがみ。");
        logger.severe("すもももももももものうち。");
    }
}

 ところが、標準エラー出力にはinfo、warning、severeの3メソッドで呼び出したログ内容しか出力されないことが分かります。

実行結果(コンソール出力)

2007/11/26 14:41:49 SampleLogging2 main

情報: 生麦生米生卵。

2007/11/26 14:41:49 SampleLogging2 main

警告: あかまきがみ。

2007/11/26 14:41:49 SampleLogging2 main

致命的: すもももももももものうち。


 なぜなのでしょう? Java実行環境はデフォルト状態ではINFOレベルより下のレベルのログは出力されないようになっているからなのです。

はじめての「LogManager 構成プロパティ」の設定

 info、warning、severeの3メソッド以外で呼び出した際のログ出力も標準エラー出力に出てくるようにしたいのですが、それに先立ち、「LogManager 構成プロパティ」の設定を行います。java.util.loggingは、「LogManager 構成プロパティ」というものの設定に従って動作するようになっています。ここでは、最も単純な「LogManager 構成プロパティ」の設定方法を見ていきます。

 最も単純な設定方法は、プログラム内部から設定内容を与えてしまう方法です。環境など外部の影響を受けないので、最も簡単で確実に設定変更を与えることができます。

 まずは、Java実行環境のデフォルト状態に相当する設定内容を読み込む例を示します。

SampleLogging3.java
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class SampleLogging3 {
    /**
    * ログ設定プロパティファイルのファイル内容
    */
    protected static final String LOGGING_PROPERTIES_DATA
        = "handlers=java.util.logging.ConsoleHandler\n"
        + ".level=INFO\n"
        + "java.util.logging.ConsoleHandler.level=INFO\n"
        + "java.util.logging.ConsoleHandler.formatter"
        + "=java.util.logging.SimpleFormatter";

    /**
    * static initializer によるログ設定の初期化
    */
    static {
        final Logger logger = Logger.getLogger("SampleLogging");
        InputStream inStream = null;
        try {
            inStream = new ByteArrayInputStream(
                LOGGING_PROPERTIES_DATA.getBytes("UTF-8"));
            try {
                LogManager.getLogManager().readConfiguration(
                    inStream);
                logger.config(
                    "ログ設定: LogManagerを設定しました。");
            } catch (IOException e) {
                logger.warning("ログ設定: LogManager設定の際に"
                    + "例外が発生しました。:" + e.toString());
            }
        } catch (UnsupportedEncodingException e) {
            logger.severe("ログ設定: UTF-8エンコーディングが"
                + "サポートされていません。:" + e.toString());
        } finally {
            try {
                if (inStream != null) inStream.close();
            } catch (IOException e) {
                logger.warning(
                    "ログ設定: ログ設定プロパティファイルのスト"
                    + "リームクローズ時に例外が発生しました。:"
                    + e.toString());
            }
        }
    }
    public static void main(final String[] args) {
        final Logger logger = Logger.getLogger("SampleLogging");

        logger.finest("隣の客はよく柿食う客だ。");
        logger.finer("東京都特許許可局。");
        logger.fine("かえるぴょこぴょこ。");
        logger.config("庭には二羽鶏が。");
        logger.info("生麦生米生卵。");
        logger.warning("あかまきがみ。");
        logger.severe("すもももももももものうち。");
    }
}

 これを実行すると、標準エラー出力に下記のように表示されます。

実行結果(コンソール出力)

2007/11/26 15:00:53 SampleLogging3 main

情報: 生麦生米生卵。

2007/11/26 15:00:53 SampleLogging3 main

警告: あかまきがみ。

2007/11/26 15:00:53 SampleLogging3 main

致命的: すもももももももものうち。


 ここで、ソースコードを一部説明していきます。

 下記の個所は、java.util.loggingの設定情報をプロパティファイル形式で与える(「LogManager 構成プロパティ」)ための定数です。このプロパティファイル自体は、構成ファイルとも呼ばれます。

    protected static final String LOGGING_PROPERTIES_DATA

 構成ファイルの内容をLOGGING_PROPERTIES_DATA定数にセットします。

        = "handlers=java.util.logging.ConsoleHandler\n"

 ハンドラとして、java.util.logging.ConsoleHandlerクラスを設定しています。

        + ".level=INFO\n"

 フィルターする最低レベルをINFOに設定しています。

        + "java.util.logging.ConsoleHandler.level=INFO\n"

 ConsoleHandlerのフィルターするレベルを INFOに設定しています。

        + "java.util.logging.ConsoleHandler.formatter"
        + "=java.util.logging.SimpleFormatter";

 ConsoleHandlerのフォーマッタをjava.util.logging.SimpleFormatterクラスに設定しています。

        LogManager.getLogManager().readConfiguration(inStream);

 この個所では、先ほどの設定をjava.util.logging.LogManagerクラスのオブジェクトに与えています。設定された内容は「LogManager 構成プロパティ」と呼ばれます。なお、この設定変更はプログラムが動作しているJava VMプロセスそのものにも影響を与える点に注目してください。

        final Logger logger = Logger.getLogger("SampleLogging");

 ここで、ロガーオブジェクトを取得します。readConfigrationメソッドによって設定変更がされた後のロガーオブジェクトが取得されます。

 続いて次ページでは、ログの設定についてさらに解説します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。