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.
- package com.ddlab.logger.custom.filter;
- import java.util.logging.Filter;
- import java.util.logging.LogRecord;
-
-
-
-
-
-
-
- public class LogFilter implements Filter {
-
-
-
-
-
-
-
- @Override
- public boolean isLoggable(LogRecord record) {
- if(record.getSourceClassName().indexOf("org.some.third") != -1)
- return false;
- else
- return true;
- }
- }
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.
- public class Test1 {
-
-
-
- protected final static Logger logger = Logger.getLogger(Test1.class.getName());
- static {
- try {
- Handler handler = new FileHandler("applogs1.log", true);
-
-
- logger.addHandler(handler);
- } catch (IOException ex) {
- Logger.getLogger(Test1.class.getName()).log(Level.SEVERE, null, ex);
- } catch (SecurityException ex) {
- Logger.getLogger(Test1.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
-
-
-
- public static void main(String[] args) {
- logger.log(Level.INFO, "Info Message");
- logger.log(Level.SEVERE, "It is an Exception or an Error");
- }
- }
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.
- handlers = java.util.logging.FileHandler,java.util.logging.ConsoleHandler
- java.util.logging.FileHandler.level = ALL
- java.util.logging.FileHandler.encoding =
- java.util.logging.FileHandler.limit =
- java.util.logging.FileHandler.append = true
- java.util.logging.FileHandler.pattern = logs/log%u.%g.txt
- java.util.logging.ConsoleHandler.level = ALL
The following Java code is used to configure the logger config.
- private static LogManager manager = LogManager.getLogManager();
- static {
-
- try {
- InputStream in = new FileInputStream("logcofig/logconfig.properties");
- manager.readConfiguration(in);
- in.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
Configuration
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