Home of: [工房 "藤車"] > [SourceForge.net における PTLog]

クライアントコードの記述

本節では、 ログ要求を発行するクライアントコードの記述方法を説明します。

デモンストレーション実装のbasic.client パッケージに属するクラス群も参照してください。

概要

クラス名

本チュートリアルでは、 クラスは全てクラス名のみで表記されています。 完全な名称は以下の通りです。

PTLog のクラス

表記 完全名
Log jp.ne.dti.lares.foozy.ptlog.Log
LogBuffer jp.ne.dti.lares.foozy.ptlog.LogBuffer
LogTap jp.ne.dti.lares.foozy.ptlog.LogTap
WriterProvider jp.ne.dti.lares.foozy.ptlog.writer.WriterProvider

LogTap の生成

利便性の上から、 はじめに LogTap を生成する必要があります。


public class Client
{
    ....

    final static
    public LogTap TAP =
    new LogTap(Client.class, WriterProvider.STDOUT);
}

LogTap の生成

LogTap は JDK ログ API(ないし Apache Log4j)における Logger とほぼ同等のものです。

コンストラクタパラメータの前者は、 ログ要求の「主体(subject)」を意味します。 これはログ要求の発行者を識別するために使用されます。

後者のパラメータは、 基礎となるログフレームワークを指定します。 この例における "WriterProvider.STDOUT" の場合は、 初期状態ではログ要求が標準出力に書き出されることを意味します。

後者のパラメータに関する詳細は "ログフレームワークへの接続" をご覧ください。

Log 経由での要求発行

以上で、 LogTap から取得した Log 経由でログ要求を発行できます。 例えば:


    public void doSomething(){
        Log log = TAP.getLog("doSomething");

        log.info("INFO 型によるログ");
        log.dump("DUMP 型によるログ");

        try{
            ....
            ....
        }
        catch(Exception e){
            log.error("ERROR 型によるログ", e);
        }
    }

Log 経由での要求発行

LogTap#getLog() のパラメータは、 ログ要求の発行元となるメソッドの名前です。

Log は、 ログ要求を受け付ける幾つかの「型(type)」を持っています。

対応する level/method
JDK logging API Apache Log4j JCL(*1)
fatal SEVERE(1000) FATAL(50000) fatal
error SEVERE(1000) ERROR(40000) error
warn WARNING(900) WARN(30000) warn
info INFO(800) INFO(20000) info
config CONFIG(700) INFO(20000) info
dump FINE(500) DEBUG(10000) debug
trace FINER(400) TRACE(5000)(*2) trace(*3)
---(*4) FINEST(300) --- ---

(*1) は、このチュートリアルにおいて "Jakarta Common Loggings" の略称として使用されます。

(*2) は、Log4j 1.2.12 からサポートされています。

(*3) は、 JCL 1.0.x では、"DEBUG" (Log4j 環境)ないし "FINEST"(JDK Logging API 環境)を使用しています。

(*4) に対応する出力は、型変換により可能になります。


Log クラスは、 各「型」ごとに3つのシグネチャバリエーションを持っています。


    public void <type>(String message, Throwable throwable);

    public void <type>(Object data);

    public boolean enables<Type>();

シグネチャバリエーション

最初の形式は、 他のログフレームワーク(例えば JDK logging API、Log4j ないし JCL) と同様の一般的なものです。 message および(ないし) throwable には、 "null" を指定しても構いません。

2つ目の形式は、 Throwable を含む任意のデータのログ要求の際に使用されます。 StringThrowable のいずれかのみを記録したい場合に有用です。

3つ目の形式は、 指定した「型」のログ要求の可否を判定するのに使用されます。 例えば:


    public void doSomething(){
        Log log = TAP.getLog("doSomething");

        if(log.enablesDump()){
            log.dump("DUMP 型によるログ");
        }
    }

"型" の確認

"log.enablesDump()" 条件下のブロックは、 "dump" によるログが可能である場合にのみ実行されます。 このような条件は、実行中に動的に変化する可能性があります。

このような確認は、 常に情報収集を実施することが非常に高価である場合に有用です。

"trace" 型には、 これらに加えて3つの追加バリエーションがあります。


    public void doSomething(){
        Log log = TAP.getLog("doSomething");
        log.enter(); // メソッド開始を意味します

        ....
        log.pass("initialize phase - 1");
        ....
        log.pass("initialize phase - 2");
        ....
        log.pass("initialize phase - 3");
        ....
        ....

        log.exit(); // メソッド終了を意味します
    }

"trace" のためのユーティリティメソッド

上記例におけるそれぞれのメソッドは "Log#trace" メソッドで置き換え可能ですが、 これらのメソッドは "trace" ログの統一された要求(およびフォーマット) 方式を提供します。

それに、メソッド起動コードが短いのは重要ですよね?

LogBuffer 経由での要求発行

経験上、 パラメータの出力はログの主要な目的の一つであり、 ログ要求には2つのスタイルがあります。

1つ目は「結合」スタイルです。


    public void doSomething(int p1, int p2, int p3, ....){
        Log log = TAP.getLog("doSomething");
        log.dump("p1=" + p1 +
                 "/p2=" + p2 +
                 "/p3=" + p3 +
                 .....);
    }

「結合」スタイル

もう1つは「分離」スタイルです。


    public void doSomething(int p1, int p2, int p3, ....){
        Log log = TAP.getLog("doSomething");
        log.dump("p1=" + p1);
        log.dump("p2=" + p2);
        log.dump("p3=" + p3);
        ....
    }

「分離」スタイル

「結合」スタイルでは、 1つのログレコード中にパラメータ出力を得ることができますが、 ログ要求を行うクライアントコードは優雅ではありません。

「分離」スタイルでは、 パラメータ出力が複数のログレコードに分割されるため、 ログ出力から情報を収集しなければなりません。

PTLog は LogBuffer によってこの問題を解決します。


    public void doSomething(int p1, int p2, int p3, ....){
        Log log = TAP.getLog("doSomething");

        LogBuffer dump = log.forDump();
        dump.add("p1", p1);
        dump.add("p2", p2);
        dump.add("p3", p3);
        ....
        dump.flush(); // ログ要求発行
    }

LogBuffer によるログ要求

上記例では、 ログ要求は LogBuffer#flush() 起動時に「dump」型で発行されます。 LogBuffer はパラメータの名前と値を結合します。

対応する「型」のログ記録が可能でない場合、 Log#for<Type>() メソッドは、 いずれのメソッド発行に対しても何も行わない実装の LogBuffer を返します。 そのため、 Object#toString の実行コストの高価なものが含まれるか、 パラメータ数が極めて多い場合以外は、 性能劣化防止に備えた Log#enables<Type>() による確認は不要です。


次節「ログフレームワークへの接続」へ