Log4j Tutorial

Filed Under: Java

Welcome to log4j tutorial. Log4j is most used logging framework in java applications. In this log4j tutorial, we will go through log4j basics, it’s configuration and then see it in action in java standalone application and then in java web application.

Log4j Tutorial

Before we start with log4j examples, first step is to get log4j jars. There are many ways to download log4j jars.

  1. My favourite is to get all the dependencies through Maven. You can add below dependencies in your pom.xml file to get log4j jar.
    
    <dependency>
    	<groupId>log4j</groupId>
    	<artifactId>log4j</artifactId>
    	<version>1.2.17</version>
    </dependency>
    
  2. If you are using gradle, then add dependency as: 'log4j:log4j:1.2.17'
  3. If you are not using any build tools, you can download the log4j jar from Apache Log4j Official page and include into your project classpath.

Log4j Configuration

Log4j supports both properties based as well as XML based configuration. Here I will use XML based configuration, you can see log4j properties based configuration in the linked post.

log4j.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
	debug="false">

	<!-- console appender -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p %c{1} - %m%n" />
		</layout>
	</appender>
	
	<!-- rolling file appender -->
	<appender name="file" class="org.apache.log4j.RollingFileAppender">
		<param name="File" value="logs/main.log" />
		<param name="Append" value="true" />
		<param name="ImmediateFlush" value="true" />
		<param name="MaxFileSize" value="10MB" />
		<param name="MaxBackupIndex" value="5" />

		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" />
		</layout>
	</appender>


	<logger name="com.journaldev.log4j" additivity="false">
		<level value="DEBUG" />
		<appender-ref ref="file" />
		<appender-ref ref="console" />
	</logger>

	<logger name="com.journaldev.log4j.logic" additivity="false">
		<level value="INFO" />
		<appender-ref ref="file" />
	</logger>

	<root>
		<priority value="DEBUG" />
		<appender-ref ref="file" />
		<appender-ref ref="console" />
	</root>

</log4j:configuration>

The most important part of log4j configuration files are:

  1. Appenders: Here we define the logging strategy, such as which type of appender class to use, for example org.apache.log4j.ConsoleAppender or org.apache.log4j.RollingFileAppender. org.apache.log4j.PatternLayout is used to define the logging pattern. %d %d{Z} [%t] %-5p (%F:%L) - %m%n will append time, thread, logging level, class name with line number. We can define any number of appenders in our log4j configuration file.
  2. logger: It’s used to provide mapping between java packages/classes with appenders and logging levels. As you can see, multiple appenders can be used with a single logger. If multiple logger matches with the java class package, more specific one is used.
  3. root: This is used when there is no logger defined for java packages. For example, if have some classes in com.journaldev.beans package then it won’t match with any logger. So root logger will be used for logging configurations.

Once log4j configuration file is ready, we have to configure it in the code before we can actually start logging. Below is the way to do that.


//for XML based configuration
DOMConfigurator.configure("log4j.xml");
//for properties based configuration
PropertyConfigurator.configure("log4j.properties");

Note that if our log4j configuration file name is log4j.xml or log4j.properties, then we can skip this step because log4j tries to automatically load these files from classpath.

Java Log4j usage

Now let’s see how they can be used in the code. We have created two classes for our above defined loggers.


package com.journaldev.log4j.main;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

import com.journaldev.log4j.logic.MathUtils;

public class Log4jExample {

	static{
		init();
	}
	
	private final static Logger logger = Logger.getLogger(Log4jExample.class);
	
	public static void main(String[] args) {

		logger.debug("My Debug Log");
		logger.info("My Info Log");
		logger.warn("My Warn Log");
		logger.error("My error log");
		logger.fatal("My fatal log");
		
		MathUtils.add(4,5);
		MathUtils.add(40,50);
		MathUtils.add(1,5);
		
	}

	/**
	 * method to init log4j configurations
	 */
	private static void init() {
		DOMConfigurator.configure("log4j.xml");
	}

}

We can create a final Logger instance once and then reuse it across the class. Notice that I am configuring log4j in init() method that is called at the time of class loading in static block.


package com.journaldev.log4j.logic;

import org.apache.log4j.Logger;

public class MathUtils {

	private static final Logger logger = Logger.getLogger(MathUtils.class);
	
	public static int add(int x, int y){
		logger.debug("inputs are:"+x+", "+y);
		return x+y;
	}
}

Now when we run above main method, we will get below logs in main.log file.


2016-05-12 21:22:44,610 +0530 [main] DEBUG (Log4jExample.java:18) - My Debug Log
2016-05-12 21:22:44,611 +0530 [main] INFO  (Log4jExample.java:19) - My Info Log
2016-05-12 21:22:44,611 +0530 [main] WARN  (Log4jExample.java:20) - My Warn Log
2016-05-12 21:22:44,612 +0530 [main] ERROR (Log4jExample.java:21) - My error log
2016-05-12 21:22:44,612 +0530 [main] FATAL (Log4jExample.java:22) - My fatal log

You will also see logs printing into console.


DEBUG Log4jExample - My Debug Log
INFO  Log4jExample - My Info Log
WARN  Log4jExample - My Warn Log
ERROR Log4jExample - My error log
FATAL Log4jExample - My fatal log

Notice that there are no logs getting printed from MathUtils class, it’s because it’s logger level is INFO that is higher than DEBUG. Just change it’s logging level to DEBUG like below.


<logger name="com.journaldev.log4j.logic" additivity="false">
	<level value="DEBUG" />
	<appender-ref ref="file" />
</logger>

Now when you will run the program again, main.log file will have below logs too.


2016-05-12 21:23:56,151 +0530 [main] DEBUG (MathUtils.java:10) - inputs are:4, 5
2016-05-12 21:23:56,151 +0530 [main] DEBUG (MathUtils.java:10) - inputs are:40, 50
2016-05-12 21:23:56,153 +0530 [main] DEBUG (MathUtils.java:10) - inputs are:1, 5

That’s it for using log4j in java standalone application. Below image shows the final project structure in eclipse.

log4j tutorial

You can download this project from below link.

Log4j Java Web Application

Now let’s see how to use log4j in java web application. Create a “Dynamic Web Project” and then convert it to Maven. Below image shows the final structure of the project.

log4j java web application project

Below is the log4j configuration file.

my-log4j.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
	debug="false">

	<!-- console appender -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p %c{1} - %m%n" />
		</layout>
	</appender>
	
	<!-- rolling file appender -->
	<appender name="file" class="org.apache.log4j.RollingFileAppender">
		<param name="File" value="${catalina.home}/logs/main.log" />
		<param name="Append" value="true" />
		<param name="ImmediateFlush" value="true" />
		<param name="MaxFileSize" value="10MB" />
		<param name="MaxBackupIndex" value="5" />

		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" />
		</layout>
	</appender>


	<logger name="com.journaldev.log4j" additivity="false">
		<level value="DEBUG" />
		<appender-ref ref="file" />
		<appender-ref ref="console" />
	</logger>

	<root>
		<priority value="DEBUG" />
		<appender-ref ref="file" />
		<appender-ref ref="console" />
	</root>

</log4j:configuration>

More of less it’s similar to earlier configuration, except that we are injecting catalina.home variable to generate log files into tomcat logs directory.

Since we have to configure log4j before it’s being used, we can load it by defining a ServletContextListener as below.


package com.journaldev.log4j.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.apache.log4j.xml.DOMConfigurator;

@WebListener
public final class Log4jInitListener implements ServletContextListener {

    public Log4jInitListener() {
    }

    public void contextDestroyed(ServletContextEvent paramServletContextEvent)  { 
    }

    public void contextInitialized(ServletContextEvent servletContext)  { 
    	String webAppPath = servletContext.getServletContext().getRealPath("/");
	String log4jFilePath = webAppPath + "WEB-INF/classes/my-log4j.xml";
    	DOMConfigurator.configure(log4jFilePath);
    	System.out.println("initialized log4j configuration from file:"+log4jFilePath);
    }
	
}

Notice the use of ServletContext to get the full path of log4j configuration file. This is something additional we have to do because we don’t know the full path of the log4j file at runtime and we don’t want to hardcode it either.

Below is a simple Servlet class using Logger to log some messages.


package com.journaldev.log4j.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
	
	private static final Logger logger = Logger.getLogger(MyServlet.class);
	
    public MyServlet() {
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String name = request.getParameter("name");
		logger.info("Name parameter value = "+name);
		
		PrintWriter out = response.getWriter();
		
		out.append("Served at: ").append(request.getContextPath());
		out.append("\n\nHello "+name);
		out.flush();
	}

}

Just export the project as WAR file and then deploy into Tomcat server, below image shows when we call the servlet in browser.

log4j servlet example

You will get below kind of logs in tomcat logs directory main.log file.


pankaj:logs pankaj$ tail -f main.log 
2016-05-12 21:46:33,038 +0530 [http-nio-8080-exec-2] INFO  (MyServlet.java:29) - Name parameter value = Pankaj

Since we are also logging to console that goes to catalina.out file, you will find below logs in catalina log file.


pankaj:logs pankaj$ tail -f catalina.out 
INFO  MyServlet - Name parameter value = Pankaj

That’s it for a quick tutorial on log4j, you can download Log4j Web Application example project from below link.

References:

Comments

  1. Varun Awasthi says:

    Hi Pankaj, Thanks for the tutorial . I downloaded the sample project for Web-APP and found an issue . The path for my my-log4j.xml is not correctly set in Log4JInitializer.java .A (/ ) is missing

  2. Raneesh says:

    Yo man thanks

  3. Sameera says:

    Informative Example, Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages