Formatters
Every handler must have a formatter defined, and the API has
pre-defined a SimpleFormatter and an XMLFormatter which
both extend the abstract class Formatter. You may define your
own formatter if you like, and it's actually quite simple. You only
have to implement the format method. This method receives an
instance of the LogRecord class which contains several
properties. format returns a string with the data that should
be logged. In the next example I've made a formatter that returns the
most important properties from the LogRecord:
package hansen.playground.logging;
import java.util.*;
import java.util.logging.*;
public class MyFormatter extends Formatter {
public String format(LogRecord record) {
return
"LogRecord info:\n" +
"Level: " + record.getLevel() + '\n' +
"LoggerName: " + record.getLoggerName() + '\n' +
"Message: " + record.getMessage() + '\n' +
" " + record.getMillis() + '\n' +
"Sequence Number: " + record.getSequenceNumber() + '\n' +
"SourceClassName: " + record.getSourceClassName() + '\n' +
"SourceMethodName: " + record.getSourceMethodName() + '\n' +
"ThreadID: " + record.getThreadID() + '\n';
}
}
|
The simplest way to try this formatter is to put its name in the
logging.properties file. So we replace
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
with
java.util.logging.ConsoleHandler.formatter = hansen.playground.logging.MyFormatter
If we run program Log1 we get this written out to the
console:
LogRecord info:
Level: SEVERE
LoggerName: hansen.playground.logging.Log1
Message: severe message
Millis: 1028657842830
Sequence Number: 0
SourceClassName: hansen.playground.logging.LoggerInformation
SourceMethodName: tryLevels
ThreadID: 10
LogRecord info:
Level: WARNING
LoggerName: hansen.playground.logging.Log1
Message: warning message
Millis: 1028657842830
Sequence Number: 1
SourceClassName: hansen.playground.logging.LoggerInformation
SourceMethodName: tryLevels
ThreadID: 10
LogRecord info:
Level: INFO
LoggerName: hansen.playground.logging.Log1
Message: info message
Millis: 1028657842830
Sequence Number: 2
SourceClassName: hansen.playground.logging.LoggerInformation
SourceMethodName: tryLevels
ThreadID: 10
|
If you compare it to the output from the
SimpleFormatter:
11-08-2002 19:49:10 hansen.playground.logging.LoggerInformation tryLevels
SEVERE: severe message
then you can see that this format contains: a timestamp,
SourceClassName, SourceMethodName, Level, and Message. In most cases
this format is sufficient.
Rotating files
A very nice feature in the FileHandler is the option to use
a set of rotating files. If you define your FileHandler like
this:
FileHandler filehandler =
new FileHandler("%h/mylog%g.txt", 100000, 2);
then the file is placed in the "user.home" directory (the "%h"),
it can hold 100000 bytes of data, and it'll switch between two files
called mylog0.txt and mylog1.txt. The generation
numbers comes from the "%g" notation. A small example will illustrate
this. We'll write 10 lines to two very small log-files (300 bytes
each):
package hansen.playground.logging;
import java.util.*;
import java.util.logging.*;
public class CyclicFiles {
private static Logger logger1 =
Logger.getLogger("hansen.playground.logging.CyclicFiles");
public static void main(String[] args)
throws java.io.IOException {
FileHandler filehandler =
new FileHandler("%h/mylog%g.txt", 300, 2);
logger1.addHandler(filehandler);
filehandler.setFormatter(new SimpleFormatter());
for (int i = 0; i < 10; i++) {
logger1.info("Line " + i);
}
}
}
|
When we run this program we'll first of all see 10 lines written
to the console (System.err), but in the user.home directory--which is
C:\WINDOWS on my Win98 computer--we find two files: mylog0.txt
contains this:
11-08-2002 13:07:48 hansen.playground.logging.CyclicFiles main
INFO: Line 8
11-08-2002 13:07:48 hansen.playground.logging.CyclicFiles main
INFO: Line 9
|
and mylog1.txt this:
11-08-2002 13:07:48 hansen.playground.logging.CyclicFiles main
INFO: Line 4
11-08-2002 13:07:48 hansen.playground.logging.CyclicFiles main
INFO: Line 5
11-08-2002 13:07:48 hansen.playground.logging.CyclicFiles main
INFO: Line 6
11-08-2002 13:07:48 hansen.playground.logging.CyclicFiles main
INFO: Line 7
|
A total of 10 messages have been logged. The first 4 were logged
to mylog0.txt, which then was full (as defined by the maximum
allowable size of 300 bytes). The following 4 were logged to
mylog1.txt which then was also full. Then the cyclic logging
mechanism started over with the first file (mylog0.txt), which it
completely overwrites and thereby only leaves the last 2 messages in
the file.
If you have ever tried to empty a log file on a web server without
success, because the file was being used by the server, then you'll
appreciate this feature.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.