Disclaimer don't get the wrong idea about what you've found here

What appears below are my personal notes I wish were part of my long-term memory but don't always seem to fit. I strive for accuracy and clarity and appreciate feedback. If applying any of this information anywhere, confirm for youself the correctness of your work as what you see below might very well be, albeit unintentionally, incorrect or misleading. These notes are here as an easy reference for myself.

Information worthy of a more formal presentation will appear elsewhere than this "Scratch" area. - ksb


KSB's Java Logging notes

Table of Contents

References


History

From what I understand: Log4j was the de facto standard logging system for Java, then Sun added it into the JDK as java.util.logging and 'got it wrong'. Commons-Logging came into existance as a compromise as a general logging API under which your logging engine of choice could be used. The de facto standard now appears to be to use the commons-logging API with log4j underneath as the implementation.

What follows is my brief example-driven introduction to using the commons-logging API with (the default) log4j underneath. Read the two (short) user guides for Commons Logging and Log4j for a real introduction.


"Hello, World" example

Compile and run the the following code:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class KSBLogTest {

    // Get a log object named after this class
    private static Log log = LogFactory.getLog(KSBLogTest.class);

    public static void main(String[] args) {

	System.out.println("Sysout: main: in");
	log.info("log: hello");

	log.info("log: goodbye");
	System.out.println("Sysout: main: out");
    }
}

and here is what you get:

$ javac -classpath /usr/local/share/java/classes/commons-logging.jar KSBLogTest.java
$ java -cp /usr/local/share/java/classes/commons-logging.jar:. KSBLogTest
Sysout: main: in
log4j:WARN No appenders could be found for logger (KSBLogTest).
log4j:WARN Please initialize the log4j system properly.
Sysout: main: out

Probably not what you expected but it points out that log4j is the default implementation and it needs something more to initialize it properly - namely a configuration file.

By default a log4j.properties file will be looked for to configure log4j. Drop this into the current dir (or anywhere in the CLASSPATH):

# Set the root logger to the DEBUG level and CA to be it's appender
log4j.rootLogger=DEBUG, CA

# Set CA to be a ConsoleAppender.
log4j.appender.CA=org.apache.log4j.ConsoleAppender

# Set CA to use the SimpleLayout
log4j.appender.CA.layout=org.apache.log4j.SimpleLayout

and now you get:

$ java -cp /usr/local/share/java/classes/commons-logging.jar:. KSBLogTest
Sysout: main: in
INFO - log: hello
INFO - log: goodbye
Sysout: main: out

So if we want to format that output a little better use a different layout, like this:

# Set the root logger to the DEBUG level and CA to be it's appender
log4j.rootLogger=DEBUG, CA

# Set CA to be a ConsoleAppender.
log4j.appender.CA=org.apache.log4j.ConsoleAppender

# Set CA to use a PatternLayout
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] (%F:%L) %-5p %c %x - %m%n

Now we get:

$ java -cp /usr/local/share/java/classes/commons-logging.jar:. KSBLogTest
Sysout: main: in
1    [main] (KSBLogTest.java:13) INFO  KSBLogTest  - log: hello
9    [main] (KSBLogTest.java:16) INFO  KSBLogTest  - log: goodbye
Sysout: main: out

Log4j can also be configured using a log4j.xml XML file rather than the log4j.properties file. Here is the equivalent of the first .properties file (which can also be anywhere on the CLASSPATH):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

  <appender name="CA" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.SimpleLayout"/>
  </appender>

  <root>
    <priority value ="debug" />
    <appender-ref ref="CA"/>
  </root>

</log4j:configuration>

Here is the logj4.xml file that uses the PatternLayout as the second log4j.properties file does.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        
  <appender name="CA" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%-4r [%t] (%F:%L) %-5p %c %x - %m%n"/>
    </layout>
  </appender>

  <root>
    <priority value ="debug" />
    <appender-ref ref="CA"/>
  </root>

</log4j:configuration>


Writing log4j.{xml,properties} configuration files

When writing log4j config files, use the log4j javadoc as your guide. It appears that they follow the class and member structure in a pretty straightforward way.

A helpful trick is to turn on debugging for logj4 itself by setting log4j.debug property in the VM:

$ java -Dlog4j.debug -cp /usr/local/share/java/classes/commons-logging.jar:. KSBLogTest
log4j: Trying to find [log4j.xml] using context classloader sun.misc.Launcher$AppClassLoader@53c015.
log4j: Trying to find [log4j.xml] using sun.misc.Launcher$AppClassLoader@53c015 class loader.
log4j: Trying to find [log4j.xml] using ClassLoader.getSystemResource().
log4j: Trying to find [log4j.properties] using context classloader sun.misc.Launcher$AppClassLoader@53c015.
log4j: Using URL [file:/home/ksb/Scratch/log4j.properties] for automatic log4j configuration.
log4j: Reading configuration from URL file:/home/ksb/Scratch/log4j.properties
log4j: Parsing for [root] with value=[DEBUG, CA].
log4j: Level token is [DEBUG].
log4j: Category root set to DEBUG
log4j: Parsing appender named "CA".
log4j: Parsing layout options for "CA".
log4j: Setting property [conversionPattern] to [%-4r [%t] (%F:%L) %-5p %c %x - %m%n].
log4j: End of parsing for "CA".
log4j: Parsed "CA" options.
log4j: Finished configuring.
Sysout: main: in
1    [main] (KSBLogTest.java:13) INFO  KSBLogTest  - log: hello
24   [main] (KSBLogTest.java:16) INFO  KSBLogTest  - log: goodbye
Sysout: main: out

So the log4j.xml file takes precedence over the logj4.properties file, as that is searched for, and used, first.

Another possibility is to set the name (and location) of the config file with the log4j.configuration property. As in:

$ java -Dlog4j.configuration=file:///tmp/log4j.xml -cp /usr/local/share/java/classes/commons-logging.jar:. KSBLogTest
Sysout: main: in
0    [main] (KSBLogTest.java:13) INFO  KSBLogTest  - log: hello
10   [main] (KSBLogTest.java:16) INFO  KSBLogTest  - log: goodbye
Sysout: main: out

Yes, that's a URL so it could be http:// something and therefore remote.

Here is a pair of config files using a FileAppender to log to a file.

# Set the root logger to the DEBUG level and FA as a FileAppender
log4j.rootLogger=DEBUG, FA

# Set FA to be a FileAppender.
log4j.appender.FA=org.apache.log4j.FileAppender

# Set the filename and layout for FA to use
log4j.appender.FA.file=KSBTest.log
log4j.appender.FA.layout=org.apache.log4j.SimpleLayout

and the equivalent log4j.xml file:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        
  <appender name="FA" class="org.apache.log4j.FileAppender">
    <param name="file" value="KSBTest.log"/>
    <layout class="org.apache.log4j.SimpleLayout"/>
  </appender>

  <root>
    <priority value ="debug" />
    <appender-ref ref="FA"/>
  </root>

</log4j:configuration>

I figured this out by looking at the javadoc for FileAppender and using the file property. Log4j will print out helpfull information if doesn't understand what you've got.


Keith S. Beattie is responsible for this document, located at http://dst.lbl.gov/~ksb/Scratch/java_logging.html, which is subject to LBNL's Privacy & Security Notice, Copyright Status and Disclaimers.

Last Modified: Monday, 25-Feb-2013 16:57:57 PST