Log4j Tutorial
Log4j Tutorial
Log4j Tutorial
This tutorial explains how to set up log4j with email, files and stdout. It compares XML to
properties configuration files, shows how to change LogLevels for a running application.
Furthermore, we explain best practices on logging and exception handling.
In-depth, detailed and easy-to-follow Tutorials for JSP, JavaServer Faces, Struts, Spring,
Hibernate and EJB
Seminars and Education at reasonable prices on a wide range of Java Technologies, Design
Patterns, and Enterprise Best Practices Improve your development quality
An hour of support can save you a lot of time - Code and Design Reviews to insure that the
best practices are being followed! Reduce solving and testing time
Consulting on Java technologies Get to know best suitable libraries and technologies
2 General
Author: Sebastian Hennebrueder
Date: February, 22th, 2007
Used software and frameworks
Tomcat 5.5
Log4j 1.2.14
3 Beginning
You can download the current version of log4j from the project home page.
http://logging.apache.org/log4j/
Make sure that you use use md5sum to check that the downloaded file is not hacked.
In a linux console you can type the following and compare the number to that from the home page:
md5sum logging-log4j-1.2.14.zip
There are md5sum tools for windows as well. For Firefox you can install the md hash tool
extension and check directly from the download windows.
4 First example
4.1 log4j.properties example
Create a Java project.
Add the log4j.jar to the build path of the project.
Create a file named log4j.properties in the src folder with the following content.
log.trace("Trace");
log.debug("Debug");
log.info("Info");
log.warn("Warn");
log.error("Error");
log.fatal("Fatal");
}
}
Run it. You should see the log messages in the console.
08:50:49,661 DEBUG LogClass:29 - Debug
08:50:49,663 INFO LogClass:30 - Info
08:50:49,663 WARN LogClass:31 - Warn
08:50:49,663 ERROR LogClass:32 - Error
08:50:49,664 FATAL LogClass:33 - Fatal
to
log4j.rootLogger=warn, stdout
Copy the log4j.dtd into the source folder as well. You can find it in the download of log4j. The XML
requires a dom4j.jar which might not be included in older Java versions. You do not need it with
Java 5
You can test your configuration the same way as the former example.
The best up-to-date documentation about available layouts can be found in the API
documentation:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/Layout.html
There you can see that we have DateLayout, HTMLLayout, PatternLayout, SimpleLayout,
XMLLayout as options.
SimpleLayout has no properties to be set. It is simple.
We used PatternLayout in our example and we set a property named ConversionPattern. This
property allows us to define the log output.
%d{ABSOLUTE}
Date in Format Absolute
%5p
%5 defines a right justified print with 5
characters, p prints the priority of the log
message
%c{1}:%L - %m%n
And the other settings. Very simple. They are all
explained in the API.
The options to influence the layout are explained perfectly in the API documentation:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
Custom appenders can be created as well. The log4j download comes with a whole bunch of
samples in the examples directory.
and
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.SimpleLayout"></layout>
</appender>
<root>
<priority value="debug"></priority>
<appender-ref ref="stdout"/>
</root>
</log4j:configuration>
In a web application you might configure a servlet to be loaded on startup to initialize your
configuration.
Keep in mind that this is not required, if you use the default names and folders for the
configuration file.
The following example will check the configuration file in defined intervals and reconfigure log4j if
any changes are found.
We need to create three things:
a) a monitor thread, monitoring the configuration file and reconfiguring log4j if needed
b) a servlet starting and stopping the monitor thread
c) an entry in the web.xml, to initialize the servlet
The following class monitors the logj4 configuration file and checks with the last change date has
changed:
package de.laliluna.logexample;
import java.io.File;
import java.net.URL;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
boolean interruped;
monitor();
}
while (!interruped) {
lastModified = temp;
} else
log.debug("Log4j configuration is not modified");
try {
Thread.currentThread().sleep(checkIntervalMillis);
} catch (InterruptedException e) {
interruped = true;
}
}
log.info("Shutting down log4j monitor");
}
/**
* Sets the interval for checking the url for changes. Unit is
* milliseconds, 10000 = 10 seconds
*
* @param checkIntervalMillis
*/
public void setCheckIntervalMillis(long checkIntervalMillis) {
this.checkIntervalMillis = checkIntervalMillis;
}
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@Override
public void destroy() {
thread.interrupt();
super.destroy();
}
6 Examples
6.1 Rolling File and errors to email
Log messages with Level info to fatal to a file and send messages from error to fatal by email. The
file should be rolled every 100 KB.
You need mail.jar and activation.jar libraries from J2EE to send emails. Further properties of the
SmtpAppender are described here:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/net/SMTPAppender.html
log4j.properties
### file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.maxFileSize=100KB
log4j.appender.file.maxBackupIndex=5
log4j.appender.file.File=test.log
log4j.appender.file.threshold=info
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
#email appender
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
#defines how othen emails are send
log4j.appender.mail.BufferSize=1
log4j.appender.mail.SMTPHost="smtp.myservername.xx"
log4j.appender.mail.From=fromemail@myservername.xx
log4j.appender.mail.To=toemail@myservername.xx
log4j.appender.mail.Subject=Log ...
log4j.appender.mail.threshold=error
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
log4j.appender.mail.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=warn, file, mail
log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
<appender name="file"
class="org.apache.log4j.RollingFileAppender">
<param name="maxFileSize" value="100KB" />
<param name="maxBackupIndex" value="5" />
<param name="File" value="test.log" />
<param name="threshold" value="info"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{ABSOLUTE} %5p %c{1}:%L - %m%n" />
</layout>
</appender>
<appender name="mail" class="org.apache.log4j.net.SMTPAppender">
<param name="SMTPHost" value="smtp.myservername.xx" />
<param name="From" value="email@fromemail.xx" />
<param name="To" value="toemail@toemail.xx" />
<param name="Subject" value="[LOG] ..." />
<param name="BufferSize" value="1" />
<param name="threshold" value="error" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{ABSOLUTE} %5p %c{1}:%L - %m%n" />
</layout>
</appender>
<root>
<priority value="debug"></priority>
<appender-ref ref="file" />
<appender-ref ref="mail"/>
</root>
</log4j:configuration>
<root>
<priority value="debug"></priority>
<appender-ref ref="file" />
<appender-ref ref="mail"/>
</root>
</log4j:configuration>
<root>
<priority value="debug"></priority>
<appender-ref ref="debugfile" />
<appender-ref ref="file" />
</root>
</log4j:configuration>
Hint: If you do not place a configuration file in one of your applications, it will use the Tomcat
log files for logging.
Hint: If you do not want Tomcat to use log4j to log but only your application, you can place
log4j in the WEB-INF-lib directory of your application as well.
You can use log.error(e,e). The second parameter passed an exception and will print the stack
trace into the logfile.
try {
......... snip .......
} catch (SomeException e) {
log.error("Exception Message", e);
// display error message to customer
}
Do not catch an exception, log the stacktrace and then continue to throw it. If higher levels log a
message as well, you will end up with a stacktrace printed 2 or more times into the log files.
This code will erase the stacktrace from the SQLException. This is not recommended, because
you will loose important information about the exception. Better do the following.
try{
... some code
}catch(SQLException e){
throw new RuntimeException("My Exception name", e);
}