Hi,

In this article, I would present the famous framework of logging Log4J which is used in the most projects. So, our article will be composed of several sections:
1) Presentation of logging and Log4J,
2) The components of Log4J,
3) Apache Commons Logging and SLF4J


1) Presentation of logging and Log4J
The best practices of development recommend the use of a logging system instead of the use of System.out.print* and System.err.print* to display a message. These systemes provide more flexibility.

Log4J simplifies the management of logs and the debugging of Java applications by providing classes and methods for recording information. The log files are the memory of an application. In a logging system, the messages have a granularity level that set by the developer (DEBUG, INFO, WARNING, ERROR, CRITICAL). The logging parameters are configured in a properties/XML external file by specifying the levels, the concerned java classes or packages, the output format of message, the type of storing (console, file,…etc).

So, an application could display all messages of:
– DEBUG level and higher in the the console/screen during the development phase,
– WARNING level and higher in a log file in the production environnement.

The message displayed or stored in a log file, could contains:

  • the class or method which is the origin of the message,
  • the line number in source code,
  • a custom message,
  • …etc.

To conclude this first section, Log4J is a open source project of Apache Foundation which is distributed under the BSD license, its official documentation http://logging.apache.org/log4j/2.x/ and the current version is 2.x.


2) The components of Log4J
Log4J is composed of three main components which configure the logging system:

  • the Loggers to write messages,
  • the Appenders to select the type of messages recording,
  • the Layouts for the messages formatting

2.1. The Loggers
The Logger is the basic entity to perform logging, it is implemented by means of the class org.apache.log4j.Logger. A Logger instance is obtained by calling the static method Logger.getLogger:

import org.apache.log4j.Logger;

public class MyClasse {

	private static final Logger logger = Logger.getLogger(MyClasse.class);
	// ...
}

The granularity of message
The granularity or level of logging/message represents the priority/importance of the message to be logged. A message is logged only if its priority/level is higher than or equal to the priority of Logger performing logging.
Log4j API defines five levels of logging exposed below by decreasing severity:

  • FATAL: log a fatal error that can lead to premature termination of the application:
    logger.fatal(msg);
    logger.log(Level.FATAL, msg);
    
  • ERROR: log an error that does not preclude the application to run (the logging events with granularity FATAL and ERROR are logged):
    logger.error(msg);
    logger.log(Level.ERROR, msg);
    
  • WARN: log a warning which could be an inconsistency in the configuration (the logging events with granularity FATAL, ERROR AND WARN are logged):
    logger.warn(msg);
    logger.log(Level.WARN, msg);
    
  • INFO: log informative messages (the logging events with granularity FATAL, ERROR, WARN and INFO are logged):
    logger.info(msg);
    logger.log(Level.INFO, msg);
    
  • DEBUG: generate messages that can be useful in debugging (the logging events with granularity FATAL, ERROR, WARN, INFO and DEBUG are logged):
    logger.debug(msg);
    logger.log(Level.DEBUG, msg);
    
  • TRACE: to use in order to record the entry or the exit of a method (the logging events with granularity FATAL, ERROR, WARN, INFO, DEBUG and TRACE are logged):
    logger.trace(msg);
    logger.log(Level.TRACE, msg);
    
  • Two particular levels, ALL and OFF are used for configuration;

Notes:
– Further down in the level, the more messages are many.
– These levels are accessible via the org.apache.log4j.Level class.
– If necessary, you can create your own levels by extending the class org.apache.log4j.Level.
– The logging of a message at a given level is done via the method:

logger.log(Level.INFO, msg);

– There are several variants of log methods, for example, to pass a Throwable whose trace will be recorded.

2.2. The Appender interface
The Logger provides a addAppender(…) allowing to add a new Appender. The interface org.apache.log4j.Appender is used to record logging events. In fact, each Appender has a specific way to record these events. The handling of appenders is not necessary directly in Java code, however, it is necessary to know their operation to configure properly Log4j.

Log4j provides a set of appenders used in the configuration:

  • org.apache.log4j.jdbc.JDBCAppender: performs the logging events to a database;
  • org.apache.log4j.net.JMSAppender: performs the logging events via JMS;
  • org.apache.log4j.nt.NTEventLogAppender: performs the logging events via Event Log of Windows (NT/2000/XP);
  • org.apache.log4j.lf5.LF5Appender: performs the logging events to a Swing-based console allowing the sorting or filtering of events;
  • org.apache.log4j.varia.NullAppender: doesn’t perform the logging events;
  • org.apache.log4j.net.SMTPAppender: sends an email when certain events occur;
  • org.apache.log4j.net.SocketAppender: sends the logging events to a log server;
  • org.apache.log4j.net.SyslogAppender: performs the logging events to a Syslog daemon (remote or not);
  • org.apache.log4j.net.TelnetAppender: performs the logging events to a socket accessible via telnet;
  • org.apache.log4j.ConsoleAppender: performs the logging events to the standard console;
  • org.apache.log4j.FileAppender: performs the logging events to a file;
  • org.apache.log4j.DailyRollingFileAppender: performs the logging events to a file which is renamed at a defined frequency (not necessarily every day);
  • org.apache.log4j.RollingFileAppender: performs the logging events to a file which is renamed when it reaches a certain size and logging resumes in a new file;

The last four appenders (ConsoleAppender, FileAppender, DailyRollingFileAppender, RollingFileAppender) are the most used appenders. An appender is the target of events’ logging messages, i.e. where they will be physically displayed or stored.

2.3. The Layouts
The layouts are used to format the different logging events in conjunction with the appenders. Although all appenders accept a Layout, however, the appenders using the layouts are identifiable by the requiresLayout method which returns true.

Here the layouts provided by log4j:

  • org.apache.log4j.SimpleLayout: this is the easiest Layout, the logging events have the format [Level – Message];
  • org.apache.log4j.PatternLayout: the most flexible layout, the message format is specified by a pattern (pattern) consisting of text and escape sequences indicating the information to display;
  • org.apache.log4j.XMLLayout: it formats the logging events in XML (used in conjunction with a Appender of type of FileAppenders);
  • org.apache.log4j.HTMLLayout: the logging events are logged to HTML. Each new logging session (reset Log4j) creates a new HTML document;

Simple example of most interresting layout PatternLayout, in this example,
we display the time and date, the error level (aligned to left), the name of the logger, the file name, the number of the corresponding line of code and finally the message:

Logger log = Logger.getLogger("com.ho.log4j.test1.MyClass");
PatternLayout layout = new PatternLayout("\%d \%-5p \%c - \%F:\%L - \%m\%n");
ConsoleAppender stdout = new ConsoleAppender(layout);
log.addAppender(stdout);

…and the result could be in the console:

2013-01-15 04:44:32,211 DEBUG com.ho.log4j.test1.MyClass - MyClass.java:32 - My message line 32
2013-01-15 04:44:32,221 DEBUG com.ho.log4j.test1.MyClass - MyClass.java:55 - My message line 55


3) Apache Commons Logging and SLF4J
There are a large range of logging APIs, but the problem is that the multitude of APIs and frameworks added to an application, don’t necessarily use the chosen implementation of this application. However, the role of abstraction layers is to limit these differences. They can be abstracted from the implementation used. Jakarta Common Logging (JCL) and SLF4J are the most known.

The JCL API includes the commons-logging.jar file containing the default LogFactory implementation and thin-wrapper Log implementations for Log4J, Avalon LogKit, ..etc. The org.apache.commons.logging package is a simple wrapper API around multiple logging APIs.

SLF4J solution has established itself on large projects like Hibernate 3, Wicket, DBUnit, Gradle, Sonar, …etc. One of the strengths of SLF4J (Simple Logging Facade for Java) is that it is possible to intercept calls to all implementations, which was not possible with JCL. Once everything is at SJF4J, it remains only to “select” the desired implementation for our application.

That’s all!!!

Huseyin OZVEREN