Introduction
The morale effects are startling. Enthusiasm jumps when there is a running system, even a simple one. Efforts redouble when the first picture from a new graphics software system appears on the screen, even if it is only a rectangle. One always has, at every stage in the process, a working system. I find that teams can grow much more complex entities in four months than they can build.
—FREDERIC P. BROOKS, JR., The Mythical Man-Month
What is logback?
Logback is intended as a successor to the popular log4j
project. It was designed by Ceki Gülcü, log4j's
founder. It builds upon a decade long experience gained in
designing industrial-strength logging systems. The resulting
product, logback is faster with a smaller footprint than all
existing logging systems, sometimes by a wide margin. Logback also
offers unique and rather useful features such as Markers,
parameterized logging statements, conditional stack tracing and
powerful event filtering. These are only few examples of useful
features logback has to offer. For its own error reporting,
logback relies on Status
objects, which greatly
facilitate troubleshooting. You may wish to rely on Status objects
in contexts other than logging. Logback-core bundles Joran, a
powerful and generic configuration system, which can be put to use
in your own projects to great effect.
First Baby Step
Requirements
Logback-classic module requires the presence slf4j-api.jar, logback-core.jar in addition to logback-classic.jar on the classpath.
The logback-*.jar files are part of the logback distribution whereas slf4j-api-${slf4j.version}.jar ships with SLF4J, a separate project.
Let us now begin experimenting with logback.
Example 1.1: Basic template for logging (logback-examples/src/main/java/chapter1/HelloWorld1.java)package chapter1; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HelloWorld1 { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld1"); logger.debug("Hello world."); } }
HelloWorld
class is defined in the
chapter1
package. It starts by importing the Logger
and LoggerFactory
classes defined in the SLF4J API, more specifically within the
org.slf4j
package.
On the first line of the main() method, the variable named
logger
is assigned a Logger
instance
retrieved by invoking the static getLogger
method
from the LoggerFactory
class. This logger is named
"chapter1.HelloWorld1". The main method proceeds to call the
debug
method of this logger passing "Hello World" as
an argument. We say that the main method contains a logging
statement of level DEBUG with the message "Hello world".
Note that the above example does not reference any logback classes. In most cases, as far as logging is concerned, your classes will only need to import SLF4J classes. Thus, the vast majority, if not all, of your classes will be cognizant of SLF4J API and oblivious to the existence of logback.
You can launch the first sample application, chapter1.HelloWorld1 with the command:
java chapter1.HelloWorld1
Launching the HelloWorld1
application will output
a single line on the console. By virtue of logback's default
configuration policy, when no default configuration file is found,
logback will add a ConsoleAppender
to the root
logger.
20:49:07.962 [main] DEBUG chapter1.HelloWorld1 - Hello world.
Logback can report information about its internal state using a
built-in status system. Important events occuring during logback's
lifetime can be accessed through a StatusManager
. For
the time being, let us instruct logback to print its internal
state. This is accomplished by a static method in the
LoggerStatusPrinter
class.
package chapter1; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.core.util.StatusPrinter; public class HelloWorld2 { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld2"); logger.debug("Hello world."); // print internal state LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); StatusPrinter.print(lc); } }
Running the HelloWorld2
application will produce
the following output:
12:49:22.203 [main] DEBUG chapter1.HelloWorld2 - Hello world. 12:49:22,078 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml] 12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml] 12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
Logback explains that having failed to find the
logback-test.xml and logback.xml configuration
files (discussed later), it configured itself using its default
policy, which is a basic ConsoleAppender
. An
Appender
is a class that can be seen as an output
destination. Appenders exist for many different destinations
including the console, files, Syslog, TCP Socket, JMS and many
more. Users can also easily create their own Appenders as
appropriate for their specific situation.
Note that in case of errors, logback will automatically print its internal state on the console.
The previous examples are rather simple. Actual logging in a larger application would not be that different. The general pattern for logging statements would not change. Only the configuration process would be different. However, you would probably want to customize or configure logback according to your needs. Logback configuration will be covered in subsequent chapters.
Note that in the above example we have instructed logback to
print its internal state by invoking
StatusPrinter.print()
method. Logback's internal status
information can be very useful in diagnosing logback-related
problems.
Here is a list of the three required steps in order to enable logging in your application.
- Configure the logback environment. You can do so in several more or less sophisticated ways. More on this later.
- In every class where you wish to perform logging, retrieve a
Logger
instance by invoking theorg.slf4j.LoggerFactory
class'getLogger()
method, passing the current class name or the class itself as a parameter. - Use this logger instance by invoking its printing methods, namely the debug(), info(), warn() and error(). This will produce logging output on the configured appenders.
Building logback
As its build tool, logback relies on Maven2, a widely-used open-source build tool.
Once you have installed Maven2, building the logback project,
including all its modules, should be as easy as issuing a mvn
package
command from within the directory where you
unarchived the logback distribution. Maven will automatically
download the required external libraries.
Logback distributions contain complete source code such that you can modify parts of logback library and build your own version of it. You may even redistribute the modified version, as long as you adhere to the conditions of the LGPL License.
Logback has been built and tested with the follwing JDKs.
JDK | Operating System |
---|---|
Sun JDK 1.5.0.06 | Windows XP |
Sun JDK 1.5.0.08 | Linux 64bit AMD |
WebLogic JRockit 1.5.0.14 | Linux 64bit AMD |
IBM JDK 1.6.0.1 | Linux 64bit AMD |