Friday, February 18, 2011

Logger information

What is Logger?

Logger is kind of custom auditing tool through which you can trace back the execution flow.In application we can use it the way we want as a debugger during development mode and as a info during production mode.
Moving from one level to another does not allow binary changes .It can be controlled by external properties/configuration file.

Log4j Infrastructure

In order to define logging we need following objects.These are:-

i)Logger is an entity identified by a name and follows the hierarchy
   i.e
   Logger for com.kunaal.X is parent of logger for com.kunaal.sub.Y
   Logger can customize the priority level.Since all loggers are child of root logger.Properties defined here over ride the inherited settings of the root logger.

e.g. Lets suppose we have 3 packages in our project
  -com.kunaal.domain
  -com.kunaal.service
  -com.kunaal.dao

   We have defined root logger with priority level as INFO.
   We have defined logger for com.kunaal.dao with priority level as DEBUG.

    So in our application following logging will happen
   -For all classes in com.kunaal.dao. all logging information with priority level as DEBUG and above it will be logged in the appender.
   -For all classes in com.kunaal.domain and com.kunaal.service.There is no specific logging criteria defined.So it will inherit the information from root logger.So logging information with priority level as INFO and above will be logged.
  
ii)Appenders is an object which sends the logging information to the final destination.Log4J has provided many appenders.Some of the frequently used appenders are as follows.


   -File Appender lets you log the information in a file.
   -Console Appender lets you log the information to the console.By default its System.out.
   -JDBC Appender lets you log the information to the database table.
   -JMS Appender lets you publish the information to JMS topic
   -Rolling File Appender lets you log the information ina file.Once file reaches up the max size.It backs up the file and create a new file.

iii)Layout lets you customize the format in which you log the information.

Root Logger

Root logger is at the top of logger hierarchy and all other loggers are child loggers of the root logger.If we donot specify any custom settings for the child logger,child logger inherit the setting information from the root logger or the logger nearest to it.

Root logger always exits and there is a utility method Logger.getRootLogger() to fetch it.

Inheritance in logger

Log4j incorporates inheritance among loggers.If we have not specified any logger for the particular class,it fetches logger information from immediate parent going upto root logger.
This is illustrated by testInheritance() method in LoggerExample.There we have not defined any logger for the Logger for LoggerExample.So it inherits the information from the immediate parent which is root logger in this case.More information is available in method comments.



Logging output to multiple appenders

Logging lets us write the log information to multiple appenders if reqd.All we need is to define the appender information in the logger.

In the Logger Example mentioned below we have added a file appender.So for logger "com.kunaal.logger.domain" logging information will go to file appender besides the console appender specified in root logger.

What is LogManager and how logger is created

LogManager is the internal class  used by log4j for getting loggers and other operations.LogManager has a data structure of type map to persist logger against classname.When we do Logger.getLogger(Class....).It checks in the internal data structure whether any logger for this class is created or not.If its created it returns the same,otherwise creates a new logger and persist it in the internal map. This is illustrated by testLogMgr() in LoggerExample

Different log levels

There are six log levels supported by log4j.These are as follows
  • Trace
  • Debug                           
  • Info
  • Warn
  • Error
  • Fatal
These log levels determine which log information is actually logged.Logging rule states that information corresponding to log level of the logger or higher than that is logged to the appender i.e.
If logging level for a logger is defined as INFO,then except debug and trace rest all information will be logged.

Why logging is preferred over SOP?

Reason being its not possible with System.out.println(SOP)  to turn it off/on.It can be either totally on or off.Moreover once placed inside the code it will always be run.Its not possible to let few statements run and few does not run.Moreover this setting can't externalized and controlled as we can do with priority level in log4j using configuration /properties file.

With log4j we can customize the layout and information can be sent to different appenders like file appender/jms appender/mail appender /console appender which is not possible with SOP.


In log4j there is a hierarchy among loggers which does not exist in SOP.

Logging example

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

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        
  <!-- Console appender for logging -->       
 <appender name="appender" class="org.apache.log4j.ConsoleAppender">
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="[%t] %-5p %c{2} %x - %m%n"/>
     </layout>
   </appender>
   
   <!-- File appender for logging.This is used currently for logger com.kunaal.logger.domain -->
   <appender name="fileAppender" class="org.apache.log4j.FileAppender">
    <param name="file" value="example.log"/>
    <param name="additivity" value="false"/>
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="[%t] %-5p %c{2} %x - %m%n"/>
     </layout>    
   </appender>

 <!-- 
  Creating the child logger for all classes under service package
  with debug level as info.
  So all the messages with priority level less than 
  info i.e debug and trace won't be logged
  -->
 <logger name="com.kunaal.logger.service">
        <level value="info"/>
    </logger>

 <!-- 
  Creating the child logger for all classes under domain package
  with priority level as trace.
  So all the messages will be logged as trace is at the lowest rank.
  -->
 <logger name="com.kunaal.logger.domain">
        <level value="trace"/>
        <appender-ref ref="fileAppender"/>
    </logger>
    
    <!-- 
     Root logger with appender information
     All corresponding loggers are child of root logger
     So they will inherit the properties of root logger
     unless over ridden as in case of service and domain logger
     -->
   <root>
     <priority value ="debug"/>
     <appender-ref ref="appender"/>
     
   </root>

</log4j:configuration>


Domain class for EducationalInfo
package com.kunaal.logger.domain;

/**
 * Class for capturing educational details of an employee
 * 
 * @author Kunaal A Trehan
 *
 */
public class EducationalInfo {
 
 //Boolean variable capturing whether person is under graduate or not
 private boolean isUG;
 
 //Boolean variable capturing whether person is post graduate or not
 private boolean isPG;
 
 //String variable capturing specialization for under graduation
 private String ugSpecialization;
 
 //String variable capturing specialization for post graduation
 private String pgSpecialization;
 
 //String variable capturing other specialization details
 private String others;

 /**
  * Default constructor
  */
 public EducationalInfo() {
  super();
 }

 /**
  * @return the isUG
  */
 public boolean isUG() {
  return isUG;
 }

 /**
  * @param isUG the isUG to set
  */
 public void setUG(boolean isUG) {
  this.isUG = isUG;
 }

 /**
  * @return the isPG
  */
 public boolean isPG() {
  return isPG;
 }

 /**
  * @param isPG the isPG to set
  */
 public void setPG(boolean isPG) {
  this.isPG = isPG;
 }

 /**
  * @return the ugSpecialization
  */
 public String getUgSpecialization() {
  return ugSpecialization;
 }

 /**
  * @param ugSpecialization the ugSpecialization to set
  */
 public void setUgSpecialization(String ugSpecialization) {
  this.ugSpecialization = ugSpecialization;
 }

 /**
  * @return the pgSpecialization
  */
 public String getPgSpecialization() {
  return pgSpecialization;
 }

 /**
  * @param pgSpecialization the pgSpecialization to set
  */
 public void setPgSpecialization(String pgSpecialization) {
  this.pgSpecialization = pgSpecialization;
 }

 /**
  * @return the others
  */
 public String getOthers() {
  return others;
 }

 /**
  * @param others the others to set
  */
 public void setOthers(String others) {
  this.others = others;
 }

 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  return "EducationalInfo [isUG=" + isUG + ", isPG=" + isPG
    + ", ugSpecialization=" + ((ugSpecialization==null)?"NA":ugSpecialization)
    + ", pgSpecialization=" + ((pgSpecialization==null)?"NA":pgSpecialization)
    + ", others=" + ((others==null)?"NA":others) + "]";
 }

 /**
  * Overridden hash code method
  */
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + (isPG ? 1231 : 1237);
  result = prime * result + (isUG ? 1231 : 1237);
  result = prime * result + ((others == null) ? 0 : others.hashCode());
  result = prime
    * result
    + ((pgSpecialization == null) ? 0 : pgSpecialization.hashCode());
  result = prime
    * result
    + ((ugSpecialization == null) ? 0 : ugSpecialization.hashCode());
  return result;
 }

 /**
  * Overridden equals method
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  EducationalInfo other = (EducationalInfo) obj;
  if (isPG != other.isPG)
   return false;
  if (isUG != other.isUG)
   return false;
  if (others == null) {
   if (other.others != null)
    return false;
  } else if (!others.equals(other.others))
   return false;
  if (pgSpecialization == null) {
   if (other.pgSpecialization != null)
    return false;
  } else if (!pgSpecialization.equals(other.pgSpecialization))
   return false;
  if (ugSpecialization == null) {
   if (other.ugSpecialization != null)
    return false;
  } else if (!ugSpecialization.equals(other.ugSpecialization))
   return false;
  return true;
 }

}

Domain class for Employee
package com.kunaal.logger.domain;

import org.apache.log4j.Logger;

/**
 * @author Kunaal A Trehan
 *
 */
public class Employee {

 //Logger variable
 private static final Logger LOGGER=Logger.getLogger(Employee.class);
 
 //Variable for employee's personal info
 private PersonalInfo personalInfo;
 
 //Variable for employee's family info
 private FamilyInfo familyInfo;
 
 //Variable for employee's educational info
 private EducationalInfo eduInfo;

 /**
  * @return the personalInfo
  */
 public PersonalInfo getPersonalInfo() {
  return personalInfo;
 }

 /**
  * @param personalInfo the personalInfo to set
  */
 public void setPersonalInfo(PersonalInfo personalInfo) {
  this.personalInfo = personalInfo;
 }

 /**
  * @return the familyInfo
  */
 public FamilyInfo getFamilyInfo() {
  return familyInfo;
 }

 /**
  * @param familyInfo the familyInfo to set
  */
 public void setFamilyInfo(FamilyInfo familyInfo) {
  this.familyInfo = familyInfo;
 }

 /**
  * @return the eduInfo
  */
 public EducationalInfo getEduInfo() {
  return eduInfo;
 }

 /**
  * @param eduInfo the eduInfo to set
  */
 public void setEduInfo(EducationalInfo eduInfo) {
  this.eduInfo = eduInfo;
 }

 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  return "Employee [personalInfo=" + personalInfo + ", familyInfo="
    + familyInfo + ", eduInfo=" + eduInfo + "]";
 }

 /**
  * Overridden hash code method
  */
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((eduInfo == null) ? 0 : eduInfo.hashCode());
  result = prime * result
    + ((familyInfo == null) ? 0 : familyInfo.hashCode());
  result = prime * result
    + ((personalInfo == null) ? 0 : personalInfo.hashCode());
  return result;
 }

 /**
  * Overridden equals method
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Employee other = (Employee) obj;
  if (eduInfo == null) {
   if (other.eduInfo != null)
    return false;
  } else if (!eduInfo.equals(other.eduInfo))
   return false;
  if (familyInfo == null) {
   if (other.familyInfo != null)
    return false;
  } else if (!familyInfo.equals(other.familyInfo))
   return false;
  if (personalInfo == null) {
   if (other.personalInfo != null)
    return false;
  } else if (!personalInfo.equals(other.personalInfo))
   return false;
  return true;
 }
 
 /**
  * Method which in turn uses toString() of composite element classes
  * and uses debug level of logger for printing
  */
 public void printEmployee(){
  LOGGER.trace("***********PRINT EMPLOYEE CALLED********************");
  LOGGER.trace("Employee details are as follows:-" );
  LOGGER.trace("Personal Information of employee is"+ personalInfo);
  LOGGER.trace("Family Information of employee is"+ familyInfo);
  LOGGER.trace("Educational Information of employee is"+ eduInfo);
  
  LOGGER.trace("*************************************************************************");
 }
 
 
}


Domain class for FamilyInfo
package com.kunaal.logger.domain;

import java.util.ArrayList;
import java.util.List;

/**
 * Class for capturing family information 
 * 
 * @author Kunaal A Trehan
 *
 */
public class FamilyInfo {
 //Boolean flag for capturing whether person is married or not
 private boolean isMarried;
 
 //String variable for capturing name of spouse
 private String spouseName;
 
 //Boolean flag for capturing whether person has any kids or not
 private boolean anyKids;
 
 //List containing kids name
 private List<String> kidList=new ArrayList<String>();

 /**
  * @return the isMarried
  */
 public boolean isMarried() {
  return isMarried;
 }

 /**
  * @param isMarried the isMarried to set
  */
 public void setMarried(boolean isMarried) {
  this.isMarried = isMarried;
 }

 /**
  * @return the spouseName
  */
 public String getSpouseName() {
  return spouseName;
 }

 /**
  * @param spouseName the spouseName to set
  */
 public void setSpouseName(String spouseName) {
  this.spouseName = spouseName;
 }

 /**
  * @return the kidList
  */
 public List<String> getKidList() {
  return kidList;
 }

 /**
  * @param kidList the kidList to set
  */
 public void setKidList(List<String> kidList) {
  this.kidList = kidList;
 }

 /**
  * @return the anyKids
  */
 public boolean isAnyKids() {
  return anyKids;
 }

 /**
  * @param anyKids the anyKids to set
  */
 public void setAnyKids(boolean anyKids) {
  this.anyKids = anyKids;
 }
 
 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  if(isMarried && anyKids){  
   return "FamilyInfo [Spouse name is -" + spouseName+",Kids name-"+ kidList+"]";
  }else if(isMarried){
   return "FamilyInfo [Spouse name is -" + spouseName+"]";
  }else{
   return "FamilyInfo [Enjoying bachelor hood]";
  }
 }

 /**
  * Overridden hash code method
  */
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + (anyKids ? 1231 : 1237);
  result = prime * result + (isMarried ? 1231 : 1237);
  result = prime * result + ((kidList == null) ? 0 : kidList.hashCode());
  result = prime * result
    + ((spouseName == null) ? 0 : spouseName.hashCode());
  return result;
 }

 /**
  * Overridden equals method
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  FamilyInfo other = (FamilyInfo) obj;
  if (anyKids != other.anyKids)
   return false;
  if (isMarried != other.isMarried)
   return false;
  if (kidList == null) {
   if (other.kidList != null)
    return false;
  } else if (!kidList.equals(other.kidList))
   return false;
  if (spouseName == null) {
   if (other.spouseName != null)
    return false;
  } else if (!spouseName.equals(other.spouseName))
   return false;
  return true;
 }
 

}


Domain class for PersonalInfo
package com.kunaal.logger.domain;

import java.util.Date;

/**
 * Class for capturing personal information about an employee
 * 
 * @author Kunaal A Trehan
 *
 */
public class PersonalInfo {

 //Private variable for name
 private String name;
 
 //Private variable for age
 private Integer age;
 
 //Private variable for date of birth
 private Date dob;
 
 /**
  * Default constructor
  */
 public PersonalInfo() {
 }

 /**
  * @return the name
  */
 public  String getName() {
  return name;
 }

 /**
  * @param name the name to set
  */
 public  void setName(String name) {
  this.name = name;
 }

 /**
  * @return the age
  */
 public  Integer getAge() {
  return age;
 }

 /**
  * @param age the age to set
  */
 public  void setAge(Integer age) {
  this.age = age;
 }

 /**
  * @return the dob
  */
 public  Date getDob() {
  return dob;
 }

 /**
  * @param dob the dob to set
  */
 public  void setDob(Date dob) {
  this.dob = dob;
 }

 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  return "PersonalInfo [name=" + name + ", age=" + age + ", dob=" + dob
    + "]";
 }

 /**
  * Overridden hash code method
  */
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((age == null) ? 0 : age.hashCode());
  result = prime * result + ((dob == null) ? 0 : dob.hashCode());
  result = prime * result + ((name == null) ? 0 : name.hashCode());
  return result;
 }

 /**
  * Overridden equals method
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  PersonalInfo other = (PersonalInfo) obj;
  if (age == null) {
   if (other.age != null)
    return false;
  } else if (!age.equals(other.age))
   return false;
  if (dob == null) {
   if (other.dob != null)
    return false;
  } else if (!dob.equals(other.dob))
   return false;
  if (name == null) {
   if (other.name != null)
    return false;
  } else if (!name.equals(other.name))
   return false;
  return true;
 }

}


DomainService class
package com.kunaal.logger.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.kunaal.logger.domain.EducationalInfo;
import com.kunaal.logger.domain.Employee;
import com.kunaal.logger.domain.FamilyInfo;
import com.kunaal.logger.domain.PersonalInfo;

/**
 * This class has utility methods for inserting,updating,deleting the employee information
 * 
 * @author Kunaal A Trehan
 *
 */
public class DomainService {
 //Creating a logger variable
 private static final Logger LOGGER=Logger.getLogger(DomainService.class);
 
 //List data structure containing employee information
 private static final List<Employee> empList=new ArrayList<Employee>();

 /**
  * Utility method for adding employee
  * 
  * @param employee
  */
 public static void insertEmployee(Employee employee){
  if(empList.contains(employee)){
   LOGGER.warn("Employee-" + employee + " already exists,use update method for updating the information");
  }else{
   empList.add(employee);
   LOGGER.debug("Employee-" + employee.getPersonalInfo().getName() + " added succesfully");
  }
 }
 
 /**
  * Utility method for updating personal information of an employee
  * 
  * @param emp
  * @param personalInfo
  */
 public static void updatePersonalInfo(Employee emp,PersonalInfo personalInfo){
  if(!empList.contains(emp)){
   LOGGER.warn("Employee-" + emp + " does not exists,use insert method");
  }else{
   int index = empList.indexOf(emp);
   Employee employee = empList.get(index);
   employee.setPersonalInfo(personalInfo);
   LOGGER.debug("Personal information for employee-"+ employee.getPersonalInfo().getName()
     + " updated successfully");
  }
 }
 
 /**
  * Utility method for updating family information of an employee
  * 
  * @param emp
  * @param familyInfo
  */
 public static void updateFamilyInfo(Employee emp,FamilyInfo familyInfo){
  if(!empList.contains(emp)){
   LOGGER.warn("Employee-" + emp + " does not exists,use insert method");
  }else{
   int index = empList.indexOf(emp);
   Employee employee = empList.get(index);
   employee.setFamilyInfo(familyInfo);
   LOGGER.debug("Family information for employee-"+ employee.getPersonalInfo().getName()
     + " updated successfully");
  }
 }
 
 /**
  * Utility method for updating educational information of an employee
  * 
  * @param emp
  * @param eduInfo
  */
 public static void updateEducationalInfo(Employee emp,EducationalInfo eduInfo){
  if(!empList.contains(emp)){
   LOGGER.warn("Employee-" + emp + " does not exists,use insert method");
  }else{
   int index = empList.indexOf(emp);
   Employee employee = empList.get(index);
   employee.setEduInfo(eduInfo);
   LOGGER.debug("Educational information for employee-"+ employee.getPersonalInfo().getName()
     + " updated successfully");
  }
 }
 
 /**
  * Utility method for deleting an employee
  * 
  * @param emp
  */
 public static void deleteEmployee(Employee emp){
  if(!empList.contains(emp)){
   LOGGER.warn("Employee-" + emp + " does not exists");
  }else{
   empList.remove(emp);
   LOGGER.debug("Employee-" + emp.getPersonalInfo().getName() + " deleted succesfully");
  }
 }
 
 /**
  * Utility method for printing employee personal information
  * as logger INFO
  */
 public static void printPersonalInfo(){
  LOGGER.info("*****************PRINT PERSONAL INFO OF ALL EMP*******************");
  for(Employee emp:empList){
   LOGGER.info(emp.getPersonalInfo());
  }
  LOGGER.info("******************************************************************");
 }
 
 
}


Util Class
package com.kunaal.logger.util;

import java.util.Date;
import java.util.List;

import com.kunaal.logger.domain.EducationalInfo;
import com.kunaal.logger.domain.Employee;
import com.kunaal.logger.domain.FamilyInfo;
import com.kunaal.logger.domain.PersonalInfo;

/**
 * @author Kunaal A Trehan
 *
 */
public class Util {

 /**
  * Utility method for creating employee
  * 
  * @param personalInfo
  * @param eduInfo
  * @param familyInfo
  * @return
  */
 public static Employee createEmployee(PersonalInfo personalInfo,EducationalInfo eduInfo,
        FamilyInfo familyInfo){
  Employee emp=new Employee();
  
  emp.setEduInfo(eduInfo);
  emp.setFamilyInfo(familyInfo);
  emp.setPersonalInfo(personalInfo);
  
  return emp;
 }
 
 /**
  * Utility method for creating personal information
  * 
  * @param age
  * @param name
  * @param dob
  * @return
  */
 public static PersonalInfo getPersonalInfo(Integer age,String name,Date dob){
  PersonalInfo personalInfo=new PersonalInfo();
  personalInfo.setAge(age);
  personalInfo.setDob(dob);
  personalInfo.setName(name);
  
  return personalInfo;
 }
 
 /**
  * Utility method for creating educational information.
  * 
  * @param isUg
  * @param ugSpl
  * @param isPg
  * @param pgSpl
  * @param others
  * @return
  */
 public static EducationalInfo getEduInfo(boolean isUg,String ugSpl,boolean isPg,String pgSpl,String others){
  EducationalInfo eduInfo=new EducationalInfo();
  eduInfo.setUG(isUg);
  eduInfo.setPG(isPg);
  eduInfo.setOthers(others);
  eduInfo.setPgSpecialization(pgSpl);
  eduInfo.setUgSpecialization(ugSpl);
  
  return eduInfo;
 }
 
 /**
  * Utility methods for creating family information.
  * 
  * @param anyKids
  * @param kidList
  * @param isMarried
  * @param spouse
  * @return
  */
 public static FamilyInfo getFamilyInfo(boolean anyKids,List<String> kidList,boolean isMarried,String spouse){
  FamilyInfo familyInfo=new FamilyInfo();
  familyInfo.setAnyKids(anyKids);
  familyInfo.setKidList(kidList);
  familyInfo.setMarried(isMarried);
  familyInfo.setSpouseName(spouse);
  
  return familyInfo;
 }
}

LoggerExample class showing inheritance,multiple appenders,logmanager datastructure and others
package com.kunaal.logger;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

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

import com.kunaal.logger.domain.EducationalInfo;
import com.kunaal.logger.domain.Employee;
import com.kunaal.logger.domain.FamilyInfo;
import com.kunaal.logger.domain.PersonalInfo;
import com.kunaal.logger.service.DomainService;
import com.kunaal.logger.util.Util;

/**
 * @author Kunaal A Trehan
 *
 */
public class LoggerExample {
 //LOGGER for this class.Since there is not customization done.
 //So it will inherit the properties from root logger.
 private static final Logger LOGGER=Logger.getLogger(LoggerExample.class);
 
 private static final Logger DUP_LOGGER=Logger.getLogger(LoggerExample.class);

 /**
  * @param args
  */
 public static void main(String[] args) {
  DOMConfigurator.configure("src/com/kunaal/logger/conf/log4j.xml");
  testInheritance();
  testLogMgr();
  
  //Here we are persisting same employee twice.
  //Since for domain package we have set logging level to INFO
  //So only warning gets printed when we insert again.
  //Debug information regarding insertion successful is not printed.
  Employee emp=insertEmp();
  Employee emp1=insertEmp();
  
  //Delete non existing employee .Warning will be printed on console
  delNonExistEmployee();
  
  //Here we will see all details of employee
  //Even though root logger is at DEBUG.We will see all TRACE messages
  //As custom logger can override the settings which we did for com.kunaal.logger.domain
  emp.printEmployee();
  
  //Log Level is set to INFO for com.kunaal.logger.service.
  //So all Info messages will be printed
  DomainService.printPersonalInfo();
 }
 
 /**
  * This method shows the inheritance among the loggers
  * Here there is no customization for the logger of this class.
  * So it will inherit the properties from root logger
  * which says log level is debug.
  * 
  * So trace information won't be printed.
  */
 private static void testInheritance(){
  LOGGER.info("This is info level information");
  LOGGER.trace("This is trace level information");
 }
 
 /**
  * This method shows that logger is created only once.
  * Then its instance is persisted in map of LogManager
  * which is used to get the logger when we do 
  * Logger.getLogger(....)
  */
 private static void testLogMgr(){
  LOGGER.info("Logger information-" +LOGGER.toString());
  LOGGER.info("Duplicate logger information-" +DUP_LOGGER.toString());
  LOGGER.info("Is logger and duplicate logger point to same instance-" +(LOGGER==DUP_LOGGER));
 }
 
 /**
  * Method for inserting employee
  * @return
  */
 private static Employee insertEmp(){
  EducationalInfo eduInfo=Util.getEduInfo(true, "Engg.", false, null, null);
  Calendar cal=new GregorianCalendar(1978, 2, 18);
  PersonalInfo personalInfo=Util.getPersonalInfo(new Integer(30), "Kunaal A Trehan", cal.getTime());
  List<String> kidList=new ArrayList<String>();
  kidList.add("Annika");
  FamilyInfo familyInfo=Util.getFamilyInfo(true, kidList, true, "Mrs X");
  
  Employee emp=Util.createEmployee(personalInfo, eduInfo, familyInfo);
  DomainService.insertEmployee(emp);
  
  return emp;
  
 }
 
 /**
  * Method for deleteing non existing employee
  * It will print warning on console
  */
 private static void delNonExistEmployee(){
  Employee emp=new Employee();
  DomainService.deleteEmployee(emp);  
 }
 
 

}

Console Output
[main] INFO  logger.LoggerExample  - This is info level information
[main] INFO  logger.LoggerExample  - Logger information-org.apache.log4j.Logger@2bbd86
[main] INFO  logger.LoggerExample  - Duplicate logger information-org.apache.log4j.Logger@2bbd86
[main] INFO  logger.LoggerExample  - Is logger and duplicate logger point to same instance-true
[main] WARN  service.DomainService  - Employee-Employee [personalInfo=PersonalInfo [name=Kunaal A Trehan, age=30, dob=Sat Mar 18 00:00:00 GMT+05:30 1978], familyInfo=FamilyInfo [Spouse name is -Mrs X,Kids name-[Annika]], eduInfo=EducationalInfo [isUG=true, isPG=false, ugSpecialization=Engg., pgSpecialization=NA, others=NA]] already exists,use update method for updating the information
[main] WARN  service.DomainService  - Employee-Employee [personalInfo=null, familyInfo=null, eduInfo=null] does not exists
[main] TRACE domain.Employee  - ***********PRINT EMPLOYEE CALLED********************
[main] TRACE domain.Employee  - Employee details are as follows:-
[main] TRACE domain.Employee  - Personal Information of employee isPersonalInfo [name=Kunaal A Trehan, age=30, dob=Sat Mar 18 00:00:00 GMT+05:30 1978]
[main] TRACE domain.Employee  - Family Information of employee isFamilyInfo [Spouse name is -Mrs X,Kids name-[Annika]]
[main] TRACE domain.Employee  - Educational Information of employee isEducationalInfo [isUG=true, isPG=false, ugSpecialization=Engg., pgSpecialization=NA, others=NA]
[main] TRACE domain.Employee  - *************************************************************************
[main] INFO  service.DomainService  - *****************PRINT PERSONAL INFO OF ALL EMP*******************
[main] INFO  service.DomainService  - PersonalInfo [name=Kunaal A Trehan, age=30, dob=Sat Mar 18 00:00:00 GMT+05:30 1978]
[main] INFO  service.DomainService  - ******************************************************************

Best Practices

When we do LOGGER.debug("......" + "....");,the operation becomes expensive if logger priority level is above debug as the expression will be evaluated and only when logger tries to put the information in the appender.Then it will check and figure out that this information can't be logged.

So its better to write the above statement as follows:-

if(LOGGER.isDebugEnabled()){
       LOGGER.debug("......" + "....");
}

In this way we avoid unnecessary creation of log message if its not going to be logged.

No comments:

Post a Comment