Home of: [Atelier "FUJIGURUMA"] >> [PTLog hosted by SourceForge.net]

SEE "For Readers of English Version",
or Japanese version of this page

Write client code

This section explains how to write client code of logging request.

Please see also classes belonging to basic.client package of demonstration implementation.

Overview

Class names

In this tutorial, abbreviated class names are used. Complete names are shown below.

Classes of PTLog

Notation Full name
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

Create LogTap

At first, you should create LogTap for convenience.


public class Client
{
    ....

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

Create LogTap

LogTap is almost equivalent to Logger of JDK logging API(or Apache Log4j).

The former parameter of constructor is the "subject" of logging request. This is used to identify logging request issuer.

The later parameter specifies underlying logging framework. In this case, "WriterProvider.STDOUT" means that logging request is written out to standard out initially.

Please see "Plug into logging framework" for detail about the later parameter.

Request via Log

Now you can issue logging request via Log gotten from LogTap. For example:


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

        log.info("log with INFO type");
        log.dump("log with DUMP type");

        try{
            ....
            ....
        }
        catch(Exception e){
            log.error("log with ERROR type", e);
        }
    }

Request via Log

Parameter of LogTap#getLog() means name of method in which logging request is issued.

Log has some "type"s to accept logging request:

type corresponded 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) is used as abbreviation of "Jakarta Common Loggings" in this tutorial.

(*2) is supported since Log4j 1.2.12.

(*3) uses "DEBUG"(in Log4j environment) or "FINEST"(in JDK Logging API environment), according to JCL 1.0.x.

(*4) can be enabled by type conversion.

Each "type"s have three signature variations in Log class.


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

    public void <type>(Object data);

    public boolean enables<Type>();

signature variations

First of them is generic form like other logging frameworks (such as JDK logging API, Log4j and JCL). You can specify "null" as message and/or throwable.

Second of them is used to log any data including Throwable. This is usefull if you want to write out only one of String or Throwable.

Third of them is used to examine whether logging request of such "type" is enabled or not. For example:


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

        if(log.enablesDump()){
            log.dump("log with DUMP type");
        }
    }

examine "type"

Block under "log.enablesDump()" condition is executed only when "dump" is enabled. Such condition may be changed dynamically in runtime.

This examination is usefull when information gatherring is too expensive to do it always.

In addition to them, three more variations are defined for "trace" type.


    public void doSomething(){
        Log log = TAP.getLog("doSomething");
        log.enter(); // means method entry

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

        log.exit(); // means method exit
    }

convenience methods for "trace"

Each methods shown in above example are replacable by "Log#trace" method, but these methods provide uniform ways to request(and format) "trace" logging.

And, shortness of method invocation code is important, is not it?

Request via LogBuffer

In my experience, parameter output is one of major purposes of logging, and there are two styles to request logging.

One of them is "concatenation" style.


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

"concatenation" style

The other of them is "separation" style.


    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);
        ....
    }

"separation" style

In "concatenation" style, you can get parameter output in one log record, but client code of logging request is not elegant.

In "separation" style, you should gather information from logging output, because parameter output is splitted into some log records.

PTLog solves this by 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(); // requests logging
    }

logging with LogBuffer

In above example, logging request is issued in "dump" type at LogBuffer#flush() invocation. LogBuffer concatenates names and values of parameters.

When corresponded "type" is disabled to log, Log#for<Type>() methods return LogBuffer implementation which does nothing at any method invocations. So you do not have to examine by Log#enables<Type>() unless any of parameters have expensive Object#toString or number of parameters is very big.


To next section "Plug into logging framework"