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

値のフォーマット

本節では、 ログ出力における指定値のフォーマットの方法を説明します。

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

概要

クラス名

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

PTLog のクラス

表記 完全名
DefaultIntFormatter jp.ne.dti.lares.foozy.ptlog.format.DefaultIntFormatter
DefaultUniversalFormatter jp.ne.dti.lares.foozy.ptlog.format.DefaultUniversalFormatter
IntFormatter jp.ne.dti.lares.foozy.ptlog.format.IntFormatter
Log jp.ne.dti.lares.foozy.ptlog.Log
LogBuffer jp.ne.dti.lares.foozy.ptlog.LogBuffer
LogDirector jp.ne.dti.lares.foozy.ptlog.LogDirector
LogServer jp.ne.dti.lares.foozy.ptlog.LogServer
LogTap jp.ne.dti.lares.foozy.ptlog.LogTap
UniversalFormatter jp.ne.dti.lares.foozy.ptlog.format.UniversalFormatter

要求ごとのフォーマット指定

前節では、 1つのログレコードに複数の値を記録するコードを示しました。

このような場合、 例えば、int 値を10進ではなく16進で、といったように、 指定値を個別の形式でフォーマットしたいと思うかもしれません。

要求ごとのフォーマット指定は、 以下に示すようにして行うことが出来ます。


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

        LogBuffer dump = log.forDump();

        dump.add("p1", p1);
        // "符号付10進(signed decimal)" でフォーマット

        dump.add("p2", p2, DefaultIntFormatter.S_OCT);
        // "符号付8進(Signed OCTal)" でフォーマット

        dump.add("p3", p3, DefaultIntFormatter.U_HEX);
        // "符号無16進(Unsigned HEXdecimal)" でフォーマット
    }

要求ごとのフォーマット指定

既定義済みフォーマットインスタンスに関する詳細は、 jp.ne.dti.lares.foozy.ptlog.format パッケージの "Default*" クラス群を参照してください。

データ型ごとのフォーマット指定

以下に示すようにして、 データ型ごとにフォーマットを指定することも出来ます。


public class Client
{
    ....
    final static
    public LogTap TAP =
    new LogTap(Client.class, LogConfig.DIRECTOR);

    static{
        IntFormatter intFormatter = DefaultIntFormatter.U_HEX;
        TAP.DEFAULT_FORMATTER.setIntFormatter(intFormatter);
    }
}

データ型ごとのフォーマット指定

DEFAULT_FORMATTER インスタンスフィールドは LogTap のデフォルトフォーマッタとして使用されるため、 DEFAULT_FORMATTER を通じて LogTap の挙動を設定することが出来ます。

上記例では、 一度に一つの LogClient#TAP しか設定できません。

一度に複数の LogTap を設定するには、 2つの方法があります。

1つ目の方法は、 固有の LogTap クラスを定義して使用することです。 例えば:


public class CustomTap
    extends LogTap
{
    public CustomTap(Object subject, LogServer initialServer){
        super(subject, initialServer);

        IntFormatter intFormatter = DefaultIntFormatter.U_HEX;
        DEFAULT_FORMATTER.setIntFormatter(intFormatter);
    }
}

固有の LogTap

もう一つの方法は、 LogTap の生成にリスナーを引っ掛けることです。 例えば:


public class LogConfig
{
    ....

    final static
    public LogDirector DIRECTOR = new LogDirector();

    static{
        // このブロックは、LogConfig クラスが
        // ロードされた際に実行されます。
        // そのため、"addListener" は
        // LogConfig#DIRECTOR を参照する
        // LogTap 群が生成される前に実行されます。

        LogTap.addListener(new LogTap.Listener(){
            public void initialized(LogTap tap,
                                    String subjectName,
                                    Class level)
            {
                // 自身のパッケージ以外を無視したい場合:
                if(!subjectName.startsWith("your.package.")){
                    return;
                }

                IntFormatter intFormatter = DefaultIntFormatter.U_HEX;
                tap.DEFAULT_FORMATTER.setIntFormatter(intFormatter);
            }
        });
    }
}

LogTap の生成にリスナーを引っ掛ける

LogTap 生成に引っ掛けたリスナー群は、 LogTap の生成の都度、 呼び出しによる通知を受けます。

前者の方法は、非常にシンプルで明快ですが、 CustomTap コンストラクタの呼び出しが強制されます。 今日では、Eclipse のようなりファクタリングツールのお陰で、 自身のアプリケーション中の LogTap コンストラクタ起動を CustomTap で置き換えることはそれほど難しくありません。 しかし、他の人のコード中のものを置き換えるのは難しいでしょう。

後者の方法は幾分複雑ですが、 この方法は、 例え "private" だったり他人のコード中のものであっても、 殆ど全ての LogTap 群に対する設定を可能にします。

備考: LogTap を設定するためにはリスナーの登録が必要なため、 設定可能な LogTap は、 「全て」ではなく「殆ど全て」と記述しました。

リスナー登録前に生成された "private" な LogTap を設定する方法は無いためです。

デフォルトフォーマッタの指定

LogBuffer における値のフォーマットは UniversalFormatter 実装クラスによって行われており、 固有の UniversalFormatter 実装を使って "#setFormatter(UniversalFormatter)" 起動を行うことで、 LogTap が利用するデフォルト実装を設定できます。

UniversalFormatter のカスタマイズの第一歩として、 本チュートリアルでは、 UniversalFormatter 実装クラスである DefaultUniversalFormatter の派生クラスの例を示します。


public class CustomFormatter
    extends DefaultUniversalFormatter
{
    public CustomFormatter(){
        super();

        setIntFormatter(DefaultIntFormatter.U_HEX);
    }
}

固有 UniversalFormatter の定義

固有フォーマッタを LogTap の初期フォーマッタに指定する方法は、 "データ型ごとのフォーマット指定" を参照してください。

Log/LogBuffer ごとのフォーマッタ指定

以下のようにして、 Log ないし LogBuffer ごとにフォーマッタを指定することも出来ます。


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

        LogBuffer dump = log.forDump(new CustomFormatter());
        dump.add("p1", p1);
        ....
    }

Log/LogBuffer ごとのフォーマッタ指定

フォーマット設定の通用範囲に応じて、 起動メソッドを選択してください。

備考: 上記のコード例はコードの単純さを優先しているため、 設定メソッドの呼出しごとに CustomFormatter コンストラクタを起動しています。

固有フォーマッタがマルチスレッドセーフであるなら、 資源消費の点からも、 自分自身のインスタンスを保持する (おそらく "final" で) "static" な メンバ変数を CustomFormatter で定義して、 それを使うようにしましょう。


次節「固有のログタイプ」へ