Logger in Java - A Basic Introduction

Introduction

 
A Logger is a part and parcel of any application that helps in debugging and resolving issues. There are various kinds of logger messages through which we can identify the information flowing in the system. In the case of Java, there are many third-party frameworks that provide flexible ways to log the required messages in the application. It is always important to know why, how and what to log. In this small article I will familiarize you with the logger API already available in Java called JDK Logger and very few people are aware of the JDK logger API. It is a common practice in case of any project to use an external logging library to track the log messages. In this small article, I will present how to log the messages and how to customize the logger for our requirements easily without using any external framework.
 

Technicalities

 
There are numerous logger implementations available in the market that can be easily plugged into the system. Some of the popular logger APIs are given below.
  • Commons-logging
  • Jboss-logging
  • Log4j
  • Log4j2
  • Slf4j
The basic question that always haunts us is why to use one instead of "System.out.println". Can't we customize the "println" statement available in Java? Of course, we can customize it as needed, but again does it serve the purposes of our logging? I provide below the following important reasons for which we use a logger in our application.
  • Easy configuration of Logger statements
  • Logging messages using various formats like text, HTML, XML and so on
  • Various types of logging persistence
  • Asynchronous logger
  • Categorization of logging the messages
  • Backup of the log message and sending to various channels
In most cases, it is observed that a novice developer always prefers to write "System.out.println()" for debugging purposes. But that creates substantial overhead when the application is moved into production. It is also observed that most of the developers are happy if their log messages appear only in the console. It is always important to maintain all log messages in the file system for further analysis. Basically it provides you comprehensive diagnostic information about the various operations performed in the application. In the case of post-production issues, the log file from the application helps to a greater extent to fix the issues. However, let us learn a few things about the Java logging API. It is always recommended to use the logger instead of "System.out.println" even if you do not have external logging APIs.
 
The JDK logger comes with the package java.util. Let us have a glance at the following significant classes and interfaces available as a part of logger implementation in Java.
  • java.util.logging.Logger
  • java.util.logging.Level
  • java.util.logging.LogManager
  • java.util.logging.Filter

java.util.logging.Logger

 
This class is the actual implementation of a logger framework in Java. It provides various convenient methods to log the messages. It also provides methods to plug in the handler implementation. Handlers log messages, either in the file system or in the pre-defined console. The Logger class also provides various message levels. Message levels allow prioritization of the messages to the log. The levels can be a warning, error or simple information.
 

java.util.logging.Level

 
As I have already explained about the Level, it is a way to construct the log messages as needed. It is also important to not provide a log message after every statement. The Level class provides the following Level constants, from the Java docs. 
  • SEVERE (highest value)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (lowest value) 

java.util.logging.LogManager

 
Java also supports logger configuration through a properties file and a LogManager class that helps to configure the config file and the one-time configuration and subsequent changes have no impact after LogManger initialization.
 

java.util.logging.Filter

 
The Filter interface provides a flexible structure to control your log messages. Let us consider a typical situation where you are dependent on other APIs and you do not want to display the messages coming from other APIs. In this situation, you can customize the Java logger using a filter so that messages coming from other APIs will not be displayed or logged. Let us consider the following code snippet for the implementation of the Filter interface. 
  1. package com.ddlab.logger.custom.filter;   
  2. import java.util.logging.Filter;  
  3. import java.util.logging.LogRecord;   
  4. /** 
  5.  * This class is used as a log filter. You need to provide your own implementation 
  6.  * for custom logging message. In this class, I have provided implementation to skip 
  7.  * the log messages coming from a specific library. 
  8.  * @author <a href="mailto:[email protected]">Debadatta Mishra</a> 
  9.  * @since 2013 
  10.  */  
  11. public class LogFilter implements Filter {   
  12.     /** 
  13.      * This method is used to provide the custom implementation for the logging 
  14.      * messages. In this case the implementation prevents to log the messages coming 
  15.      * from a third-party. 
  16.      * @param record 
  17.      * @return true or false 
  18.      */  
  19.     @Override  
  20.     public boolean isLoggable(LogRecord record) {  
  21.         if(record.getSourceClassName().indexOf("org.some.third") != -1)  
  22.             return false;  
  23.         else  
  24.             return true;  
  25.     }  
  26. }  
In this above case, we are just filtering out the messages from other APIs.
 
Let us consider a typical Java code where we use a JDK logger. 
  1. public class Test1 {  
  2.     /** 
  3.      * Java logger 
  4.      */  
  5.     protected final static Logger logger = Logger.getLogger(Test1.class.getName());   
  6.     static {  
  7.         try {  
  8.             Handler handler = new FileHandler("applogs1.log"true);  
  9.             //Default is XMl Formatter  
  10.            //handler.setFormatter( new java.util.logging.SimpleFormatter());  
  11.             logger.addHandler(handler);  
  12.         } catch (IOException ex) {  
  13.             Logger.getLogger(Test1.class.getName()).log(Level.SEVERE, null, ex);  
  14.         } catch (SecurityException ex) {  
  15.          Logger.getLogger(Test1.class.getName()).log(Level.SEVERE, null, ex);  
  16.         }  
  17.     }   
  18.     /** 
  19.      * Main method 
  20.      * @param args  
  21.      */  
  22.     public static void main(String[] args) {  
  23.         logger.log(Level.INFO, "Info Message");  
  24.         logger.log(Level.SEVERE, "It is an Exception or an Error");  
  25.     }  
  26. }  

Configuration in Java Logger

 
As I have already explained, Java supports logger configuration through a properties file. Let us see the sample structure of the properties file.
  1. handlers = java.util.logging.FileHandler,java.util.logging.ConsoleHandler    
  2. java.util.logging.FileHandler.level     = ALL  
  3. java.util.logging.FileHandler.encoding  =  
  4. java.util.logging.FileHandler.limit     =  
  5. java.util.logging.FileHandler.append    = true  
  6. java.util.logging.FileHandler.pattern   = logs/log%u.%g.txt   
  7. java.util.logging.ConsoleHandler.level  = ALL   
The following Java code is used to configure the logger config.
  1. private static LogManager manager = LogManager.getLogManager();   
  2.    static {  
  3.       //Initialize the logger config file.  
  4.       try {  
  5.          InputStream in = new FileInputStream("logcofig/logconfig.properties");  
  6.          manager.readConfiguration(in);  
  7.          in.close();  
  8.       } catch (Exception e) {  
  9.          e.printStackTrace();  
  10.      }  
  11. }  

Configuration

 
You can download the complete project on Java logger usage from this site or from the dropbox link "https://www.dropbox.com/s/qevu7xo05b01i61/javalogger.zip". You can configure the project in Eclipse or Netbeans IDE. Run the test classes available inside the test source folder.
 

Conclusion

 
I hope you have enjoyed my small article about the usage of the Java logger API. Download the complete project and go through the source code to understand the concept and its usage. Based on the complexity and design, you can decide whether to use this concept. For any kind of issues and errors, you can contact me at [email protected].
 
Resources and References
 
Refer to the following links to get more clarity on the usage of a Java logger.
http://www.onjava.com/pub/a/onjava/2002/06/19/log.html
http://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html