java.util.logging Example
In this article, we will discuss about the logging functionality in Java. Logging in simple words refers to the recording of an application activity. Logging is used to store exceptions, information, and warnings as messages that occur during the execution of a program. Logging helps a programmer in the debugging process of a program.
Java provides logging facility in the java.util.logging
package. The package consists of a set of classes and interfaces which are used in logging. The System uses a Logger
object to log messages.
The Logger
object is allocated with a LogRecord
object which stores the message to be logged. This LogRecord
object is forwarded to all the handlers assigned to the Logger
object. Both loggers and handlers can optionally use a Filter
that is associated with them, to filter the log messages. Then, the handlers published the logged messages to the external system.
Let’s start with some of the important classes of the package.
1. Logger and Level
A Logger
class is used to create a logger object which is used to log messages. A logger object is provided with a name and has a set of methods which are used to log messages at the different levels. Although you can provide any name to the logger, it is recommended to provide a name based on the package and the class name in which the logger is created.
There are seven logging levels provided by the Level
class.
• SEVERE (highest level)
• WARNING
• INFO
• CONFIG
• FINE
• FINER
• FINEST (lowest level)
All these levels are present in the Level
class, as a static final field. You can use any of these levels, according to the level of the message you log. Additionally, it also provides a level OFF that can be used to turn off the logging and a level ALL to turn on the logging for all the levels.
Let’s see an example about how to create and use a logger.
LoggerExample.java
package com.javacodegeeks.corejava.util.logging; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; public class LoggerExample { private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); public static void main(String[] args) throws SecurityException, IOException { LOGGER.info("Logger Name: "+LOGGER.getName()); LOGGER.warning("Can cause ArrayIndexOutOfBoundsException"); //An array of size 3 int []a = {1,2,3}; int index = 4; LOGGER.config("index is set to "+index); try{ System.out.println(a[index]); }catch(ArrayIndexOutOfBoundsException ex){ LOGGER.log(Level.SEVERE, "Exception occur", ex); } } }
- If we run the above code, we will have the following results:
Jun 08, 2014 1:19:30 PM com.javacodegeeks.corejava.util.logging.LoggerExample main INFO: Logger Name: com.javacodegeeks.corejava.util.logging.LoggerExample Jun 08, 2014 1:19:31 PM com.javacodegeeks.corejava.util.logging.LoggerExample main WARNING: Can cause ArrayIndexOutOfBoundsException Jun 08, 2014 1:19:31 PM com.javacodegeeks.corejava.util.logging.LoggerExample main SEVERE: Exception occur java.lang.ArrayIndexOutOfBoundsException: 4 at com.javacodegeeks.corejava.util.logging.LoggerExample.main(LoggerExample.java:22)
In the above example, we have created a logger object using the getLogger
static method. Then we have logged messages at different levels. We also have thrown an ArrayIndexOutOfBoundsException
to illustrate the use of the Logger
.
Let’s have a look at some of the methods used in this example.
Logger.getLogger(String name)
: This method is used to create or find a logger by the name passed as a parameter.
void info(String msg)
: This instance method is used to log an INFO message, if the logger is currently enabled for the INFO message else the logged message is gets ignored.
void warning(String msg)
: This instance method is used to log a WARNING message, if the logger is currently enabled for the WARNING message else the logged message is gets ignored.
void config(String msg)
: This instance method is used to log a CONFIG message, if the logger is currently enabled for the CONFIG message else the logged message is gets ignored.
void log(Level level, String msg, Object param1)
: This method is used to log a message with a given level, and with an Object
as a parameter. You can use this method when you want to store an object in the log as done in the above example where we have logged an exception object at SEVERE level.
Please note that the INFO level is the default level set in the Logger
. Any message logged with the level lower than the INFO gets ignored. As you can see, the message logged at the WARNING level gets ignored and it did not get published in the console.
2. Handler
A Handler
is one of the components of the logging framework. It is responsible for printing the log message at a target destination. The destination can be a console or a file. The Handler
is used to take a log message in the form of a LogRecord
object and export it to the target destination.
A Logger
can be associated with one or more handlers that eventually forward the logged message to all the handlers. A Handler
is an abstract class in the java.util.logging
package which is a base class for all types of handlers in Java. There are 4 types of built-in handlers in Java.
ConsoleHandler
: A ConsoleHandler
records all the log messages to System.err
. By default, a Logger
is associated with this handler.
FileHandler
: A FileHandler
is used to record all the log messages to a specific file or to a rotating set of files.
StreamHandler
: A StreamHandler
publishes all the log messages to an OutputStream
.
SocketHandler
: The SocketHandler
publish the LogRecords
to a network stream connection.
MemoryHandler
: It is used to keep the LogRecords
into a memory buffer. If the buffer gets full, the new LogRecords
starts overwriting the old LogRecords
.
HandlerExample.java
package com.javacodegeeks.corejava.util.logging; import java.io.IOException; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; public class HandlerExample { private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); public static void main(String[] args) { Handler consoleHandler = null; Handler fileHandler = null; try{ //Creating consoleHandler and fileHandler consoleHandler = new ConsoleHandler(); fileHandler = new FileHandler("./javacodegeeks.log"); //Assigning handlers to LOGGER object LOGGER.addHandler(consoleHandler); LOGGER.addHandler(fileHandler); //Setting levels to handlers and LOGGER consoleHandler.setLevel(Level.ALL); fileHandler.setLevel(Level.ALL); LOGGER.setLevel(Level.ALL); LOGGER.config("Configuration done."); //Console handler removed LOGGER.removeHandler(consoleHandler); LOGGER.log(Level.FINE, "Finer logged"); }catch(IOException exception){ LOGGER.log(Level.SEVERE, "Error occur in FileHandler.", exception); } LOGGER.finer("Finest example on LOGGER handler completed."); } }
- If we run the above code, we will have the following results:
Jun 08, 2014 1:43:19 PM com.javacodegeeks.corejava.util.logging.HandlerExample main CONFIG: Configuration done.
This example also generates a log file javacodegeeks.log at the root directory of this project.
The file contains the following log.
<?xml version="1.0" encoding="windows-1252" standalone="no"?> <!DOCTYPE log SYSTEM "logger.dtd"> <log> <record> <date>2014-06-08T13:43:19</date> <millis>1402215199326</millis> <sequence>0</sequence> <logger>com.javacodegeeks.corejava.util.logging.LoggerExample</logger> <level>CONFIG</level> <class>com.javacodegeeks.corejava.util.logging.HandlerExample</class> <method>main</method> <thread>1</thread> <message>Configuration done.</message> </record> <record> <date>2014-06-08T13:43:19</date> <millis>1402215199376</millis> <sequence>1</sequence> <logger>com.javacodegeeks.corejava.util.logging.LoggerExample</logger> <level>FINE</level> <class>com.javacodegeeks.corejava.util.logging.HandlerExample</class> <method>main</method> <thread>1</thread> <message>Finer logged</message> </record> <record> <date>2014-06-08T13:43:19</date> <millis>1402215199376</millis> <sequence>2</sequence> <logger>com.javacodegeeks.corejava.util.logging.LoggerExample</logger> <level>FINER</level> <class>com.javacodegeeks.corejava.util.logging.HandlerExample</class> <method>main</method> <thread>1</thread> <message>Finest example on LOGGER handler completed.</message> </record> </log>
In this example, we have logged messages to both the FileHandler
and the ConsoleHandler
. Let’s discuss the above example.
ConsoleHandler()
: A constructor that creates a ConsoleHandler
for System.err
.
FileHandler(String pattern)
: A constructor that creates a FileHandler
to log messages in the given file name.
void addHandler(Handler handler)
: It’s an instance method from the Logger
class which is used to assign a handler to the logger object. You can assign multiple handlers to a single logger object. Like in this example, we have assigned both ConsoleHandler
and FileHandler
to a single logger object.
void setLevel(Level newLevel)
: This method is from the Logger
and the Handler
class. It sets the log level specifying which message levels will be logged by this logger. Message levels lower than the level set will be ignored.
void removeHandler(Handler handler)
: It is used to remove the associated handler from the logger object. Once the handler is removed, it will not be able to publish any further logs. In this example, we removed the ConsoleHandler
and all messages following it did not get published in the console.
void finer(String msg)
: This instance method is used to log a FINER message, if the logger is currently enabled for the FINER message else the logged message gets ignored.
The log messages published by the FileHandler
in the above example are in the XML format. It’s the default format of the FileHandler
. We can change the format of the handler using a Formatter
. In the next section, we will discuss about the Formatter
class and its uses.
3. Formatter
A Formatter
is used to format a LogRecord
. Each handler is associated with a formatter. Java provides the Formatter
as a parent class of two in-built formatter’s i.e. SimpleFormatter
and XMLFormatter
. Let’s see some examples:
FormatterExample.java
package com.javacodegeeks.corejava.util.logging; import java.io.IOException; import java.util.logging.Formatter; import java.util.logging.FileHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; public class FormatterExample { private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); public static void main(String[] args) { Handler fileHandler = null; Formatter simpleFormatter = null; try{ // Creating FileHandler fileHandler = new FileHandler("./javacodegeeks.formatter.log"); // Creating SimpleFormatter simpleFormatter = new SimpleFormatter(); // Assigning handler to logger LOGGER.addHandler(fileHandler); // Logging message of Level info (this should be publish in the default format i.e. XMLFormat) LOGGER.info("Finnest message: Logger with DEFAULT FORMATTER"); // Setting formatter to the handler fileHandler.setFormatter(simpleFormatter); // Setting Level to ALL fileHandler.setLevel(Level.ALL); LOGGER.setLevel(Level.ALL); // Logging message of Level finest (this should be publish in the simple format) LOGGER.finest("Finnest message: Logger with SIMPLE FORMATTER"); }catch(IOException exception){ LOGGER.log(Level.SEVERE, "Error occur in FileHandler.", exception); } } }
- If we run the above code, we will have the following results:
Jun 08, 2014 4:57:02 PM com.javacodegeeks.corejava.util.logging.FormatterExample main INFO: Finnest message: Logger with DEFAULT FORMATTER
This example also generates a log file javacodegeeks.formatter.log in the root directory of this project.
In the above example, we have used the SimpleFormatter
in our example, which prints the LogRecord
in a simple human readable format. Please note that before setting the SimpleFormatter
to the handler, we have logged a message which is published in an XML format, this is because the XMLFormatter
is the default formatter for the FileHandler
. Also note that the LogRecord
is also published in the console because the ConsoleHandler
is by default associated with the Logger
.
SimpleFormatter()
: This constructor is used to create a SimpleFormatter
object.
void setFormatter(Formatter newFormatter)
: This method is from the Handler
class and used to set the formatter to the handler.
4. Filter
A Filter
is an interface in java.util.logging
package. It is used to control the messages to be logged by the handler. Every Logger
and Handler
optionally can have a Filter
. The Filter
has a isLoggable
method which returns a boolean
. Before publishing the message the Logger
or the Handler
calls this method, if the method returns true the LogRecord
gets publish else it gets ignored.
FilterExample.java
package com.javacodegeeks.corejava.util.logging; import java.util.logging.Filter; import java.util.logging.LogRecord; import java.util.logging.Logger; public class FilterExample implements Filter{ private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); public static void main(String[] args) { //Setting filter FilterExample LOGGER.setFilter(new FilterExample()); //Since this message string does not contain the word important. Despite of being the Level SEVERE this will be ignored LOGGER.severe("This is SEVERE message"); //This will get published LOGGER.warning("This is important warning message"); } // This method will return true only if the LogRecord object contains the message which contains the word important @Override public boolean isLoggable(LogRecord record) { if(record == null) return false; String message = record.getMessage()==null?"":record.getMessage(); if(message.contains("important")) return true; return false; } }
- If we run the above code, we will have the following results:
Jun 08, 2014 5:13:46 PM com.javacodegeeks.corejava.util.logging.FilterExample main WARNING: This is important warning message
void setFilter(Filter newFilter)
: This method sets a Filter
which controls the output on this Logger
.
boolean isLoggable(LogRecord record)
: This method is from the Filter
interface which checks if a given LogRecord
object should be published or not.
5. Configuration
You can provide configuration properties to a Logger
using a configuration file. This helps you to remove the configuration from the code and provides an easy way to re-configure whenever it is required without changing the code again and again. This flexibility is provided by the LogManager
class.
ConfigurationExample.java
package com.javacodegeeks.corejava.util.logging; import java.io.FileInputStream; import java.io.IOException; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; public class ConfigurationExample { private static final LogManager logManager = LogManager.getLogManager(); private static final Logger LOGGER = Logger.getLogger("confLogger"); static{ try { logManager.readConfiguration(new FileInputStream("./javacodegeeks.properties")); } catch (IOException exception) { LOGGER.log(Level.SEVERE, "Error in loading configuration",exception); } } public static void main(String[] args) { LOGGER.fine("Fine message logged"); } }
This example reads a property file which contains the following properties:
handlers=java.util.logging.ConsoleHandler .level=ALL java.util.logging.ConsoleHandler.level=ALL java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter confLogger.level=ALL
- If we run the above code, we will have the following results:
Jun 08, 2014 5:23:25 PM com.javacodegeeks.corejava.util.logging.ConfigurationExample main FINE: Fine message logged
Let’s us discuss about the code and the configuration properties.
handlers: used to set the default handlers for all the loggers.
.level: sets the default Level
for all the loggers to ALL.
java.util.logging.ConsoleHandler.level: sets the default Level
for all the ConsoleHandler
to ALL.
java.util.logging.ConsoleHandler.formatter: sets the default formatter for the ConsoleHandler
to a SimpleFormatter
.
confLogger.level: sets the default level of the Logger
named confLogger to ALL.
Please note that you can override these properties in the code.
LogManager.getLogManager()
: This is a static factory method used to get a LogManager
object. There is a single global LogManager
object that is used to maintain a set of shared state about the Loggers
and the log services.
void readConfiguration(InputStream ins)
: This method is used to reinitialize the logging properties and re-read the logging configuration from the given stream, which should be in java.util.Properties
format.
6. Download the source code
You can download the source code of this example from here: LoggingExample.zip
In Logger and level package, In LoggerExample.java class why Logger.config method part is not printed on the console.