Can you even count the number of times you've setup Log4j in a web application? This is one of those tasks we find ourselves doing over and over again, yet each time, we have to dig up old code to remind ourselves how it's done. Hopefully, this page can save you some of that hassle. It provides a quick guide for setting up Log4j in a web application and is intended for those who are already familiar with Log4j and just need a rapid reminder.
Step 1 - Download the Log4j library
Download the latest binary release from the Apache Logging Services site
.
Step 2 - Import the jar file into your web project
Import the log4j jar file into your project WEB-INF/lib directory so that it will be on the classpath for your web application.
You might instead put the jar file on your server in some globally recognizable location so that more than one application can have visibility to the same lib. For example, in WebSphere AppServer, you might put it under <WebSphere install>/AppServer/lib. You can also make it available to all portlets in a WebSphere Portal instance by putting it in <WebSphere install>/PortalServer/shared/app. Always look for some existing version of the log4j library first. You may either already have it or you may wish to use a newer release; you do not want to end up with two versions of the log4j lib in the same directory, but with different names.
Step 3 - Import some existing (starter) Log4j XML configuration files
Yes, you can use a simple Java properties file to configure Log4j, but it's a lot less flexible than the XML configuration format; don't be a wimp!
Create a properties folder and make it recognizable by the IDE as a source folder
I like to do my Log4j configuration in a separate properties folder outside of the normal src folder in Eclipse or Rational Software Architect. It keeps the project clean and it can also be useful to the formal build system. Here's how:
- In Eclipse or Rational, right click on the project node.
- Select New -> Folder and create a new folder called 'properties'. Make sure the folder is in the root of your project, not in the src folder.
- Now we want the properties folder to get recognized as a source folder. Right click the project node and select Properties.
- In the Properties dialog, select Java Build Path -> Source tab
- Click Add Folder, choose the properties folder, and click OK.
Import Log4j DTD and example (starter) XML configuration into properties folder
Next, you need to import two files into your properties folder. I am including versions here that you can use as a starting set:
You may also want to grab this simple console test for quick confirmation that you've got the logging set-up properly. From within eclipse, you can right-click this java file and choose Run As.. > Java Application. That will print several log messages to the console to give you confirmation.
Step 4 - Customize the XML configuration just enough to test
Go ahead and open up the log4j.xml file. If you used the starter provided in the link above, you'll find the following:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" > <log4j:configuration> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <!-- <param name="ConversionPattern" value="[%d{ISO8601}] %-5p [%c] %m %n" /> --> <param name="ConversionPattern" value="%-5p [%c] %m %n" /> </layout> </appender> <appender name="STDERR" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.err" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{ISO8601}] %-5p [%c] %m %n" /> </layout> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="LevelMin" value="ERROR" /> <param name="LevelMax" value="FATAL" /> </filter> </appender> <appender name="SSB_ROLLING_FILE" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="D:/ssb.log" /> <param name="Append" value="true" /> <param name="MaxFileSize" value="500KB" /> <param name="MaxBackupIndex" value="5" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{ISO8601}] %-5p %m%n" /> </layout> </appender> <!-- --> <!-- Declare the SMTPAppender --> <!-- --> <!-- <appender name="EMAIL" class="org.apache.log4j.net.SMTPAppender"> <param name="BufferSize" value="512" /> <param name="SMTPHost" value="smtp.mail.yahoo.com" /> <param name="From" value="whoever@wherever.com" /> <param name="To" value="whoever@wherever.com" /> <param name="Subject" value="[SMTPAppender] Application message" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{ISO8601}]%n%n%-5p%n%n%c%n%n%m%n%n" /> </layout> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="LevelMin" value="FATAL" /> <param name="LevelMax" value="FATAL" /> </filter> </appender> --> <logger name="com.burlesontech.ssb" additivity="false"> <level value="trace" /> <appender-ref ref="SSB_ROLLING_FILE" /> <appender-ref ref="STDOUT" /> </logger> <!-- ** --> <root> <level value="ERROR" /> <appender-ref ref="STDERR" /> <!-- <appender-ref ref="EMAIL" /> --> </root> </log4j:configuration>
Now, this is really simple even though it may look a bit daunting at first. We've got two console appenders (OUT and ERR) and we have one file appender that will write our log statements to disk. In this way, we get console logging for development and file logging for deployment. There's also an email appender, but it is commented out for now. I would keep it if I were you; you may later wish to receive email notifications if your application throws errors.
- Find SSB_ROLLING_FILE and change the name to reflect your own application's name. Change both the declaration and the reference to it in the logger that is defined later in the file.
- In the file appender, customize the File parameter so that the logs will get written to a path of your own choosing.
- The first logger defined is set to log on anything under the package com.burlesontech.ssb. Change that to reflect some parent package in your own application.
- Save the file (duh!)
Step 5 - Put logging code in your classes
The last thing you need to do is drop some logging code in a class and test this whole setup.
Add the following to the imports section of your java code:
import org.apache.log4j.Logger;
Add the following at the top of your class in the global section (just under the line that declares your class public class Whatever extends Whatever {. Change the name of the class in the getLogger method call, of course. Name it the same as the class you're dropping this code into.
static Logger log = Logger.getLogger(MyClassName.class);
Apache Commons Logging
If you want to use Apache commons logging, instead add the following imports:
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
And then declare the logger like so:
private static final Log log = LogFactory.getLog(MyClassName.class);
Throw some logging statements in your code somewhere where you know they'll be fired right away when you run your app. For example:
log.trace("Hello World!"); log.debug("How are you today?"); log.info("I am fine."); log.error("I am programming."); log.warn("I love programming."); log.fatal("I am now dead. I should have been a movie star.");
Step 6 - Run your app and make sure it works
Finally, run your app and make sure it works. You should see log lines in your console and in the file where you setup your appender. If it doesn't work, just review these steps a little more carefully and fiddle with it.
| Name | Size | Creator (Last Modifier) | Creation Date | Last Mod Date | Comment | ||
|---|---|---|---|---|---|---|---|
| 2 kB | Cody Burleson | Jun 27, 2008 | Jun 27, 2008 | ||||
| 5 kB | Cody Burleson | Jun 27, 2008 | Jun 27, 2008 | ||||
| 2 kB | Cody Burleson | Sep 11, 2008 | Sep 11, 2008 |
Comments (3)
Aug 10
Anonymous says:
Hi, The code in step 5 is an example of common bad coding practice. All trace an...Hi,
The code in step 5 is an example of common bad coding practice. All trace and debug log statements must be written this way:
If in production code expected to be run on FATAL level, all statements should be enclosed within corresponding isXXXEnabled.
Aleksey.
Aug 08
Anonymous says:
I agree, it should be done this way if you have more expensive logging than this...I agree, it should be done this way if you have more expensive logging than this example.
The example just prints a plain string, no expensive things, log4j will stop directly in the Logger itself (where the same if is repeated).
If on the other hand you do string concatenation or toStrings that are more expensive, you'll first have to check if the level is enabled.
Aug 10
Cody Burleson says:
The example in step five is intended only as a step to test quickly that your lo...The example in step five is intended only as a step to test quickly that your logging has indeed been setup properly and is working in your application. I agree also that it is good to practice guarded logging in your production code.
"Guarded logging" is a pattern that checks to see if a log statement will result in output before it is executed. Since the logger itself makes this check, it may seem redundant to do this for every call. However, as almost every logging call creates String objects, it is critical. The accumulation of these Strings causes memory fragmentation and unnecessary garbage collection. Garbage collection, while beneficial, also produces significant performance loss. To reduce this as much as possible, always guard logging statements with a severity less than SEVERE. Since SEVERE is always expressed by the logger, these do not need a guard. Here is an example: