java.util.logging

java.util.loggingのみを利用してJavaAPI標準のログ機能を確認しましょう。

java.util.logging概要

java.util.logging概要

ログの出力までに最低4種類のクラスが提供されています。1つ1つ主な役割について説明します。

クラス名 必要数 説明
Logger ログ対象のクラス1つに対して
1つのインスタンス
ログを出力するための主クラス
Loggerのインスタンスに対して、ログレベルの指定、メッセージの引渡し
最低1つ以上のHandlerオブジェクトに出力依頼を保持し、出力処理を委譲する。
LogRecord 0~1 ログ情報(ログレベル、ログメッセージ、引数オブジェクトなど)を管理するモデルオブジェクト
Loggerの各種メソッドでログ情報をLogRecode無しで引き数引渡しで設定できます。
LogRecordインスタンスにログ情報を設定してLoggerに引き渡す方法もあります。
LoggerはLogRecordインスタンスを保持しているHandlerクラスに引き渡します。
Handler 1~N ログの出力先やフォーマットを決定するクラス
Handlerそれぞれに個別の役割を与え、Loggerインスタンスに設定します。
Loggerのログ出力メソッドが実行されると設定されているHandlerが実行され、
LoggerのインスタンスがHandlerのインスタンスに処理を委譲します。
Filter 0~1 Loggger、Handlerに対して0~1設定できます。
ログの出力可否やLogRecodeのインスタンスの判定を行います。
図中HandlerがFilterを2つ指しているのは切替している例です。

実際にそれぞれつかっていきましょう。

名前空間

名前空間

java.util.loggingパッケージに関わらずJavaのオープンソースのログにも適用される基本機能です。
Loggerのインスタンスをパッケージ階層で管理します。実際には、パッケージ階層以外の階層構造の名前を付与できますが、
パッケージ階層を付与するのが各ログライブラリで推奨されています。

上記図の例では、「ルートロガー」という全体のパッケージを管理する親のロガーがあります。
その他にロガーの指定がなければ、同一パッケージ階層以下全てにルートロガーが適用されます。

そして、大規模システムで良く見受けられるのが、セキュリティやお金、個人情報操作などに関する他の情報処理より
管理が重要なサービスやデータアクセスでは、それぞれのロガーを用意します。
上記例は「bill(請求サブシステム)」を親ロガーと異なる動きをさせたいため名前空間を新しく定義しています。

名前空間は、ロガーインスタンスの継承関係に似たログの属性の引継ぎが行われます。
ルートロガーがの設定が名前空間の階層配下の子ロガーに適用され、子ロガーで明示された属性は、子ロガーの性質が適用されます。

デフォルトで動かすサンプル

前置きが長くなりましたが、まずは、デフォルトの設定でシンプルなログを実行してみましょう。

JavaAPILogDefaultSample.java

package jp.co.yourcompany.education.log;

import java.util.logging.Filter;
import java.util.logging.Handler;
import java.util.logging.Logger;;

/**
 * java.util.loggingAPIを利用して、
 * デフォルトのログの出力状況を確認するクラス
 * @author raita.kuwabara
 */
public class JavaAPILogDefaultSample {

    /**
     * ロガーインスタンスの生成
     * このようにロガーは、クラスメンバーフィールド(static)で定義します。
     */
    public static final Logger log = Logger.getLogger( JavaAPILogDefaultSample.class.getName() );

    /**
     * ログ出力サンプルを全て実行する。
     */
    public void execAllSamples(){

        outputLoggerInfo();

        logSevere();
        logWarning();
        logInfo();
        logConfig();
        logFine();
        logFiner();
        logFinest();

    }

    /**
     * ログの出力レベル:SERVEREの確認
     */
    private void logSevere(){
        System.out.println("logSevere START ");
        log.severe("LOGLEVEL:SERVERE");
        System.out.println("logSevere END ");
    }

    /**
     * ログの出力レベル:WARNINGの確認
     */
    private void logWarning(){
        System.out.println("logWarning START ");
        log.warning("LOGLEVEL:WARNING");
        System.out.println("logWarning END ");
    }

    /**
     * ログの出力レベル:INFOの確認
     */
    private void logInfo(){
        System.out.println("logInfo START ");
        log.info("LOGLEVEL:INFO");
        System.out.println("logInfo END ");
    }

    /**
     * ログの出力レベル:CONFIGの確認
     */
    private void logConfig(){
        System.out.println("logConfig START ");
        log.config("LOGLEVEL:CONFIG");
        System.out.println("logConfig END ");
    }

    /**
     * ログの出力レベル:FINEの確認
     */
    private void logFine(){
        System.out.println("logFine START ");
        log.fine("LOGLEVEL:FINE");
        System.out.println("logFine END ");
    }

    /**
     * ログの出力レベル:FINERの確認
     */
    private void logFiner(){
        System.out.println("logFiner START ");
        log.finer("LOGLEVEL:FINER");
        System.out.println("logFiner END ");
    }

    /**
     * ログの出力レベル:FINESTの確認
     */
    private void logFinest(){
        System.out.println("logFinest START ");
        log.finest("LOGLEVEL:FINEST");
        System.out.println("logFinest END ");
    }

    /**
     * デフォルト設定を出力する
     */
    private void outputLoggerInfo(){

        String logName= log.getName();
        Logger logger = log;
        do{
            System.out.println("----------------START LOG INSTANCE------------------------");
            System.out.println("logger.getName():" + logger.getName());
            System.out.println("logger.getResouceBundleName():" +logger.getResourceBundleName());

            Handler[] handlers = logger.getHandlers();
            if( handlers == null){
                System.out.println("logger.getHandlers:null");
            } else {
                System.out.println("logger.getHandlers:notnull size is" + handlers.length);
                for( int i = 0 ; i <  handlers.length ; i++){
                    System.out.println("logger.handler.formatter.toString():" +  handlers[i].getFormatter().toString());
                    System.out.println("logger.handler.formatter.getName():" +  handlers[i].getLevel().getName());
                }
            }

            Filter filter = log.getFilter();
            if( filter == null){
                System.out.println("logger.getFilter is null");
            } else {
                System.out.println("loggger.getFilter is not null ");
            }
            logName = logger.getName();
            logger = log.getParent();
            System.out.println("----------------END LOG INSTANCE------------------------");
        }while ( logName.length() != 0);
    }

    /**
     * javaコマンドから実行されるmainメソッド
     */
    public static final void main( String[] args ) {
        JavaAPILogDefaultSample sample = new JavaAPILogDefaultSample();
        sample.execAllSamples();
    }
}

						
実行結果
----------------START LOG INSTANCE------------------------
logger.getName():jp.co.yourcompany.education.log.JavaAPILogDefaultSample
logger.getResouceBundleName():null
logger.getHandlers:notnull size is0
logger.getFilter is null
----------------END LOG INSTANCE------------------------
----------------START LOG INSTANCE------------------------
logger.getName():
logger.getResouceBundleName():null
logger.getHandlers:notnull size is1
logger.handler.formatter.toString():java.util.logging.SimpleFormatter@33909752
logger.handler.formatter.getName():INFO
logger.getFilter is null
----------------END LOG INSTANCE------------------------
logSevere START
logSevere END
logWarning START
3 13, 2017 3:43:29 午後 jp.co.yourcompany.education.log.JavaAPILogDefaultSample logSevere
重大: LOGLEVEL:SERVERE
3 13, 2017 3:43:29 午後 jp.co.yourcompany.education.log.JavaAPILogDefaultSample logWarning
警告: LOGLEVEL:WARNING
logWarning END
logInfo START
3 13, 2017 3:43:29 午後 jp.co.yourcompany.education.log.JavaAPILogDefaultSample logInfo
情報: LOGLEVEL:INFO
logInfo END
logConfig START
logConfig END
logFine START
logFine END
logFiner START
logFiner END
logFinest START
logFinest END
						

実行結果からデフォルトの設定におけるjava.util.loggingについて以下の事が分かります。

  1. デフォルトのLoggerにHandlerは0個
  2. 親のLogger(getName.length=0)のHandlerがデフォルトで1つ設定されている。
  3. Handlerは、ログを出力する役割なので、子ロガーにHandlerが未設定の場合には、ルートロガーまでに設定されたHandlerが利用される
  4. HandlerにFomatterクラスが設定されている。
  5. Filterは子ロガー、親ロガー共にデフォルトでnull
  6. LogLevelのデフォルトは、「INFO」
  7. フォーマットは「%td %tm %tY %tl:%tM:%tS %tp %Sクラス名 %Sメッセージ」
  8. フォーマットのバンドルで「日本語」が選択されいている。
  9. 重要ログメッセージの出力は非同期(メソッドの実行順に出力されていない事から)

次の頁では、デフォルトの設定ファイルの確認とサンプルアプリ用に色々と設定ファイルを試して実行しましょう。