| Sign In/My Account | View Cart |
Unless you've been living under a rock, you already know that the official release of JDK 1.4 came out in the first quarter of this year, and included with it is a new logging API. This API was first described in JSR 47. Essentially the same description is also available in the documentation of logging for JDK 1.4 .
In addition to the implementation provided in JDK 1.4, there is an open source implementation of the API for JDKs 1.2 and 1.3 called Lumberjack, available on SourceForge. The library provides a way for people to begin using the API before they make the move to JDK 1.4. It also allows them to use the API in work they do which must be done in 1.2 or 1.3 for some reason.
The logging API is part of J2SE as of JDK 1.4, and it ships with the JDK. It is designed to let a Java program, servlet, applet, EJB, etc. produce messages of interest to end users, system administrators, field engineers, and software developers. Especially in production situations, where things can't be run in a debugger, or if doing so masks the problem that is occurring (because it is timing related, for example), such logs are frequently the greatest (and sometimes the only) source of information about a running program.
To make sure that logging can be left in a production program, the API is designed to make logging as inexpensive as possible. To let code produce fine-grained logging when needed but not slow the application in normal production use, the API provides mechanisms to dynamically change what log messages are produced, so that the impact of the logging code is minimized during normal operation. It also provides a number of Java interfaces and superclasses that provide "hooks" for developers to extend the API.
The entire logging API is contained in the package
java.util.logging and is made up of the following
interfaces and classes:
ConsoleHandlerFileHanderFilterFormatterHandlerLevelLoggerLoggingPermissionLogManagerLogRecordMemoryHandlerSimpleFormatterSocketHandlerStreamHandlerXMLFormatterWe'll examine many of these types in more detail below.
To help motivate the use of the logging API, we will use a simple program, based on the idea of a "Hello World" program.
package logging.example1;
/**
* A simple Java Hello World program, in the tradition of
* Kernighan and Ritchie.
*/
public class HelloWorld {
public static void main(String[] args) {
HelloWorld hello = new HelloWorld("Hello world!");
hello.sayHello();
}
private String theMessage;
public HelloWorld(String message) {
theMessage = message;
}
public void sayHello() {
System.err.println(theMessage);
}
}
We will expand upon this simple program in order to demonstrate and
motivate the logging API. The first thing we will do is actually
generate a logging message. This is straightforward; we need to
create a Logger object, which represents the
HelloWorld class, like this:
package logging.example2;
import java.util.logging.Logger;
/**
* A simple Java Hello World program, in the tradition of
* Kernighan and Ritchie.
*/
public class HelloWorld {
private static Logger theLogger =
Logger.getLogger(HelloWorld.class.getName());
public static void main(String[] args) {
HelloWorld hello = new HelloWorld("Hello world!");
hello.sayHello();
}
private String theMessage;
public HelloWorld(String message) {
theMessage = message;
}
public void sayHello() {
System.err.println(theMessage);
}
}
This generates a Logger, which we can use to generate
logging messages. Since you typically use one logger per class, we
can make it a static field of the HelloWorld class. We
use the fully qualified name of the HelloWorld class as
the name of the Logger. We'll look at the reasons for
this in more detail later. Now, let's actually use the
Logger to try to generate a logging message:
package logging.example3;
import java.util.logging.Logger;
/**
* A simple Java Hello World program, in the tradition of
* Kernighan and Ritchie.
*/
public class HelloWorld {
private static Logger theLogger =
Logger.getLogger(HelloWorld.class.getName());
public static void main(String[] args) {
HelloWorld hello = new HelloWorld("Hello world!");
hello.sayHello();
}
private String theMessage;
public HelloWorld(String message) {
theMessage = message;
}
public void sayHello() {
// use the 'least important' type of message, one at
// the 'finest' level.
theLogger.finest("Hello logging!");
System.err.println(theMessage);
}
}
The logging API has a configuration file and by default, it provides
a handler that will send logging messages, in the form of a
LogRecord to the console (System.err).
So we would expect to see the string "Hello logging!"; appear
before
our message of "Hello world!". But if you run this program
you only
see "Hello world!":
% java logging.example3.HelloWorld
Hello world
What's going on here? The answer lies in the notion of logging levels.
Because we want to leave logging code in an application that goes
into production, we need logging to cost us very little at runtime
when it is not being used. To help achieve this, the logging system
defines a class called Level to specify the importance
of a logging record. The logging library has a set of predefined
logging levels:
| SEVERE | The highest value; intended for extremely important messages (e.g. fatal program errors). |
| WARNING | Intended for warning messages. |
| INFO | Informational runtime messages. |
| CONFIG | Informational messages about configuration settings/setup. |
| FINE | Used for greater detail, when debugging/diagnosing problems. |
| FINER | Even greater detail. |
| FINEST | The lowest value; greatest detail. |
In addition to these levels, there is a level ALL,
which enables logging of all records, and one called
OFF that can be used to turn off logging. It is also
possible to define custom levels, but in this article we will stick
with the predefined levels.
|
Related Reading Java In a Nutshell |
So now we can explain why our logging record didn't appear. We
used the finest() method of our logger, which generates
a logging record at the Level.FINEST level. By default,
only records at the Level.INFO level or higher
will be logged to the console, so our record wasn't printed. We can cause our logging record to
appear by increasing the logging level used in generating the record, like this:
package logging.example4;
import java.util.logging.Logger;
/**
* A simple Java Hello World program, in the tradition of
* Kernighan and Ritchie.
*/
public class HelloWorld {
private static Logger theLogger =
Logger.getLogger(HelloWorld.class.getName());
public static void main(String[] args) {
HelloWorld hello = new HelloWorld("Hello world!");
hello.sayHello();
}
private String theMessage;
public HelloWorld(String message) {
theMessage = message;
}
public void sayHello() {
theLogger.info("Hello logging!");
System.err.println(theMessage);
}
}
Now, when we run this program, we see output like this:
% java logging.example4.HelloWorld
INFO; 992149105222ms; 3207485;# 1; logging.example4.HelloWorld; sayHello; Hello logging!
Hello world!
Of course, using a higher logging level for a logging record is not
always what we want. Sometimes we have messages that are
finer-grained than the INFO level, and we only want
them printed when the information they contain is needed. To allow
this, the logging library allows us to control the log level of our
Loggers.
Pages: 1, 2 |