Version 1.3
Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013 Lars Vogel
14.01.2013
| Revision History | |||
|---|---|---|---|
| Revision 0.1 | 01.07.2007 | Lars Vogel |
Created |
| Revision 0.2 - 1.3 | 09.07.2007 - 14.01.2013 | Lars Vogel |
Bug fixes and Enhancements |
Table of Contents
The JDK contains the Java Logging API. Via a logger you can save text to a central place to report on errors, provide additional information about your program, etc. This logging API allows to configure how messages are written by which class with which priority.
The
java.util.logging
package provides the logging
capabilities
via the
Logger
class.
To create a logger in your Java coding you can use the following snippet.
import java.util.logging.Logger; private final static Logger LOGGER = Logger.getLogger(MyClass.class .getName());
The
Logger
you create a actually a hierarchy of Loggers, and a . (dot) in the
hierarchy indicates a level in the hierarchy. So if you get a Logger
for the
com.example
key this Logger is a child of the
com
Logger and the
com
Logger is child of the Logger for the empty String. You can configure
the main logger and this affects all its children.
The log levels define the severity of a message. The
Level
class
is used to define which messages should be written to
the log.
The following lists the Log Levels in descending order:
SEVERE (highest)
WARNING
INFO
CONFIG
FINE
FINER
FINEST
In addition to that you have also the levels OFF and ALL to turn the logging of or to log everything.
For example the following example code sets the logger to the
info
level,
which means all messages with severe, warning and info will
be
logged.
LOGGER.setLevel(Level.INFO);
Each logger can have access to several handler.
The handler receives the log message from the logger and exports it to a certain target
A handler can be turn off with the
setLevel(Level.OFF)
method
and
turned on
with
setLevel()
method.
You have several standard handler, the following list gives some examples.
ConsoleHandler: Write the log message to console
FileHandler: Writes the log message to file
Log Levels INFO and higher will be automatically written to the console.
Each handlers output can be configured with a formatter
Available formatter
SimpleFormatter Generate all messages as text
XMLFormatter Generates XML output for the log messages
You can also build your own formatter. The following is an example of a formatter which will use create HTML output.
package de.vogella.logger; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; //This custom formatter formats parts of a log record to a single line class MyHtmlFormatter extends Formatter { // This method is called for every log records public String format(LogRecord rec) { StringBuffer buf = new StringBuffer(1000); // Bold any levels >= WARNING buf.append("<tr>"); buf.append("<td>"); if (rec.getLevel().intValue() >= Level.WARNING.intValue()) { buf.append("<b>"); buf.append(rec.getLevel()); buf.append("</b>"); } else { buf.append(rec.getLevel()); } buf.append("</td>"); buf.append("<td>"); buf.append(calcDate(rec.getMillis())); buf.append(' '); buf.append(formatMessage(rec)); buf.append('\n'); buf.append("<td>"); buf.append("</tr>\n"); return buf.toString(); } private String calcDate(long millisecs) { SimpleDateFormat date_format = new SimpleDateFormat("MMM dd,yyyy HH:mm"); Date resultdate = new Date(millisecs); return date_format.format(resultdate); } // This method is called just after the handler using this // formatter is created public String getHead(Handler h) { return "<HTML>\n<HEAD>\n" + (new Date()) + "\n</HEAD>\n<BODY>\n<PRE>\n" + "<table width=\"100%\" border>\n " + "<tr><th>Level</th>" + "<th>Time</th>" + "<th>Log Message</th>" + "</tr>\n"; } // This method is called just after the handler using this // formatter is closed public String getTail(Handler h) { return "</table>\n </PRE></BODY>\n</HTML>\n"; } }
The log manager is responsible for creating and managing the logger and the maintenance of the configuration.
We could set the logging level for a package, or even a set
of
packages, by calling the
LogManager.setLevel(String name,
Level level)
method. So, for example, we could set the
logging level of all loggers
"logging" to Level.FINE by
making this call:
LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME).setLevel(Level.FINE);
It is common practice to use the fully qualified name of each class whose activity is being logged as a message category because this allows developers to fine-tune log settings for each class.
Using the fully qualified class name of your class as the name of your Logger is the approach recommended by the Logging API documentation.
This example is stored in the project called de.vogella.logger.
Create your own formatter class.
package de.vogella.logger; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; //This custom formatter formats parts of a log record to a single line class MyHtmlFormatter extends Formatter { // This method is called for every log records public String format(LogRecord rec) { StringBuffer buf = new StringBuffer(1000); // Bold any levels >= WARNING buf.append("<tr>"); buf.append("<td>"); if (rec.getLevel().intValue() >= Level.WARNING.intValue()) { buf.append("<b>"); buf.append(rec.getLevel()); buf.append("</b>"); } else { buf.append(rec.getLevel()); } buf.append("</td>"); buf.append("<td>"); buf.append(calcDate(rec.getMillis())); buf.append(' '); buf.append(formatMessage(rec)); buf.append('\n'); buf.append("<td>"); buf.append("</tr>\n"); return buf.toString(); } private String calcDate(long millisecs) { SimpleDateFormat date_format = new SimpleDateFormat("MMM dd,yyyy HH:mm"); Date resultdate = new Date(millisecs); return date_format.format(resultdate); } // This method is called just after the handler using this // formatter is created public String getHead(Handler h) { return "<HTML>\n<HEAD>\n" + (new Date()) + "\n</HEAD>\n<BODY>\n<PRE>\n" + "<table width=\"100%\" border>\n " + "<tr><th>Level</th>" + "<th>Time</th>" + "<th>Log Message</th>" + "</tr>\n"; } // This method is called just after the handler using this // formatter is closed public String getTail(Handler h) { return "</table>\n </PRE></BODY>\n</HTML>\n"; } }
Initialize the logger via the following code. This Logger class uses the new HTML formater you created.
package de.vogella.logger; import java.io.IOException; import java.util.logging.FileHandler; import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; public class MyLogger { static private FileHandler fileTxt; static private SimpleFormatter formatterTxt; static private FileHandler fileHTML; static private Formatter formatterHTML; static public void setup() throws IOException { // Get the global logger to configure it Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); logger.setLevel(Level.INFO); fileTxt = new FileHandler("Logging.txt"); fileHTML = new FileHandler("Logging.html"); // Create txt Formatter formatterTxt = new SimpleFormatter(); fileTxt.setFormatter(formatterTxt); logger.addHandler(fileTxt); // Create HTML Formatter formatterHTML = new MyHtmlFormatter(); fileHTML.setFormatter(formatterHTML); logger.addHandler(fileHTML); } }
The following example class demonstrates how you can use your
MyLogger
class to create log messages.
package de.vogella.logger.test; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import de.vogella.logger.MyLogger; public class UseLogger { // Always use the classname, this way you can refactor private final static Logger LOGGER = Logger.getLogger(UseLogger.class .getName()); public void doSomeThingAndLog() { // Image here some real work // Now we demo the logging // Set the LogLevel to Severe, only severe Messages will be written LOGGER.setLevel(Level.SEVERE); LOGGER.severe("Info Log"); LOGGER.warning("Info Log"); LOGGER.info("Info Log"); LOGGER.finest("Really not important"); // Set the LogLevel to Info, severe, warning and info will be written // Finest is still not written LOGGER.setLevel(Level.INFO); LOGGER.severe("Info Log"); LOGGER.warning("Info Log"); LOGGER.info("Info Log"); LOGGER.finest("Really not important"); } public static void main(String[] args) { UseLogger tester = new UseLogger(); try { MyLogger.setup(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Problems with creating the log files"); } tester.doSomeThingAndLog(); } }
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.
http://www.onjava.com/pub/a/onjava/2002/06/19/log.html
An introduction to the Java Logging API," Brian Gilstrap (OnJava.com, June 2002) talks about the use of the standard logging API.
http://www.fawcette.com/javapro/2002_06/magazine/features/shalloway/
The Java Logging API," Stuart Dabbs Halloway (JavaPro, June 2002) is another good introduction to the API.