Log4J - Logging Java Applications
Course Schedule
Day 1 of 1
Log4j Concepts
-Logger
-Appender
-Layout
Installation of Log4j
Configuring Log4j
Demo examples on logging with Log4j , in core/web java apps
Lab exercises
Course Objectives
Understanding Logging with Log4j
Using Log4j within java applications
Understanding Logging with Log4j
Understanding Logging
What is Logging
Why Logging is required
Logging requirements
What is Log4j
Log4j Concepts
Installation of Log4j
Configuring Log4j
Logging Examples
What is Logging
Logging is writing the state of a program at various stages of its
execution to some repository such as a log file
Why Logging is required
By Logging, simple yet explanatory statements can be sent to
text file, console, or any other repository
A reliable monitoring and debugging solution can be achieved.
Logging requirements
An easy-to-use and efficient open source utility is required to
solve the Logging problems such as ..
- Logging , an overhead for the programmers
- Messy codes due to Logging statements
- Inserting log statements manually is tedious and timeconsuming
- Due to the ongoing upgrading and bug-fixing process for
application code ,managing the log statements in the code is
tedious
What is Log4j
Log4j is an open source logging API for Java
Log4j
- handles inserting log statements in application code and
managing them externally without touching application code,
by using external configuration files
- categorizes log statements according to user-specified
criteria and assigns different priority levels to these log
statements
What is Log4j
Log4j
- lets users choose from several destinations for log statements,
such as console, file, database, SMTP servers, GUI
components etc.
- facilitates creation of customized formats for log output and
provides default formats
Advantages of using log4j
Organizes the log output in separate categories , makes
pinpointing the source of an error easy
Log4j facilitates external configuration at runtime, makes the
management and modification of log statements very simple
Log4j assigns priority levels to loggers and log requests , helps
weed out unnecessary log output and allows only important log
statements to be logged
Log4j Concepts
Log4j is comprised of three main components:
- Logger
- Appender
- Layout
The functionalities of each of these components are accessible
through Java classes of the same name
Users can extend these basic classes to create their own loggers,
appenders, and layouts
Log4j Concepts - Logger
The component logger accepts log requests generated by log
statements
It then sends their output to appropriate destination
These destinations are termed as appenders
The logger component is accessible through the Logger class of
the log4j API
Log4j Concepts - Logger
This class provides a static method Logger.getLogger(name)
This method either
- retrieves an existing logger object by the given name
- or , creates a new logger of given name if none exists
The logger object is then used to .
- set properties of logger component
- invoke methods which generate log requests
debug(), info(), warn(), error(), fatal(), and log()
Log4j Concepts - Logger
Each class in the Java application being logged can have an
individual logger assigned to it or share a common logger with
other classes
Any number of loggers can be created for the application to suit
specific logging needs
It is a common practice to create one logger for each class, with
a name same as the fully-qualified class name
Log4j Concepts - Logger
Log4j provides a default root logger that all user-defined loggers
inherit from
Root logger is at the top of the logger hierarchy of all logger
objects created
If an application class doesn't have a logger assigned to it, it can
still be logged using the root logger
Root logger always exists and cannot be retrieved by name
Logger - ways to create a logger
retrieve the root logger:
Logger logger = Logger.getRootLogger();
create a new logger:
Logger logger = Logger.getLogger("MyLogger");
instantiate a static logger globally, based on the name of the
class:
static Logger logger = Logger.getLogger(test.class);
set the level with:
logger.setLevel((Level)Level.WARN);
Logger - Example
MyClass is a class in com.foo.sampleapp application package
It can have a logger named com.foo.sampleapp.MyClass
Instantiated using
Logger.getLogger("com.foo.sampleapp.MyClass")
Logger - Priority levels
Loggers can be assigned different levels of priorities
priority levels in ascending order of priority
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
There are printing methods for each of these priority levels
mylogger.info("logstatement1");
- generates log request of priority level INFO for logstatement1
Logger - Priority levels
In addition, there are two special levels of logging available
- ALL : has lowest possible rank, is intended to turn on all
logging
- OFF : has highest possible rank,is intended to turn off
logging
The behavior of loggers is hierarchical
Logger - Priority levels
The root logger is assigned the default priority level DEBUG
All loggers inherit priority level from their parent or nearest
existing ancestor logger, which is in effect until they are
assigned another priority level
A logger object can be programmatically assigned a priority level
by invoking its method
- setLevel(Level.x)
Logger - Priority levels
A logger will enable only those log requests with a priority level
equal to or greater than its own
This technique helps prevent log statements of lesser
importance from being logged
This concept is the core of log4j functionality
Logger - Priority levels
The behavior of loggers is hierarchical. The following table
illustrates this
Logger Output Hierarchy
Logger - Priority levels
Few points to make .
A logger will only output messages that are of a level greater
than or equal to it
If the level of a logger is not set it will inherit the level of the
closest ancestor
If a logger is created in the package com.foo.bar and no level is
set for it, it will inherit the level of the logger created in
com.foo
If no logger was created in com.foo, the logger created in
com.foo.bar will inherit the level of the root logger
The root logger is always instantiated and available, the root
logger is assigned the level DEBUG
Priority levels - Example
/* Instantiate a logger named MyLogger */
Logger mylogger = Logger.getLogger("MyLogger");
/* Set logger priority l*/
mylogger.setLevel(Level.INFO);
/* statement logged, since INFO = INFO*/
mylogger.info(" values ");
/* statement not logged, since DEBUG < INFO*/
mylogger.debug(not logged");
/* statement logged, since ERROR >INFO*/
mylogger.error(logged");
Log4j Concepts - Appender
Appender component is interface to the destination of log
statements, a repository where the log statements are
written/recorded
A logger receives log request from log statements being
executed, enables appropriate ones, and sends their output to
the appender(s) assigned to it
The appender writes this output to repository associated with it
Log4j Concepts - Appender
There are various appenders available such as..
ConsoleAppender appends log events to System.out or
System.err using a layout specified by the user. The default
target is System.out
FileAppender appends log events to a file
WriterAppender appends log events to a Writer or an
OutputStream depending on the user's choice
RollingFileAppender extends FileAppender to backup the log files
when they reach a certain size
DailyRollingFileAppender extends FileAppender so that the
underlying file is rolled over at a user chosen frequency
Log4j Concepts - Appender
The various appenders available ...
SMTPAppender sends an e-mail when a specific logging event
occurs, typically on errors or fatal errors
SyslogAppender sends messages to a remote syslog daemon
TelnetAppender specializes in writing to a read-only socket
SocketAppender sends LoggingEvent objects to a remote a log
server, usually a SocketNode
SocketHubAppender sends LoggingEvent objects to a set of
remote log servers, usually a SocketNodes
Log4j Concepts - Appender
An appender is assigned to a logger using the addAppender( )
method of the Logger class, or through external configuration
files
A logger can be assigned one or more appenders that can be
different from appenders of another logger
This is useful for sending log outputs of different priority levels
to different destinations for better monitoring
Log4j Concepts - Appender
A logger also implicitly inherits appenders from its parents
Therefore, the log requests accepted by logger are sent to its
own appenders along with that of all its ancestors. This
phenomenon is known as appender additivity
Appender Creating Appenders
ConsoleAppender appender = new ConsoleAppender(new PatternLayout());
FileAppender appender = null;
try { appender = new FileAppender(new PatternLayout(),"filename"); }
catch(Exception e) {}
WriterAppender appender = null;
try {
appender =
new WriterAppender(new PatternLayout(),new FileOutputStream("filename"));
}
catch(Exception e) {}
Log4j Concepts - Layout
The Layout component defines the format in which the log
statements are written to the log destination by appender
Layout is used to specify the style and content of the log output
to be recorded
This is accomplished by assigning a layout to the appender
concerned
Log4j Concepts - Layout
The Layout component defines the format in which the log
statements are written to the log destination by appender
Layout is an abstract class in log4j API; it can be extended to
create user-defined layouts
Some readymade layouts are also available in log4j package;
they are PatternLayout, SimpleLayout, DateLayout, HTMLLayout,
and XMLLayout
Layout Type of Layouts
HTMLLayout formats the output as a HTML table
PatternLayout formats the output based on a conversion
pattern specified, or if none is specified, the default
conversion pattern
SimpleLayout formats the output in a very simple manner, it
prints the Level, then a dash '-' and then the log message
Installation Log4j
Download log4j-1.2.4.jar from http://logging.apache.org/log4j
Extract the log4j-1.2.4.jar at any desired location and include
its absolute path in the application's CLASSPATH
Now ,log4j API is accessible to user's application classes and can
be used for logging
Running Log4j
To log an application class, follow these steps
1. Import log4j package
2. Instantiate a logger object using Logger.getLogger( )
3. Instantiate layouts to be assigned to appenders
4. Instantiate appenders , passing layout object in constructor
5. Assign the appenders to the Logger invoking addAppender( )
6. Invoke printing methods on Logger to perform logging
Skip 3,4,5 in case of external configuration file used
First Logging Example
package com.patni.sampleapp;
import org.apache.log4j.*;
public class MyClass
{
static Logger myLogger = Logger.getLogger(MyClass.class.getName( ));
Appender myAppender;
SimpleLayout myLayout; Object x;
public MyClass()
{
myLogger.setLevel(Level.INFO); ...
myLayout = new SimpleLayout();
myAppender = new ConsoleAppender(myLayout);
...
myLogger.addAppender(myAppender); ...
}
public void do_something( int a, float b)
{
myLogger.info("Logged since INFO=INFO"); ...
myLogger.debug("not enabled, since DEBUG < INFO");
...
if (x == null)
{myLogger.error("enabled & logged ,since ERROR > INFO");...}
} public static void main(String args[]) { new MyClass().do_something(1,(float)1.2);}
}
Configuring Log4j
The log4j can be configured both programmatically and
externally using special configuration files
External configuration is most preferred, because to take effect
it doesn't require change in application code, recompilation, or
redeployment
Configuration files can be XML files or Java property files that
can be created and edited using any text editor or XML editor,
respectively
Configuring Log4j
The simplest configuration file will contain following
specifications that can be modified, both programmatically and
externally, to suit specific logging requirements
- priority level and name of appender assigned to root logger
- appender's type
- layout assigned to the appender
Programmatic Configuration
In the last example configuration was done programmatically
package com.patni.sampleapp;
import org.apache.log4j.*;
public class MyClass
{
static Logger myLogger = Logger.getLogger(MyClass.class.getName( ));
Appender myAppender;
SimpleLayout myLayout;
public MyClass()
{ myLogger.setLevel(Level.INFO); ...
myLayout = new SimpleLayout();
myAppender = new ConsoleAppender(myLayout);
myLogger.addAppender(myAppender); ...
}
...
Using Configuration Property Files
#A sample configuration file config-sample.properties in Java
#property format
# The root logger is assigned priority level DEBUG and an appender
# named myAppender
log4j.rootLogger=debug, myAppender
# The appender's type specified as ConsoleAppender, i.e. log output
# written to console
log4j.appender.myAppender=org.apache.log4j.ConsoleAppender
# The appender is assigned a layout SimpleLayout
# SimpleLayout will include only priority level of the log
# statement and the log statement itself in log output
log4j.appender.myAppender.layout=org.apache.log4j.SimpleLayout
Using Configuration Property Files
package com.patni.sampleapp;
import org.apache.log4j.*;
public class MyClass
{
static Logger myLogger = Logger.getLogger(MyClass.class.getName( ));
//no constructor required
public void do_something( int a, float b)
{
myLogger.info("Logged since INFO=INFO"); ...
myLogger.debug("not enabled, since DEBUG < INFO");
...
if (x == null)
{myLogger.error("enabled & logged ,since ERROR > INFO");...}
}
}
//Execute the file as
// java -Dlog4j.configuration=config-sample.propertis
com.patni.sampleapp.MyClass
Using Configuration Property Files
Another example
package com.patni.sampleapp;
import org.apache.log4j.*;
import org.apache.log4j.helpers.Loader;
import java.net.*;
public class MyClass
{
static Logger myLogger = Logger.getLogger(MyClass.class.getName( ));
public MyClass()
{
URL url = Loader.getResource("config-sample.properties");
PropertyConfigurator.configure(url);
}
public void do_something( int a, float b)
{
myLogger.info("Logged since INFO=INFO"); ...
myLogger.debug("not enabled, since DEBUG < INFO");
...
if (x == null)
{myLogger.error("enabled & logged ,since ERROR > INFO");...}
}
}
Using Configuration XML Files
A sample configuration file config-sample.xml in XML format
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="myAppender class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.SimpleLayout"/>
</appender>
<root>
<priority value="debug" />
<appender-ref ref="myAppender"/>
</root>
</log4j:configuration>
Using Configuration XML Files
package com.patni.sampleapp;
import org.apache.log4j.*;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
import java.net.*;
public class MyClass
{
static Logger myLogger = Logger.getLogger(MyClass.class.getName( ));
public MyClass()
{
URL url = Loader.getResource("config-sample.xml");
DOMConfigurator.configure(url);
}
public void do_something( int a, float b)
{
myLogger.info("Logged since INFO=INFO"); ...
myLogger.debug("not enabled, since DEBUG < INFO");
if (x == null)
{myLogger.error("enabled & logged ,since ERROR > INFO");...}
...
Using Configuration Files
To use a log4j configuration file, it should be loaded using
following code, preferably inserted in startup class of the
application.
import org.apache.log4j.PropertyConfigurator; //.
PropertyConfigurator.configure("path/to/configuration_file");
// or
import org.apache.log4j.xml.DOMConfigurator; //.
DOMConfigurator.configure(path/to/xml file);
SimpleLayout and FileAppender
Example
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"); } }
SimpleLayout and FileAppender
Example
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"); } }
SimpleLayout and FileAppender
Example
Output of the above example is as shown below
DEBUG - Here is some DEBUG
INFO - Here is some INFO
WARN - Here is some WARN
ERROR - Here is some ERROR
FATAL - Here is some FATAL
HTMLLayout and WriterAppender
Example
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"); } }
HTMLLayout and WriterAppender
Example
Output of the above example is as shown below
PatternLayout and ConsoleAppender
Example
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 = ogger.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"); } }
PatternLayout and ConsoleAppender
Example
Output of the above example is as shown below
Log4j Initialization in Web Containers
Most web containers load the classes of a web-application in a separate
class loader
You may have multiple copies of log4j classes loaded simultaneously
Each such copy will go through the default log4j initialization procedure
Different class loaders may load distinct copies of the same class
These copies of the same class are considered as totally unrelated by
the JVM
Placing logj-VERSION.jar in WEB-INF/lib directory of your webapplication will cause log4j classes to be loaded/unloaded whenever
your web-application is loaded/unloaded
Default Initialization under Tomcat
web-server environment
Log4j.jar is placed in the WEB-INF/lib directory of each of your
web-applications
Place the log4j.xml or log4j.properties under the WEBINF/classes
Log4j will find the properties file and initialization itself
Conclusion : Using log4j
The log4j API provides a means for inserting useful and
manageable log statements in the application code
Resources
Log4j is freely available to download from The Apache Jakarta
Project Web site http://logging.apache.org/log4j/
For documentation of the log4j API visit
http://jakarta.apache.org/log4j/docs/api/index.html
Thank you