Logging with “Java logging API”

I wonder why you want to use Java logging API when you can use log4j. Well if you want to or have to use Java’s bundled API for logging, it is not that bad. There are several good articles on the web that go it much more details on this topic then what I am going to cover her. So, look at the articles at the end of this article for links to some of those detailed articles.

So, what am I going to be covering in this article? Just few tricks that I found intriguing and somewhat hard to understand. First of all the logging.properties file. This file resides in the JRE directory as lib/logging.properties (/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib for Mac OS users). You can edit this file to control the behavior of the default loggers that get installed when JVM starts. This is definitely is not a good idea. You can copy this file to a user space and then can edit the copy to your liking and load this file as part of your program to control the logging. As I am working on a Mac I will copy the system properties file to my space as /Users/user/LogApi/mylogging.properties. Now, I would like to have two types of handlers, the standard Console Handler and a File Handler. I edit the file to install the two handlers. So, make sure that the following line is uncommented in your properties file

handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

I would like to log everything to a file but only the SEVERE and above log entries to my log console. By default, the FileHandler logs everything to the file, so we don’t have to do anything here. To make the ConsoleHandler log only entries higher thatn SEVERE, add line similar to:

java.util.logging.ConsoleHandler.level = SEVERE

Configure the FIleHandler handler with the following properties.

java.util.logging.FileHandler.pattern = /Users/user/LogApi/build/classes/javaapi%u.log

java.util.logging.FileHandler.limit = 50000

java.util.logging.FileHandler.count = 1

java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

java.util.logging.FileHandler.append = true

The first line specifies where the logging file is to be placed. Please see (http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/FileHandler.html) for other options and detials. The “%u” in the above line basically makes the log file rotate through “javaapi0.log” and “javaapi1.log”. The “count” option controls how many of these files the logger cycles through. Also don’t forget to set the append mode to true as the default this set to false. You are done. A simple program to exercise this is given below:

package logapi;

import java.util.logging.*;

/**

* A simple Java program, to understand the Java logging API

*/

public class Main {

private Logger theLogger = null;

public static void main(String[] args) {

Main hello = new Main("Hello world!");

hello.sayHello();

}

private String theMessage;

public Main(String message) {

theMessage = message;

}

public void sayHello() {

try {

//get my logger for this class.

theLogger = Logger.getLogger(Main.class.getName());

// log a message at INFO level

theLogger.info(“info message...");

// log a message at SEVERE level

theLogger.severe("severe message...");

} catch(Exception e){

// caught exception, lets log it

theLogger.log(Level.SEVERE,"Caught excepttion, ",e);

}

}

}

Once you compile this program using javac to Main.class, you will execute this program with the following command:

java -Djava.util.logging.config.file=/Users/user/LogApi/mylogging.properties Main

You are asking the jvm to load your own logger.properties file with the “-D” switch. This is the output of this program:

localhost:classes user$ java -Djava.util.logging.config.file=/Users/user/LogApi/mylogging.properties Main

Dec 21, 2008 8:55:08 PM logapi.Main sayHello

SEVERE: severe message...

localhost:classes user$

The program after execution also wrote a file called “javaapi0.log” and the contents of this file are:

localhost:classes user$ more javaapi0.log

Dec 21, 2008 8:59:32 PM logapi.Main sayHello

INFO: info message...

Dec 21, 2008 8:59:32 PM logapi.Main sayHello

SEVERE: severe message...

localhost:classes user$

Notice that on the console we only saw the “SEVERE” message but the log file has both the info and the sever messages.

If you don’t want to mess around with the properties files but rather want to control the logging programmatically, we can do that also. Although I advise not doing this as you have no control over the logging once the program is rolled out to the filed except re-compiling. However, I will show you how we can do this programmatically just for understanding sake. I hope you have read the other detail tutorial on the web and know the hierarchy of the loggers and their default behaviour. The basic behavior of the logger is when the message comes to it for logging, it checks with its filter and if the message passes the filter the message is handed over to the installed handlers and then the message is also passed on to the parent logger. The parent logger does the same thing till we hit the “root” logger. The root logger handlers are installed at the start of the JVM through the properties file sitting under JRE/lib directory. What we will do is install our own Console and File handlers and then disable the use of the parent handlers by calling the method “theLogger.setUseParentHandlers(false)”. That way we make sure that the only handlers the message passes through are the handlers we install. Here is the code for this:

import java.util.logging.*;

/**

* A simple Java program, to understand the Java logging API

*/

public class Main {

private Logger theLogger = null;

public static void main(String[] args) {

Main hello = new Main("Hello world!");

hello.sayHello();

}

private String theMessage;

public Main(String message) {

theMessage = message;

}

public void sayHello() {

boolean append = true;

try {

// create my own Handlers for file and console

FileHandler fh = new FileHandler("/Users/user/LogApi/build/classes/javaapi%u.log", 50000, 2, append);

//ConsoleHandler only if we need to log to Console

ConsoleHandler ch = new ConsoleHandler();

//get my logger for this class.

theLogger = Logger.getLogger(Main.class.getName());

// the logging gets bubbled up to the parent and the parent default

// handlers are used. Lets disable the use of the parent Handlers.

theLogger.setUseParentHandlers(false);

// set the formatting for the log file to the simple

fh.setFormatter(new java.util.logging.SimpleFormatter());

// install our own handlers in to the logger.

theLogger.addHandler(fh);

// ConsoleHandler Seetings only if we want to log to console.

ch.setLevel(Level.SEVERE);

theLogger.addHandler(ch);

// log a message at INFO level

theLogger.info("info message...");

// log a message at SEVERE level

theLogger.severe("severe message...");

} catch(Exception e){

// caught exception, lets log it

theLogger.log(Level.SEVERE,"Caught excepttion, ",e);

}

}

}

Compile this to Main.class and execute to get the same effect as the previous program.

Finally, the reason I had to deal with this is, we were working on a Java program to parse some files on a regular interval (every 2 minutes). This program got installed under cron. As you know, under cron anything that is written to the stdout or stderr gets emailed to the user under which the program is running. If you start logging a lot of messages to stdout/stderr (the console) you will get a lots of messages flooding your inbox. Worst yet, the /var/mail/user file may continue to grow and fill up the whole space if the program is left running for a long time without cleaning the messages. If we selectively log messages to the console, then you get an e-mail message for the critical messages that you want to see any ways.

http://www.onjava.com/pub/a/onjava/2002/06/19/log.html

http://www.crazysquirrel.com/computing/java/logging.jspx

http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/overview.html

Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically to your feed reader.

Comments

It looks fine. Thanks

Leave a comment

(required)

(required)