Advertisment

Smart Logging with Log4j

author-image
PCQ Bureau
New Update

During the software development life cycle, you would be tempted to write the state of a program at various stages of its execution to some repository such as a log file, an

e-mail system, or a persistent database for debugging and monitoring your applications. This article is an introduction to Log4j, an open source logging tool developed and distributed under the Jakarta Apache Project. We will start by exploring the architecture of Log4j. Next, we will use an example to demonstrate how to 



insert log statements in a J2EE Web application.

Advertisment
Direct Hit!
Applies to: Java Developers
USP: Insert log statements in your J2EE web app and configure them externally
Primary Link:

http://logging.apache.org/log4j/docs
Google keywords: Log4j, Logging
On PCQEssential CD:

system\labs\log4j

Log4j allows developers to configure log statements at runtime with flexibility. Log4j can prove to be an asset by providing the 



developer with detailed context of a running application. It is certified by the open-source community and has evolved as a 


de-facto logging and debugging tool.

Setting up Log4j 



Download the latest version of Log4j distribution in ZIP format from the PCQEssential CD and unpack it. Inside the dist 



directory of your log4j home, copy the log4j-1.2.11.jar file to the WEB-INF/lib directory of your Web app's root directory.


Why use log4j?

Advertisment

There are other logging tools available, including the log API bundled in JDK 1.4 (java.util.logging). Log4j scores over all other logging APIs because of its ability to provide runtime control over logging without having to touch the source code or binaries. Log4j is purely written in Java. Once the log statements have been

inserted into the code, they can be controlled with external configuration files without any human intervention. Moreover, log statements can remain in shipped code without incurring a heavy performance cost. 

Logged statements on Tomcat 5 console window for our simple application that logs the IP and domain of clients that start a session

Also it supports inheritance in loggers. Using a logger hierarchy you can control which log statements are output (filtering). This in-turn helps to reduce the volume of logged output and minimize the cost of logging. 

Advertisment

Basic components



There are three aspects of log4j: logger, appender and layout. Let's discuss these in some detail.

Logger: A logger is an entity that your application program will use to log messages. Each class in your

application can have an individual logger or a common logger. The root logger is the super logger that all

loggers inherit from. Each logger in log4j is assigned a level. If you don't assign a level to a logger yourself, log4j automatically assigns to your logger the level of the parent logger. The

default level of the root logger is DEBUG. 

Following are the different logging levels available in log4j. We have listed these in ascending order

of priority):

Advertisment

DEBUG: logs messages while developing and debugging an application



INFO: helps in monitoring the progress of an application


WARN: represents potentially harmful situations


ERROR: indicates recoverable errors


FATAL:
indicates errors that will cause an application to crash

Requested servlet creates a session, and logs the domain name and client's IP address 

A logging request is said to be enabled if its priority level is higher than or equal to the priority of its Logger. 

Advertisment

Appenders and layouts: Log4j allows logging statements to print to multiple output destinations called appenders. The 



target of the logged output can be the console, a file, an OutputStream, a GUI component, a remote socket server, a remote Unix Syslog daemon, or many other output targets. With log4j you can also control the layout of your log statements. You can specify
numerous different layouts for the messages using the log4j configuration file.

Sample application



Our sample application is pretty simple, it consists of two listener classes, a servlet and a property configuration file. We will log the IP address and domain name of the client whenever a session is created. Below is a brief explanation of the application files. 

Configuration File



This is a text file with name/value pairs for configuring log4j elements such as loggers, appenders and layouts. You can either use an XML file or a Java properties file, as shown here.

Advertisment

log4j.rootLogger=DEBUG, cons



log4j.logger.com.pcquest=, myAppender

The configuration file is named MyLogger.properties, and placed inside the Web app's WEB-INF/classes directory. This file creates a logger named com.pcquest, which inherits the root

logger's DEBUG level and console appender. It will use an appender named myAppender. It is worth noticing that the logger names are based on Java package names, so the complete name of our

appender is com.pcquest.myAppender. The 'myAppender' is a rolling file appender, a log file that automatically creates a backup file when the original log reaches a certain size. Here is how the log file is configured in the log4j properties file.

og4j.appender.myAppender.File=D:/log/uservisits.log

Advertisment

ContextLogger.java: This listener class implements the ServletContextListener interface, so that it's notified whenever a context is created and destroyed for the Web app. Inside the

contextInitialized() lifecycle method, we begin by reading the log4j properties file which is set inside the DD (Deployment Descriptor), web.xml file.

Next we create a new logger named after the class as:

log=Logger.getLogger(ContextLogger.class);

The static getLogger(Class className) method creates a logger named after the class (com.pcquest. ContextLogger). This logger inherits the appender and layout that the properties file set up for com.pcquest, because the new logger's name has com.pcquest as a prefix. 

SessionListener.java: This class implements HttpSessionListener, to get notified whenever a session is created or invalidated by the container. Inside its default constructor, we get a reference to the logger object, its logger is also named after the package name as com.pcquest.SessionListener. Then, in the sessionCreated lifecycle method we log the session ID created by the container as: 

log.info("A session has been created for this web app it's ID is : "+se.getSession().getId());

LogTesterServlet.java: This servlet creates a child logger (com.pcquest.LogTesterServlet) named after the full qualified class name inheriting from the com.pcquest logger. Inside the

doGet() lifecycle method we create a session and log the domain name and IP address of the client. The code for the same looks like that shown below:

log.info("Client host name="+req.getRemoteHost()+" with IP

address="+req.getRemoteAddr());

Logged output



Log4j supports multiple output appenders per logger. 

Appenders are inherited additively from the logger hierarchy. This means that if the root logger has been configured to append to the console and your child logger appends to a file, then all the logging requests will print to the file and on the console, as in our example. 

Conclusion



Log4j, thus, dramatically cuts down on logging overheads in the applications that you work with. This also reduces the code clutter, and at the same time minimizes the performance loss in a production application with these debugging statements.

Kunal Jaggi

Advertisment