Quick Contact

    Introduction

    Log4j is a reliable, fast and flexible logging framework (APIs) written in Java, which is distributed under the Apache Software License. log4j is a popular logging package written in Java. Log4j has been ported to the C, C++, C#, Perl, Python, Ruby, and Eiffel languages.

    Log4j is highly configurable through external configuration files at runtime. It views the logging process in terms of levels of priorities and offers mechanisms to direct logging information to a great variety of destinations, such as a database, file, console, UNIX Syslog.

    Advantages of Log4j

    The advantages of Log4j are:

    • Log4j allows a very good logging infrastructure without putting in any efforts.
    • Log4j gives the ability to categorize logs at different levels (Trace, Debug, Info, Warn, Error and Fatal).
    • Log4j gives the ability to direct logs to different outputs. For e.g. to a file, Console or a Database.
    • Log4j gives the ability to define the format of output logs.
    • Log4j gives the ability to write Asynchronous logs which helps to increase the performance of the application.
    • Loggers in Log4j follow a class hierarchy which may come handy to the applications.
    Components of Log4j

    log4j has three main components:

    • Loggers: It is responsible for capturing logging information.
    • Appenders: It is responsible for publishing logging information to various preferred destinations.
    • Layouts: It is responsible for formatting logging information in different styles.
    Creating Logger

    Logger is the object which lets the log information to the required Log location, be it console or a file or even a database. Logger objects follow hierarchy similar to class hierarchy in any OOP language. Naming convention of Logger hierarchy is in the name. Each objects name decide which hierarchy it follows. For example take a logger named “Main.Utility“. So Utility is the child of Main and Main is the father of Utility. Also, all Loggers are derived from root Logger. The actual hierarchy will be root. Main.Utility with root being ancestor of Utility and Father of Main. This can be shown in a diagram below:

    These relationships are managed by the LogManager class. Lets illustrate it using an example

    import org.apache.log4j.LogManager; 
    
    import org.apache.log4j.Logger; public class SampleEntry {
    
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    
    Logger chance = LogManager.getLogger(SampleEntry.class.getName());
    Logger logger1 = LogManager.getLogger("Child1");
    Logger logger1Child = logger1.getLogger("Child1.ChildOfLogger1");
    Logger loggerGrandChild = 
    LogManager.getLogger("Child1.ChildOfLogger1.GrandChild");
    
    System.out.println("logger1's full name is " + 
    logger1.getParent().getName());
    System.out.println("logger1Child's full name is " + 
    logger1Child.getParent().getName());
    System.out.println("loggerGrandChild's full name is " + 
    loggerGrandChild.getParent().getName());
    
    }
    }
    

    Output:

    As it can see that logger1 is the parent of logger1Child and grandparent of logger GrandChild’s.

    Logging levels

    Logger class have following print methods that help you to log information.

    • Trace
    • Debug
    • Info
    • Warn
    • Error
    • Fatal

    For example a debug log can be print by just writing Logger.Debug(“This is a debug log”). Any other overloaded Logger can be used to choose Debug() method. All these print statements are called Levels. Each log level expects a certain type of information for example debug level expects logging of that information which may help a programmer debug the application in case of failures. Similarly Error Level expects all the Errors to be logged using this level. Log level of a logger can be set by using the Logger.setLevel method. Log levels have following order:

    TRACE < DEBUG < INFO < WARN < ERROR < FATAL

    Download Log4j

    Follow the given below Steps to download Log4j

    1. Go to link http://logging.apache.org/ and click Apache log4j.
    2. Click on “Download” on the left side menu.
    3. Click on the ZIP file under Mirrors column.
    4. Click on the highlighted link at the top of the page.
    5. Select the radio button for “Save File” and click OK. Zip file will be saved on the system
      with in few seconds.
    6. Right click on the Zip file and select “Extract All“.
    7. Specify the location.
    8. Wait for the Extraction to finish.
    9. Open the Log4j extracted folder from the saved location.
    10. The Log4j JAR file has downloaded, now all is need to do is to add this JAR file to the project and write the first Log4j logging enabled test script.
    Add Log4j Jar

    The steps to follow to add Log4j Jar are:

    1. Right click the project name and navigate to Build Path and select “Configure Build Path“.
    2. Click on Add External JARS and navigate to the folder where the Log4j jar files are kept.
    3. Select the Executable Jar File and click Open.
    Test Case with Log4j

    Following steps are used to create test case with Log4i:

      1. Create a new XML file, log4j.xml and place it under the Project root folder and Paste the following code in the log4j.xml file
            			<?xml version="1.0" encoding="UTF-8"?>
                        <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
        <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
        
        <appender name="fileAppender" class="org.apache.log4j.FileAppender">
        
        <param name="Threshold" value="INFO" />
        
        <param name="File" value="logfile.log"/>
        
        <layout class="org.apache.log4j.PatternLayout">
        
        <param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n"
        />
        
        </layout>
        
        </appender>
        
        <root>
        
        <level value="INFO"/>
        
        <appender-ref ref="fileAppender"/>
        
        </root>
        
        </log4j:configuration>
        
        

    Note: After pasting the code make sure that the code is exactly same, as copying from HTML may change some symbols(“) to (?).

    1. Now include logging code in to the test script
      import java.util.concurrent.TimeUnit; 
              	import org.apache.log4j.Logger;
      import org.apache.log4j.xml.DOMConfigurator; 
      import org.openqa.selenium.By;
      import org.openqa.selenium.WebDriver;
      import org.openqa.selenium.firefox.FirefoxDriver; 
      public class Log4j {
      private static WebDriver driver;
      private static Logger Log = Logger.getLogger(Log4j.class.getName());
      public static void main(String[] args) { 
      DOMConfigurator.configure("log4j.xml");
      
      // Create a new instance of the Firefox driver 
      driver = new FirefoxDriver();
      
      Log.info("New driver instantiated");
      
      //Put a Implicit wait, this means that any search for
      
      //elements on the page could take the time the implicit //wait is set for before throwing exception
      driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
       
      Log.info("Implicit wait applied on the driver for 10 seconds");
      //Launch the Online Store Website
      
      driver.get("http://www.onlinestore.toolsqa.wpengine.com"); 
      Log.info("Web application launched");
      
      // Find the element that's ID attribute is 'account'(My //Account)
      driver.findElement(By.id("account")).click(); 
      Log.info("Click action performed on My Account link");
      
      // Find the element that's ID attribute is 'log' (Username)
      // Enter Username on the element found by above desc. 
      driver.findElement(By.id("log")).sendKeys("testuser_1"); 
      Log.info("Username entered in the Username text box");
      // Find the element that's ID attribute is 'pwd' (Password)
      // Enter Password on the element found by the above
       
      desc.
      
      driver.findElement(By.id("pwd")).sendKeys("Test@123"); Log.info("Password entered in the Password text box");
      // Now submit the form. WebDriver will find the form for //us //from the element
      driver.findElement(By.id("login")).click(); 
      Log.info("Click action performed on Submit button");
      
      // Print a Log In message to the screen
      
      System.out.println(" Login Successfully, now it is the time to Log Off buddy.");
      
      // Find the element that's ID attribute is
      
      //'account_logout' (Log Out) driver.findElement(By.id("account_logout")); 
      Log.info("Click action performed on Log out link");
      
      // Close the driver driver.quit(); 
      Log.info("Browser closed");
       
      
      }
      }
      
    2. Check the output file “logfile.txt”. The output will look like below:
    Log4j Log Manager

    LogManager, as the name suggests, is the Manager of all logger objects. This is the static class that you refer to for creating Logger objects. LogManager also keeps a list of all the loggers being created by the application. If I were to summarize, LogManager does following work

    • Create instances of Logger objects.
    • Store references of all the created logger objects.
    • Allow reuse of same logger object in different parts of the code.

    Let’s look at this example code. This shows how we can create different logger instances out of a LogManager.

    import org.apache.log4j.BasicConfigurator; 
    import org.apache.log4j.LogManager;
    import org.apache.log4j.Logger;
     
    public class SampleEntry {
    
    public static void main(String[] args) {
    
    //This is how we create a logger 
    object Logger logger1 = LogManager.getLogger("Logger1"); 
    Logger logger2 = LogManager.getLogger("Logger2"); 
    Logger logger3 = LogManager.getLogger("Logger3"); BasicConfigurator.configure();
    logger1.info("This is logger 1"); 
    logger2.info("This is logger 2"); 
    logger3.info("This is logger 3");
    }
    }
    

    All the logger objects can be retrive inside LogManager at a particular instance by using the getCurrentLoggers() method. Here is the code sample

    import java.util.Enumeration;
    import org.apache.log4j.BasicConfigurator; 
    import org.apache.log4j.LogManager;
    import org.apache.log4j.Logger;
    
    public class SampleEntry {
    
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    
    Logger logger1 = LogManager.getLogger("Logger1"); 
    Logger logger2 = LogManager.getLogger("Logger2"); 
    Logger logger3 = LogManager.getLogger("Logger3"); 
    BasicConfigurator.configure();  
    logger1.info("This is logger 1");
     
    
    logger2.info("This is logger 2"); 
    logger3.info("This is logger 3");
    
    Enumeration loggers = LogManager.getCurrentLoggers(); 
    while(loggers.hasMoreElements())
    {
    logger3.info("Logger name is " + loggers.nextElement().getName());
    }
    }
    }
    

    One very important property of LogManager it can also retrieve an existing logger object by name. Also, if a logger object will create with the same name as an existing logger object, it will pass on the reference of the existing logger object instead of creating one. This can be shown in the code below

    import java.util.Enumeration;
    import org.apache.log4j.BasicConfigurator; 
    import org.apache.log4j.LogManager;
    import org.apache.log4j.Logger;
    public class SampleEntry {
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    
    Logger logger1 = LogManager.getLogger("Logger1"); 
    Logger logger2 = LogManager.getLogger("Logger2"); 
    Logger logger3 = LogManager.getLogger("Logger3"); 
    BasicConfigurator.configure();
    logger1.info("This is logger 1"); 
    logger2.info("This is logger 2"); 
    logger3.info("This is logger 3");
    
    Logger logger1_2 = LogManager.getLogger("Logger1"); 
    Logger logger1_3 = LogManager.getLogger("Logger1");
    //You will see that LogManager doesnt create a new
    //instance of logger
    //Object with name Logger1, instead passes on the
    //reference to the
    //existing Logger1 object. We can confirm this with
    //following lines
    logger1_2.info("The name of this logger is " + logger1_2.getName());
    
    if(logger1_3.equals(logger1))
    {
    logger1_3.info("Both objects are same");
    
    }
    else
    {
    logger1_3.info("Logger1 and logger1_2 are different objects");
    }
    }
    }
    

    Output

    1	[main] INFO Logger1 - This is logger 1
    2	[main] INFO Logger2 - This is logger 2
    2 [main] INFO Logger3 - This is logger 3
    2 [main] INFO Logger1 - The name of this logger is Logger1
    2 [main] INFO Logger1 - Both objects are same
     
    

    As it can see from the last two lines of output both logger1_2 and logger1_3 are pointing to same logger object which was created at the start of the program. This way same logger can be reuse across different parts of the test code.

    Log4j Appenders

    Appenders are the Log4j objects which deliver logs to the required destinations. For example
    a ConsoleAppender will deliver the logs to the console and a FileAppender to the log file. Some types of Appenders are as below:

    • File Appenders: Almost all the time there is logging of data occur in a file instead of printing it on the console. This is for obvious reasons, as to copy the logs so that it can be keep for reference and browse through it to find problems. Whenever there is a need to log in a file, a FileAppender will be use. This code sample explains to create a FileAppender object and then set it to the required logger.
      import org.apache.log4j.BasicConfigurator; 
              	import org.apache.log4j.FileAppender; 
      import org.apache.log4j.Layout;
      
      import org.apache.log4j.Level; 
      import org.apache.log4j.LogManager; 
      import org.apache.log4j.Logger;
      import org.apache.log4j.SimpleLayout; 
      public class SampleEntry {
      public static void main(String[] args) {
      // TODO Auto-generated method stub
      
      BasicConfigurator.configure(); 
      Logger OurLogger =
      LogManager.getLogger("OurLogger");
      
      //create a FileAppender object and
      //associate the file name to which you want the logs
      //to be directed to.
      //You will also have to set a layout also, here
      //We have chosen a SimpleLayout
      FileAppender fileAppender = new FileAppender(); 
      fileAppender.setFile("logfile.txt"); 
      fileAppender.setLayout(new SimpleLayout());
      
      //Add the appender to our Logger Object.
      //from now onwards all the logs will be directed
      //to file mentioned by FileAppender OurLogger.addAppender(fileAppender); 
      fileAppender.activateOptions();
      
      //lets print some log 10 times int x = 0;
      while(x < 11){
      
      
      OurLogger.debug("This is just a log that I want to print " + x);
      x++;
      }
      
      	}	
      }		
      

      Output

      DEBUG	- This	is	just	a	log	that	I	want	to	print	0
      DEBUG	- This	is	just	a	log	that	I	want	to	print	1
      DEBUG	- This	is	just	a	log	that	I	want	to	print	2
      DEBUG	- This	is	just	a	log	that	I	want	to	print	3
      DEBUG	- This	is	just	a	log	that	I	want	to	print	4
      DEBUG	- This	is	just	a	log	that	I	want	to	print	5
      DEBUG	- This	is	just	a	log	that	I	want	to	print	6
      DEBUG	- This	is	just	a	log	that	I	want	to	print	7
      DEBUG	- This	is	just	a	log	that	I	want	to	print	8
      DEBUG	- This	is	just	a	log	that	I	want	to	print	9
      DEBUG	- This	is	just	a	log	that	I	want	to	print	10
      

      While creating an appender the Layout is to be added which have been chosen. In this
      case SimpleLayout() has chosen. Also, whenever there will be a change in Appender object for example adding a file path or adding the Layout you have to call activateOptions(). The activateOptions() will activate the options set previously. This is important because the changes to Appender object won’t take place until activateOptions(). The log file will be found in the project folder in the eclipse workspace. Also, this is how the logs look in the log file:

    • Console Appenders: For testing purpose it may need to redirect the output logs to the console. Actually ConsoleAppender directs the logs to System.err and System.out streams. These streams are also read by Console and hence the output is displayed at the console as well. Let’s see with a code sample on how to use ConsoleAppender Object.
      import org.apache.log4j.BasicConfigurator; 
      import org.apache.log4j.ConsoleAppender; 
      import org.apache.log4j.FileAppender; 
      import org.apache.log4j.Layout;
      import org.apache.log4j.Level; 
      import org.apache.log4j.LogManager; 
      import org.apache.log4j.Logger;
      import org.apache.log4j.SimpleLayout; 
      public class SampleEntry {
      
      public static void main(String[] args) {
      // TODO Auto-generated method stub
      
      BasicConfigurator.configure(); 
      Logger OurLogger =
      LogManager.getLogger("OurLogger");
      
      //create a ConsoleAppender object
      //You will also have to set a layout also, here
      //We have chosen a SimpleLayout ConsoleAppender ConsoleAppender = new
      ConsoleAppender();
      
      ConsoleAppender.setLayout(new SimpleLayout());
      
      //Add the appender to our Logger Object.
      //from now onwards all the logs will be directed
      //to file mentioned by FileAppender OurLogger.addAppender(ConsoleAppender); ConsoleAppender.activateOptions();
      
      //lets print some log 10 times int x = 0;
      
      while(x < 11){
      
      OurLogger.debug("This is just a log that I want to print " + x);
      x++;
      }
      }
      }
      

      This way it will redirect all the logs to the console and can see the output in the console.

    • JDBC Appender: JDBCAppenders are used to write logs to a Data base.
      These appendersaccept data base connection credentials to connect to DB. Let’s see a code sample to understand.

      import org.apache.log4j.BasicConfigurator; 
      import org.apache.log4j.ConsoleAppender; 
      import org.apache.log4j.FileAppender; 
      import org.apache.log4j.Layout;
      import org.apache.log4j.Level; 
      import org.apache.log4j.LogManager; 
      import org.apache.log4j.Logger;
      import org.apache.log4j.SimpleLayout; 
      import org.apache.log4j.jdbc.JDBCAppender;
      
      public class SampleEntry {
      public static void main(String[] args) {
      
      // TODO Auto-generated method stub
      
      BasicConfigurator.configure(); 
      Logger OurLogger =
      LogManager.getLogger("OurLogger");
      
      //create a JDBCAppender class instance
      JDBCAppender dataBaseAppender = new JDBCAppender();
      //Provide connection details to the
      //Database appender
      
      dataBaseAppender.setURL("jdbc:mysql://localhost/test");
      //Connection url
      dataBaseAppender.setUser("User1"); 
      //Username for the DB connection dataBaseAppender.setPassword("ThisPassword");
      //Password for the DB connection 
      dataBaseAppender.setDriver("com.mysql.jdbc.Driver"); 
      // Drivers to use to connect to DB
      
      //set the sql insert statement that you want to use dataBaseAppender.setSql("INSERT INTO LOGS VALUES ('%x', now() ,'%C','%p','%m'");
      
      //activate the new options dataBaseAppender.activateOptions();
      
      //Attach the appender to the Logger OurLogger.addAppender(dataBaseAppender);
      
      int x = 0; 
      while(x < 11){
      OurLogger.debug("This is just a log that I want to print " + x);
      x++;
      }
      }
      }
      

    This code explains how to set up a JDBCAppender object and use it for logging. In the code the insert statement has to be given to the JDBCAppender. This statement is used to insert logs in the desired database table. Here the statement INSERT INTO LOGS VALUES (‘%x’, now()
    ,’%C’,’%p’,’%m’) is used. It says that logs are inserted in the table named LOGS.

    Log4j Layouts

    At times, the user wishes certain information to be pre – pended or appended with each log statement. For example, to print a timestamp along with the log statement. Thus, such requirements can be accomplished by “Layouts”.

    Layouts are a utility that allows the user to opt for the desired format in which the logs would be rendered. Appenders and Layout have a tight coupling between them. Thus, it required to map each of the appenders with a specific layout. A user is leveraged to define multiple appenders, each map with a distinct layout. The user is leveraged to specify the desired pattern in the value of the ConversionPattern parameter.

    <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss}%x %- 5p[%c{1}]: %m%n"/>
    </layout>
    

    Layout class help us define how the log information should appear in the outputs. Here is a sample code which uses PatternLayout Class to change the formatting of logs:

    import java.util.Enumeration; 
    import org.apache.log4j.Appender;
    import org.apache.log4j.BasicConfigurator; 
    import org.apache.log4j.ConsoleAppender; 
    import org.apache.log4j.Layout;
    import org.apache.log4j.LogManager; 
    import org.apache.log4j.Logger;
    
    import org.apache.log4j.PatternLayout;
    
    public class SampleEntry {
    
    //All the loggers that can be used static Logger mainLogger =
    LogManager.getLogger(SampleEntry.class.getName());
    
    public static void main(String[] args) {
    
    // TODO Auto-generated method stub
    
    BasicConfigurator.configure();
    ConsoleAppender appender = new ConsoleAppender();
    
    appender.activateOptions();
    
    PatternLayout layoutHelper = new PatternLayout(); 
    layoutHelper.setConversionPattern("%-5p [%t]: %m%n"); 
    layoutHelper.activateOptions();
    
    mainLogger.getAppender("ConsoleAppender").setLayout(layou tHelper);
    
    appender.setLayout(layoutHelper); mainLogger.addAppender(appender);
    
    //Create a console appender and attach it to our
    //mainLogger
    mainLogger.info("Pattern 1 is displayed like this"); 
    layoutHelper.setConversionPattern("%C %m%n"); 
    mainLogger.info("Pattern 2 is displayed like this");
    }
    }
    

    Expected output on the console will be

    INFO [main]: Pattern 1 is displayed like this Log4jSample.SampleEntry
    Pattern 2 is displayed like this Manual Layout
    Selenium Layout
    
    Summary
    • Log4j is a reliable, fast and flexible logging framework (APIs) written in Java, which is distributed under the Apache Software License
    • Log4j is highly configurable through external configuration files at runtime
    • Log4j allows a very good logging infrastructure without putting in any efforts
    • Log4j gives the ability to categorize logs at different levels
    • Log4j gives the ability to direct logs to different outputs. For e.g. to a file, Console or a Database
    • Log4j gives the ability to define the format of output logs
    • Log4j gives the ability to write Asynchronous logs which helps to increase the performance of the application

    Copyright 1999- Ducat Creative, All rights reserved.