You are on page 1of 6

Log4j Tutorial

Who am I? My name is Veera. Im a Java developer. I have been developing web applications in Java for the past 5 years. Almost in all my projects, I have used Log4j for logging. I have shared my knowledge in my blog in the past years. Now I compiled all my articles into a single eBook so that you can easily get to know about Log4j. I hope youll find this work useful. If you like, You can also contribute by donating a small amount!

Donate using PayPal


Blog: http://veerasundar.com/blog Contact: veera.k.sundar@gmail.com

Introduction:
Log4j is a flexible logging library, an open source project from Apache. Using Log4j, we can replace the debugging print line statements, like System.out.println(Value is + someVariable), with a configurable logging statement like logger.debug(Value is + someVariable). The advantage in using Log4j is, if you do not want to print the debugging print lines in production application, you can easily switch them off using Log4j configuration file log4j.properties. Log4j is not just for logging into console. You can log to files, emails (SMTP server), a remote server or a database. You can easily switch between the logging destinations, switch off logs of certain levels or format the log message as per your requirement. The frameworks is such flexible.

Add Log4j to your Java project:


1. Download the latest Log4j distribution from Apache website (at the time of this article is written, the latest version of Log4j is 1.2). 2. Add the downloaded log4j-xxx.jar file to your projects CLASSPATH. For a Java web application you can place the JAR file in WEB-INF/lib folder. For a Java application, you can place the JAR anywhere but remember to add the JAR to CLASSPATH. 3. Now create log4j.properties file in the root directory of your source folder. Usually, it will be src. Now youve just enabled the Log4j support to your project. In next step, youll configure it to dance to your beats.

No more System.out.println():
Lets make Log4j to write log messages to console. Yeah! you are going to replace the age-oldbullet-proof-debugging-method i.e. System.out.println(). Before you do that, you need to understand what goes in the log4j.properties file. You will be using this file mainly to configure the below things: Appender this is the class file which does the actual logging. It could be a simple Console appender which dumps the log messages to stdout (screen) or a file appender, which sends the log messages to a log file or JDBC appender. Layout is nothing but how the log message is formatted. This format is very similar to C language's printf function formatting. Logger a logger ties the appender with the log messages that are coming from the Java application. Basically, a logger tells that the log messages from these packages

should go to some appender which will log the message in the defined layout. That said, now open the log4j.properties file and type-in (remember, TYPE IN) the below code in it. #define the console appender log4j.appender.consoleAppender = org.apache.log4j.ConsoleAppender # now define the layout for the appender log4j.appender.consoleAppender.layout = org.apache.log4j.PatternLayout log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n # map console appender as a root logger,to log all messages to this appender log4j.rootLogger = DEBUG, consoleAppender The above configuration tells Log4j to log all messages to a console appender. When you run your program, you will see the log messages displayed on your console, just how your System.out.println() would do. To test this, create a Java file, put the below code and run it. public static void main(String args[]){ private static Logger logger = Logger.getLogger(MyclassName.class); logger.debug("Hello World"); }

Lets log to files:


Logging into console if fine for development. But you cant keep monitoring your console when your application goes live. So, you should log your messages to a file. Lets do that. Open the log4j.properties and type-in this code. log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender log4j.appender.rollingFile.File=D:/myapp/mylog.log log4j.appender.rollingFile.MaxFileSize=2MB log4j.appender.rollingFile.MaxBackupIndex=2 log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout log4j.appender.rollingFile.layout.ConversionPattern=%p %t %c - %m%n log4j.rootLogger = INFO, rollingFile

What you just did was simple. Instead of using a console appender, we used a file appender. Theres a simple FileAppender is available to you. But here, youve used a advanced version of it, which creates a new log file everytime the file size reaches the mazimun size you set (which is 2 MB in our case). Cool huh!?

Log different package log messages to different files:


OK. We logged all our messages into a single log file. But what if you want to log a messages from different packages to different log files? Can it be done!? Yes, my dear friend! This is very simple to do in Log4j. Log4j has a concept called Category using which you can classify a package as a category and assign a appender to that category alone. To make this point clear, consider that we have the below Java classes in our project: com.someapp.service.myservice.SomeServiceClass.java com.someapp.dao.SomeDaoClass.java Now, if you want to send the log messages from SomeServiceClass.java to service.log and SomeDaoClass.java to dao.log files respectively, then the log4j configuration would be something like this: log4j.category.com.someapp.service = INFO, serviceFileAppender log4j.category.com.someapp.dao = INFO, daoFileAppender log4j.rootLogger = INFO, defaultAppender #configure the appenders here ... As you can see in above snippet, we are defining two categories for the service and dao packages and associating them with the appenders serviceFileAppender and daoFileAppender respectively. These two appender are just any file appenders configured somewhere in the same log4j.properties file. So, all the log messages that coming from the classes which resides under the com.someapp.service package will go to the serviceFileAppender, which in turn will go to service.log. The same logic applies to dao.log also. Apart from these two logs, we also defined the defaultAppender as the root logger. Means, the log messages from all the packages will go to defaultAppender, including the service and dao log messages. Yes! with the above configuration, the service and dao log messages will be there in two places. In their respective log appenders + the defaultAppender. WHAT!? Why same log message in TWO different places? Additivity is your solution to avoid this.

Get addicted to Additivity:


Now imagine this scenario: Youve configured a total of three appenders in your application. One for the package com.demo.moduleone and one for com.demo.moduletwo and one root logger for com.demo. The configuration will look something like this (showing only the appender configuration, excluding other details) log4j.category.com.demo.moduleone = INFO, moduleOneFileAppender log4j.category.com.demo.moduletwo = INFO, moduleTwoFileAppender log4j.rootLogger = INFO, rootFileAppender In Log4j, all the loggers are following some hierarchies. ie, A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger. So, as per the hierarchy, our rootFileAppender is the parent appender for both moduleOneFileAppender and moduleTwoAppender. So, all the log messages that coming to the child loggers will be propagated to the parent appenders too. So, in our scenario, the log messages from the package com.demo.moduleone will be sent to the moduleOneFileAppender as well as the rootFileAppender. The same applies to the com.demo.moduletwo also. This leads to write the same log message in two different location. So, how to avoid this redundancy? Simply set the additivity for a logger to false and now the log messages which are coming to that logger will not be propagated to its parent loggers. So, our new configuration file would be: log4j.category.com.demo.moduleone = INFO, moduleOneFileAppender log4j.additivity.com.demo.moduleone = false log4j.category.com.demo.moduletwo = INFO, moduleTwoFileAppender log4j.additivity.com.demo.moduletwo = false log4j.rootLogger = INFO, rootFileAppender With the above configuration, the log messages from the com.demo.moduleone will go to the moduleOneAppender only and the rest of the log messages will go to the rootFileAppender.

Bonus: Creating a new log file each time your programs runs:
If you want your program log messages to a new log file each time it runs, you need to create a

custom Log4j Appender. Heres a detailed article about this: How to create a new log file for each time the application runs?

Bonus: Logging DEBUG and INFO log level messages to separate files:
Do you want to write different log levels into different files? You should read this article to see how to do that. Writing different log levels in different log files.

- The End -

Who am I? My name is Veera. Im a Java developer. I have been developing web applications in Java for the past 5 years. Almost in all my projects, I have used Log4j for logging. I have shared my knowledge in my blog in the past years. Now I compiled all my articles into a single eBook so that you can easily get to know about Log4j. I hope youll find this work useful. If you like, You can also contribute by donating a small amount!

Donate using PayPal


Blog: http://veerasundar.com/blog Contact: veera.k.sundar@gmail.com

You might also like