Monday, April 21, 2014

Using Logback logging framework in Eclipse - Simple example/tutorial

Logback is a logging architecture that is very popular and customizable. It is intended as a successor of log4j. Long story short, use logback instead of log4j for your new projects. (The author is the same for both log4j and logback frameworks. Look at the links at the end of the tutorial if you are interested in finding out the history, which framework is better etc.).

In this tutorial, we will learn on how to setup logback in a Java project, how to create appenders and how to write the logs to a specific location. This tutorial uses RSA (Rational Software Architect), but you can use Eclipse or any other IDE of your choice.

Go to File -> New -> Web -> Dynamic Web Project


 Give it a name and add the project to an EAR using the Wizard screen as shown below. (If you are not using Websphere, you can use any other server or any other Project wizard of your choice)


Click Next, Next and click Finish (you can check the ‘Generate web.xml deployment descriptor’ if you want to)

A new Web project is created by now with the above steps.

To run logback in your project, we need a façade for the logback framework. We use slf4 as the façade in this example.

JAR files needed (Use one of the three methods mentioned below to get the jar files)

We need to have the following jar files in your Project’s build path
  1. slf4j-api.jar
  2. logback-classic.jar
  3. logback-core.jar


 Method 1: If you have Ivy setup, you can add the following dependencies (Refer to http://runningexample.blogspot.com/2014/02/Using-Ivy-for-dependency-management.html on how to setup Ivy. I STRONGLY RECOMMEND SETTING UP IVY ONCE AND FOR ALL) 

<dependency org="org.slf4j" name="slf4j-api" rev="1.7.5"  />
<dependency org="ch.qos.logback" name="logback-classic" rev="1.0.13" transitive="false"/>
<dependency org="ch.qos.logback" name="logback-core" rev="1.0.13" transitive="false"/>
 Method 2: If you have Maven setup, you can add the following dependencies (Refer to http://runningexample.blogspot.com/2011/01/apache-maven-tutorial-basic-setup.html on how to setup Maven)

<properties>
 <slf4j.version>1.7.5</slf4j.version>
 <logback.version>1.0.13</logback.version>
</properties>

<dependencies>

 <dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>${slf4j.version}</version>
 </dependency>

 <dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>${logback.version}</version>
 </dependency>

 <dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-core</artifactId>
  <version>${logback.version}</version>
 </dependency>

</dependencies>
 Method 3: Download the jars manually from:
      http://www.slf4j.org/download.html  (this is for slf4j-api.jar)
      http://logback.qos.ch/download.html (this is for the two logback jars logback-classic and logback-core)

     Now that the jar files are in the classpath, let’s write a simple servlet that says “Hello World”. 

       Using File -> New -> Servlet, create a new Servlet and name it LogbackTestServlet




    Add the following imports to the created Servlet.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

      Create a new Logger object using the following line of code at the beginning of the class
private static final Logger logger = 
LoggerFactory.getLogger(LogbackTestServlet.class);

     Add the following code to the doGet method in the Servlet
logger.debug("Inside the doGet method");
String message = "Hello World";
// Set response content type
response.setContentType("text/html");

logger.debug("Before writing the output");
// Actual logic goes here.
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");

    The Servlet class should look something like this




    We created the code to write the log statements.
    Now comes the part where we need to create the logback configuration file (where the log levels, log location etc. are specified)

     For logback to run, the ONLY file we need to have is logback.xml, that we need to place is on the classpath (In this example, we will create a new file called logback.xml at the src level of the Project Structure in the Web Project).

    Create a new file using File -> New -> File and name it logback.xml. See the below picture to see where the file is created in the Package Explorer




     Copy paste the following code into that file.  (SNIPPET 1)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>LogbackTutorial.log</file>
    <append>true</append>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
 
 <root level="debug">
  <appender-ref ref="FILE" />
 </root>
</configuration>

    I will explain the logback configuration file entries now.

    First, the debug=’true’ in line number 2 of this file will help to find out what logback is doing (whether it is starting fine or not etc. on to the console or System.out log ). Always use this flag and it will save you a lot of time.
   We create something called an ‘Appender’ to write the log statements. Think of Appenders like handles that do that logging tasks. You create one or more Appenders and those will perform the logging based on the properties you set on them.
    In the code above, we created an Appender, named it to ‘FILE’ (we named it FILE as we are writing the logs to a File and not to the Console).  We asked the Appender to create a logfile named ‘LogbackTutorial.log’.  To specify the Pattern of the log statement, (for example: 15:15:24.273 [WebContainer : 0] DEBUG LogbackTestServlet - Inside the doGet method), we use the <pattern> tag inside the <encoder> tags.

   After the Appender is created, we set the loglevel to ‘debug’ and associate the appender.

  Now, run the Servlet by going to the URL
   http://localhost:9080/LogbackTutorial/LogbackTestServlet (change the host name/ports as needed)

   Go to the default log file location (Websphere/AppServer/Profiles/AppSrv01) or your server’s default log location and there you will find the LogbackTutorial.log created. It will have the following entries:
15:15:24.273 [WebContainer : 0] DEBUG LogbackTestServlet - Inside the doGet method
15:15:24.276 [WebContainer : 0] DEBUG LogbackTestServlet - Before writing the output

    That’s it !! Logback is up and logging your log statements. 


  BONUS:
  For writing logs to a specific location based on a Websphere name space binding. (SNIPPET 2):


  SKIP THIS SNIPPET IF YOU WANT THE DEFAULT LOG LOCATION.

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
 <insertFromJNDI env-entry-name="cell/persistent/LOGFOLDER" as="logFolder"/> 
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">

  <if condition='property("logFolder").contains("log")'>
   <then>
    <file>${logFolder}/Tutorials/LogbackTutorial.log</file>
   </then>
   <else>
    <file>LogbackTutorial.log</file> 
   </else>
  </if>
    <append>true</append>
    <encoder>
      <pattern>>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
 
 <root level="debug">
  <appender-ref ref="FILE" />
 </root>
</configuration>
   The <insertFromJNDI> tag is useful if you want to write to the log file to a particular location dynamically without changing the code and redeploying. For this to happen, in Websphere, you need to create a name space binding called LOGFOLDER and set it to any folder that you want to write the logs to. In my case, on Websphere Admin console, I went to ‘Name Space bindings’ and created a binding called ‘LOGFOLDER’ and set the String value to /dev/waslogs. If you run the Servlet, the logs will be written to the location that you wanted it to. In the future, if you wanted to write the logs to a different location, without changing the application code, just change value of the name space binding and restart the server. The application should write the logs to the new file location.


   Other useful links/reads:

   http://logback.qos.ch/reasonsToSwitch.html

 Please leave your comments if you find this article helpful !