RZO Web Page - networks and Co

Bienvenue sur la page RZO

Ressources de Jean et Pierre Parrend en informatique, telecoms et reseaux


Home

Pierre

Enseignement

Publications

Developpement

Jean

Ressources techniques

A Lire

Contact

Home-Pierre-Jean-Enseignement-Ressources techniques-Contact



Java Logging Facilities

The monitorization of the behavior complex applications, during development and execution phase proves to be necessary in order to assert their correctness. For runtime advanced monitoring and management, specific frameworks exit, such as JMX. But development and error tracking require more leightweight, static solutions. Logging libraries provide tools that enable a posteriori analysis of the behavior of considered systems.

Logging means classifying alerts according to severity level and making them available for the users, administrators, or developpers. In order to provide a comprehensive view of the system, a dedicated Logger is often bounded to each class.

This document propose an overview of the main logging facilities for Java, along with links to reference documents that give more details about their use. Some comparison elements between J2SE Logging API and Log4J framework are given.

Logging Libraries for Java

Main logging libraries for Java are :

  • Sun J2SE Logging API
  • Apache Log4J framework
  • Simple Log library
  • Jakarta Common Logging API
  • Simple Logging Facade for Java
  • X4juli

Sun J2SE Logging API

Main objective : configurable logging API for Java

For further informations :

Apache Log4J framework

Main Objective : Prevent performance cost that frequently occur in logging API (even when turned off).

For further informations :

Simple Log library

Main Objective : Zero learning curve for simpliest logging.

For further informations :

Jakarta Common Logging API

Main Objective : Thin, modular bridging API with out-of-the-box support for most well known logging systems.

For further informations :

Simple Logging Facade for Java (SL4J)

Main Objective : Providing a facade for various logging APIs

For further informations :

X4juli

Main Objective : Extension to J2SE Logging API that provide main parts of log4J, as well as an implementation of Jakarta Commons Logging (JCL) API and Simple Logging Facade for Java (SLF4J) API

For further information :

The Logging Process

The overall logging process is the following :

  1. An application sends logs to a given Logger Object,
  2. The Logger can filter the informations it receives (for instance according to the severity of the alert),
  3. The Logger forwards logging data to the handler,
  4. The Handler can filter the informations it receives (for instance according to the Logger Type, of to the severity of the alert),
  5. The Handler them writes the filtered information to a specific Output Format.

Logging Process

Comparison : Sun J2SE Logging API vs. Apache Log4J

You will find in this section some technical comparison between Sun J2SE Logging API and Log4J. They are meant as technical reference for helping you chose between both libraries, not as a tutorial.

Severity of the Alerts - Warning levels

Warning levels are defined in the Level class in both libraries. They make it possible to indicate the severity of the alert, and thus to filter these alerts.

Warning levels are the following (in growing order of severity) :

  • Sun J2SE Loggin API : All, Finest, Finer, Fine, Config, Info, Warning, Severe, Off.
  • Apache Log4J : All, Debug, Info, Warn, Error, Fatal, Off.

Handlers

Various Handler are defined, that enable to forward loggin information to various output facilities :

  • Sun J2SE Loggin API : StreamHandler (to data stream), ConsoleHandler (to System.err), FileHandler (to a specified file), SocketHandler (to the network), MemoryHandler (to a shared memory).
  • Apache Log4J : console, files, GUI components, remote socket servers, JMS, NT Event Loggers, and remote UNIX Syslog daemons (+ asynchronous logging).

Output Layout

Several Output Layout can be used, according to output type (graphical, text, automated analysis):

  • Sun J2SE Loggin API : SimpleFormatter, XMLFormatter
  • Apache Log4J : SimpleLayout (log type - log message), DateLayout, TTCC (log type, logger name, log message), HTML Layout, PatternLayout (enables fine configurations), XMLLayout.

Security

  • Sun J2SE Loggin API : LoggingPermission Permission for checking if logging is authorized; method getAnonimousLogger for untrusted code and applets; beware of lack of protection against spoofing (log forging), and DoS attacks (excessive log load).
  • Apache Log4J : not specified.

Code Examples

Here are some code example that provide first examples for using several logging libraries : Simple Log, Sun J2SE Logging API, Log4J.

Simple Log

A piece of code fromSimple Log web site.

public class HelloWorld

{

// Create a SimpleLogger:

private static final SimpleLogger log = new SimpleLogger(HelloWorld.class);

public static void

main(String[] argv)

{

try

{

// Use it!

log.entry("main()");

log.debug("About to print 'Hello World!'");

String helloWorldString = "'Hello World!'";

log.dbo(DebugLevel.L6_VERBOSE, "helloWorldString", helloWorldString);

log.db(DebugLevel.L7_LUDICROUS,

"I can't believe this library has a level called 'Ludicrous'!");

System.out.println(helloWorldString);

log.debug("Printed 'Hello World!'");

log.info("Did you get that?");

log.warn("This example is very contrived.");

}

catch (Throwable t)

{

// Just in case...

log.fatal("Something really unexpected dropped by.");

log.dbe(DebugLevel.L1_FATAL, t);

}

log.exit("main()");

}

Matching output is :

Fri 2004/11/26 21:10:32.618|>>>|main|HelloWorld|main()

Fri 2004/11/26 21:10:32.618| |main|HelloWorld|About to print 'Hello World!'

Fri 2004/11/26 21:10:32.618|---|main|HelloWorld|helloWorldString|'Hello World!'

Fri 2004/11/26 21:10:32.618| |main|HelloWorld|I can't believe this library has a level called 'Ludicrous'!

'Hello World!'

Fri 2004/11/26 21:10:32.618| |main|HelloWorld|Printed 'Hello World!'

Fri 2004/11/26 21:10:32.618| |main|HelloWorld|Did you get that?

Fri 2004/11/26 21:10:32.618| |main|HelloWorld|This example is very contrived.

Fri 2004/11/26 21:10:32.618|<<<|main|HelloWorld|main()

Sun J2SE Logging API

Example of a method doSomething() that creates a Logger, and launches a class MyFunnyClass using this logger.

public void doSomething()

throws IOException

{

//create a logger

logger = Logger.getLogger("logging.sun");

fh = new FileHandler("mylog.txt");

logger.addHandler(fh);

// Request that every detail gets logged.

logger.setLevel(Level.ALL);

// Log a simple INFO message.

logger.info("doing stuff");

//lauches a class that use this logger

MyFunnyClass fun = new MyFunnyClass(logger);

fun.execute();

}

doSomething() method.

import java.util.logging.Level;

import java.util.logging.Logger;

public class MyFunnyClass {

Logger log = null;

public MyFunnyClass(Logger log)

{

this.log = log;

}

public void execute()

{

System.out.println("I am funny");

log.log(Level.WARNING,"Funny is Warning U");

}

}

MyFunnyClass class.

Log4J

Two option s exist for configuration : programmatic configuration, or config file based configuration. Config file based configuration enables centralized control of logging, and thus easier control of the logging process. Both are presented here.

This code is partially driven fromLog4J tutorial.

  • Programmatic configuration

As in Sun Logging example API, a method (testWithManualConfiguration) (often not found in monitorized class, MyFunnyClass) contains the configuration of the logger.

public void testWithManualConfiguration()

{

Layout layout = null;

//layout = new TTCCLayout();

layout = new XMLLayout();

//layout = new HTMLLayout();

AppenderSkeleton appender = null;

appender = new ConsoleAppender(layout);

MyFunnyClass fun = new MyFunnyClass(appender);

fun.execute();

}

testWithManualConfiguration method

package logging.log4J;

import org.apache.log4j.AppenderSkeleton;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

public class MyFunnyClass {

Logger logger = null;

AppenderSkeleton appender = null;

public MyFunnyClass(AppenderSkeleton as)

{

appender = as;

logger = Logger.getLogger("logging.log4J.LoggingTest");

logger.addAppender(appender);

logger.setLevel(Level.INFO);

}

public void execute()

{

System.out.println("I am funny");

logger.log(Level.WARN,"Funny is Warning U");

// This request is enabled, because WARN >= INFO.

logger.warn("Low fuel level.");

// This request is disabled, because DEBUG < INFO.

logger.debug("Starting search for nearest gas station.");

// The logger instance barlogger, named "com.foo.Bar",

// will inherit its level from the logger named

// "com.foo" Thus, the following request is enabled

// because INFO >= INFO.

logger.log(Level.INFO,"Located nearest gas station.");

// This request is disabled, because DEBUG < INFO.

logger.debug("Exiting gas station search");

}

}

MyFunnyClass class.

  • Config File Based configuration

No code in necessary outside of the monitorized class. The configuration file is defined in a centralized place, and can be common to all loggers.

# Set root logger level to DEBUG and its only appender to A1.

log4j.rootLogger=INFO, A1

# A1 is set to be a ConsoleAppender.

log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses TTCCLayout.

log4j.appender.A1.layout=org.apache.log4j.TTCCLayout

#log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout

#log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

log4j.properties file.

package logging.log4J;

import org.apache.log4j.AppenderSkeleton;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

public class MyFunnyClass {

Logger logger = null;

AppenderSkeleton appender = null;

public MyFunnyClass()

{

logger = Logger.getLogger("logging.log4J.LoggingTest");

PropertyConfigurator.configure("log4J.properties");

}

public void execute()

{

System.out.println("I am funny");

logger.log(Level.WARN,"Funny is Warning U");

// This request is enabled, because WARN >= INFO.

logger.warn("Low fuel level.");

// This request is disabled, because DEBUG < INFO.

logger.debug("Starting search for nearest gas station.");

// The logger instance barlogger, named "com.foo.Bar",

// will inherit its level from the logger named

// "com.foo" Thus, the following request is enabled

// because INFO >= INFO.

logger.log(Level.INFO,"Located nearest gas station.");

// This request is disabled, because DEBUG < INFO.

logger.debug("Exiting gas station search");

}

}

MyFunnyClass class.



Home-Pierre-Jean-Enseignement-Ressources techniques-Contact

Last update : 22 April 2008 - contact the webmaster