Log4J

Log4J

Introduction
Inserting log statements into your code is a low-tech method for debugging it. It may also be the only way because debuggers are not always available or applicable. This is often the case for distributed applications.

On the other hand, some people argue that log statements pollute source code and decrease legibility. (We believe that the contrary is true). In the Java language where a preprocessor is not available, log statements increase the size of the code and reduce its speed, even when logging is turned off. Given that a reasonably sized application may contain thousands of log statements, speed is of particular importance.

With log4j it is possible to enable logging at runtime without modifying the application binary. The log4j package is designed so that these statements can remain in shipped code without incurring a heavy performance cost. Logging behavior can be controlled by editing a configuration file, without touching the application binary.

Links

 * Log4J
 * Documentation
 * Jakarta Commons Logging (JCL)

Installation

 * Download the Apache log4j at http://logging.apache.org
 * Add the file log4j-x.y.z.jar from \dist\lib in the classpath of your application.

Rules

 * A logger without an assigned level will inherit one from the hierarchy.
 * This rule assumes that priorities are ordered as follows: DEBUG < INFO < WARN < ERROR < FATAL.

Log4J Layouts
The output of an appender can be customized by associating with it a Layout. These are the types of Layout available:

Simple layout
Class: org.apache.log4j.SimpleLayout

Definition: SimpleLayout formats the output in a very simple manner, it prints the Level, then a dash '-' and then the log message.

PatternLayout
Class: org.apache.log4j.PatternLayout

Definition: PatternLayout formats the output based on a conversion pattern specified, or if none is specified, the default conversion pattern.

HTML layout
Class: org.apache.log4j.HTMLLayout

Definition: HTMLLayout formats the output as a HTML table.

XMLLayout
Class: org.apache.log4j.xml.XMLLayout

Definition: XMLLayout formats the output as a XML.

SimpleLayout and FileAppender
Here is a very simplistic example of a program implementing a SimpleLayout and FileAppender:

import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; import org.apache.log4j.FileAppender; public class simpandfile { static Logger logger = Logger.getLogger(simpandfile.class); public static void main(String args[]) { SimpleLayout layout = new SimpleLayout; FileAppender appender = null; try { appender = new FileAppender(layout,"output1.txt",false); } catch(Exception e) {}

logger.addAppender(appender); logger.setLevel((Level) Level.DEBUG);

logger.debug("Here is some DEBUG"); logger.info("Here is some INFO"); logger.warn("Here is some WARN"); logger.error("Here is some ERROR"); logger.fatal("Here is some FATAL"); } }

HTMLLayout and WriterAppender
Here is a very simplistic example of a program implementing a HTMLLayout and WriterAppender:

import java.io.*; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.HTMLLayout; import org.apache.log4j.WriterAppender; public class htmlandwrite { static Logger logger = Logger.getLogger(htmlandwrite.class); public static void main(String args[]) { HTMLLayout layout = new HTMLLayout; WriterAppender appender = null; try { FileOutputStream output = new FileOutputStream("output2.html"); appender = new WriterAppender(layout,output); } catch(Exception e) {} logger.addAppender(appender); logger.setLevel((Level) Level.DEBUG); logger.debug("Here is some DEBUG"); logger.info("Here is some INFO"); logger.warn("Here is some WARN"); logger.error("Here is some ERROR"); logger.fatal("Here is some FATAL"); } }

PatternLayout and ConsoleAppender
Here is a very simplistic example of a program implementing a PatternLayout and ConsoleAppender:

import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.ConsoleAppender; public class consandpatt { static Logger logger = Logger.getLogger(consandpatt.class); public static void main(String args[]) { // Note, %n is newline String pattern = "Milliseconds since program start: %r %n"; pattern += "Classname of caller: %C %n"; pattern += "Date in ISO8601 format: %d{ISO8601} %n"; pattern += "Location of log event: %l %n"; pattern += "Message: %m %n %n";

PatternLayout layout = new PatternLayout(pattern); ConsoleAppender appender = new ConsoleAppender(layout); logger.addAppender(appender); logger.setLevel((Level) Level.DEBUG); logger.debug("Here is some DEBUG"); logger.info("Here is some INFO"); logger.warn("Here is some WARN"); logger.error("Here is some ERROR"); logger.fatal("Here is some FATAL"); } }

Substitute symbol
%c Logger, %c{2 } last 2 partial names %C Class name (full agony), %C{2 } last 2 partial names %d{dd MMM yyyy HH:MM:ss } Date, format see java.text.SimpleDateFormat %F File name %l Location (caution: compiler-option-dependently) %L Line number %m user-defined message %M Method name %p Level %r Milliseconds since program start %t Threadname %x, %X see Doku %% individual percentage sign Caution: %C, %F, %l, %L, %M slow down program run!

Configuration Files
It is far more flexible to configure log4j using configuration files. Currently, configuration files can be written in XML or in Java properties (key=value) format.

The file log4j.properties configures priorities and appenders.

The preferred way to specify the default initialization file is through the log4j.configuration system property. In case the system property log4j.configuration is not defined, then set the string variable resource to its default value log4j.properties.

If you are using Eclipse put the file log4j.properties under. When Eclipse compiles the project, it copies automatically the configuration file to.

The default initialization under Tomcat is to put the file log4j.properties under.

Examples of configuration files
Here is a sample configuration file that results in exactly same output as the previous BasicConfigurator based example.

log4j.rootLogger=DEBUG, A1
 * 1) Set root logger level to DEBUG and its only appender to A1.

log4j.appender.A1=org.apache.log4j.ConsoleAppender
 * 1) A1 is set to be a ConsoleAppender.

log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
 * 1) A1 uses PatternLayout.

Suppose we are no longer interested in seeing the output of any component belonging to the com.foo package. The following configuration file shows one possible way of achieving this.

log4j.rootLogger=DEBUG, A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
 * 1) Print the date in ISO 8601 format

log4j.logger.com.foo=WARN
 * 1) Print only messages of level WARN or above in the package com.foo.

As the logger com.foo.Bar does not have an assigned level, it inherits its level from com.foo, which was set to WARN in the configuration file. The log statement from the Bar.doIt method has the level DEBUG, lower than the logger level WARN. Consequently, doIt method's log request is suppressed.

Here is another configuration file that uses multiple appenders.

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
 * 1) Pattern to output the caller's file name and line number.

log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB log4j.appender.R.MaxBackupIndex=1
 * 1) Keep one backup file

log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

More than one log4j.properties
A common problem for big projects occurs when you have two or more dependent projects/applications, each one has its own file located in the root of your source directory, normally. In this case, one of files is picked up first on the classpath and will be used.

We propose two solutions. The first is more general and can solve most of cases. The second is used only if you are using an Application Server.

Solution 1: 


 * Upgrade your version of commons-logging-x.y.z.jar (if you are using it) and log4j-x.y.z.jar
 * Move the file to a deeper directory of your project
 * Put the following commands just below the line

URL url = ClassLoader.getSystemResource("br/jaraujo/vistapanel/log4j.properties"); PropertyConfigurator.configure(url);


 * Substitute the value br/jaraujo/vistapanel/ with the path of your project.

It forces Log4J to re-configure itself.

Solution 2: 

If your are using an Application Server that has the file follow the instructions below:


 * Upgrade your version of commons-logging-x.y.z.jar and log4j-x.y.z.jar
 * Use ContextJNDISelector

 JNDI logging context name for this app log4j/context-name aDistinctiveLoggingContextName java.lang.String 

Read http://qos.ch/logging/sc.html and look at its JNDIRS class.

And in your application server's startup script/batch file, add the following system property:

-Dlog4j.repositorySelector=yourpackage.selector.ContextJNDISelector