Java Logging using the Java Logging APIs
In this post, we will provide an overview of the Java Logging APIs along with some simple usage examples.
On tap:
1. Java Logging APIs Overview
1.1. Log Levels
1.2. Loggers
1.3. Handlers
1.4. Formatters
1.5. Filters
2. The Configuration File
2.1. Default Configuration
1 Java Logging APIs Overview
The Java Development Kit (JDK) provides a simple logging framework called the Java Logging APIs. The Java Logging APIs were developed to aid in the maintenance and serviceability of software running at customer sites. The following four requirements were key in the creation of the Java Logging APIs.
• Problem diagnosis by end users and system administrators.
• Problem diagnosis by field service engineers.
• Returning detailed information for diagnosis by the development team.
• Problem diagnosis by developers
The Java Logging API is made up of 4 main components:
• Loggers – A logger is responsible for allocating a log record and passing the log record to each of its output ‘handlers’. It also passes the log record to its parent Logger. (we will describe parent loggers later).
• Handlers – Before publishing a log record, a handler will optionally use a formatter to localize and format a log record.
• Formatters – A formatter’s primary responsible is to format a log message e.g. in XML, etc.
• Filters – Filters are optionally used by both Loggers and Handlers, a filter decides whether the logger or handler is interested in a particular log record. NOTE: Log Levels are also used. Filter’s are optional and provide customized filtering beyond that of Log Levels.
1.1 Log Levels
Define the severity of a log record. Java logging defines seven log levels. Levels can be applied to both Loggers and Handlers.
The seven levels in descending order are:
• SEVERE (highest value)
• WARNING
• INFO
• CONFIG
• FINE
• FINER
• FINEST (lowest value)
In addition to these Levels, there exists a level OFF that can be used to turn off logging. There also exists a level ALL that can be used to enable logging. Clients may also create custom log levels by inheriting from Level.
A Log records whose level is greater than or equal to the log Level will be published to the log. For example, setting the Level equal to Level.INFO will publish log records of Level INFO, WARNING, and ERROR.
1.2 Logger’s
The following code snippet creates a logger.
[code language=”Java”]
import java.util.logging.Logger
// It is recommended practice to name a logger after its class, however not required.
// e.g. MyClass.class.getName() instead of "com.wombat.nose"
private final static Logger LOGGER = Logger.getLogger("com.wombat.nose");
[/code]
Logger’s are hierarchical. For example, the logger above, named, “com.wombat.nose” will inherit attributes from a logger named “com.wombat”, “com”, and “” (the root logger). Configuring attributes on an ancestor, or ‘parent logger’ will affect all descendant loggers. As noted, in section 1.2., Logger’s send log records to both its handlers and its ‘parent logger’. (Essentially, this means log records are also sent to its parent’s handlers).
Logger’s may inherit various attributes including:
• Logging level – a Logger will inherit the first non null level in its ancestry
• Handlers – a Logger will log records to its handles, its parent handers, and so on up its hierarchy
1.3 Handlers
A Logger may have multiple handlers. Each of the Logger’s handlers will receive a log record from the Logger. The handler will then run the log record through an optional formatter and finally, publish the log record to the log.
Handlers can be turned off by setting handler.setLevel(Level.OFF). Similarly, they are turned on by calling handler.setLevel(…) using some Level other than OFF.
[code language=”Java”]
Logger logger = Logger.getLogger(MyClass.class.getName());
// set logger level
logger.setLevel(Level.INFO);
FileHandler fileHandler = new FileHandler("file.log");
// Set the handler level
// NOTE: This setting will ignore INFO records sent by the logger
fileHandler.setLevel(Level.WARNING);
logger.addHandler(fileHandler);
[/code]
1.4 Formatters
Formatters are used by Handlers to format the output of a log record. To format the handlers output, you can add a formatter to a handler.
[code language=”Java”]
Logger logger = Logger.getLogger(MyClass.class.getName());
logger.setLevel(Level.INFO);
Handler fileHandler = new FileHandler("file.log");
// set the handler’s formatter
fileHandler.setFormatter(new SimpleFormatter());
logger.addHandler(fileHandler);
[/code]
1.5 Filters
In addition to having logging levels, it is also desirable to support a more general filter mechanism, so that application code can attach arbitrary filters to control logging output.
[code language=”Java”]
Logger logger = Logger.getLogger(MyClass.class.getName());
logger.setLevel(Level.INFO);
logger.setFilter(new Filter() {
public boolean isLoggable(LogRecord log) {
boolean shouldPublish= true;
// some filter logic
return shouldPublish;
}
});
Handler fileHandler = new FileHandler("file.log");
// set the handler’s formatter
fileHandler.setFormatter(new SimpleFormatter());
logger.addHandler(fileHandler);
[/code]
2. The Configuration File logging.properties
The configuration file is used for simple configuration. It is read by the JVM on startup and thus is used to setup the initial configuration. The initial configuration may specify levels for particular named loggers. The initial configuration may also contain arbitrary properties for use by Handlers or Loggers. By convention these properties should use names starting with the name of the handler class or the name of the main Logger for the subsystem.
The configuration file is found in JRE/lib/logging.properties.
2.1. Default Configuration
The default configuration sets the default log level to Level.INFO. It also establishes a ConsoleHandler on the root logger. The console handle is also configured with Level.INFO and uses the SimpleFormatter. (see default configuration below)
To declaratively disable parent handlers, (including global handlers) for a specific log handler, you can use the following statement in logging.properties:
com.xyz.foo.useParentHandlers=false
where com.xyz.foo identifies the specific application’s logger.
[code]</pre>
###########################################################
# Global properties
############################################################
# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
# default file output is in user’s home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Example to customize the SimpleFormatter output format
# to print one-line log message like this:
# : [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
<pre>[/code]
Thank you!
1 Response
[…] For an overview of the Java Logging APIs, including a description of loggers and handlers, see this post. […]