[logback-dev] svn commit: r1262 - in logback/trunk: logback-examples/src/main/java/chapter1 logback-examples/src/main/java/chapter2 logback-site/src/site/xdocTemplates/manual
noreply.seb at qos.ch
noreply.seb at qos.ch
Mon Jan 22 16:58:05 CET 2007
Author: seb
Date: Mon Jan 22 16:58:04 2007
New Revision: 1262
Added:
logback/trunk/logback-examples/src/main/java/chapter2/
logback/trunk/logback-examples/src/main/java/chapter2/Bar.java
logback/trunk/logback-examples/src/main/java/chapter2/HelloWorld2.java
logback/trunk/logback-examples/src/main/java/chapter2/MyAppWithConfigFile.java
logback/trunk/logback-examples/src/main/java/chapter2/sample-config-1.xml
logback/trunk/logback-examples/src/main/java/chapter2/sample-config-2.xml
logback/trunk/logback-examples/src/main/java/chapter2/sample-config-3.xml
logback/trunk/logback-site/src/site/xdocTemplates/manual/architecture.xml
logback/trunk/logback-site/src/site/xdocTemplates/manual/introduction.xml
Removed:
logback/trunk/logback-examples/src/main/java/chapter1/Bar.java
logback/trunk/logback-examples/src/main/java/chapter1/MyApp.java
logback/trunk/logback-examples/src/main/java/chapter1/MyAppWithConfigFile.java
logback/trunk/logback-examples/src/main/java/chapter1/sample-config-1.xml
logback/trunk/logback-examples/src/main/java/chapter1/sample-config-2.xml
logback/trunk/logback-examples/src/main/java/chapter1/sample-config-3.xml
Modified:
logback/trunk/logback-site/src/site/xdocTemplates/manual/index.xml
Log:
Split of the short intro into a chapter1: introduction and chapter2: architecture. Moved examples accordingly
Added: logback/trunk/logback-examples/src/main/java/chapter2/Bar.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter2/Bar.java Mon Jan 22 16:58:04 2007
@@ -0,0 +1,21 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package chapter2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class Bar {
+ Logger logger = LoggerFactory.getLogger(Bar.class);
+
+ public void doIt() {
+ logger.debug("doing my job");
+ }
+}
\ No newline at end of file
Added: logback/trunk/logback-examples/src/main/java/chapter2/HelloWorld2.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter2/HelloWorld2.java Mon Jan 22 16:58:04 2007
@@ -0,0 +1,24 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package chapter2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.util.LoggerStatusPrinter;
+
+public class HelloWorld2 {
+
+ public static void main(String[] args) {
+ Logger logger = LoggerFactory.getLogger("chapter2.HelloWorld2");
+ logger.debug("Hello world.");
+ LoggerStatusPrinter.printStatusInDefaultContext();
+ }
+}
Added: logback/trunk/logback-examples/src/main/java/chapter2/MyAppWithConfigFile.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter2/MyAppWithConfigFile.java Mon Jan 22 16:58:04 2007
@@ -0,0 +1,41 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 1999-2006, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package chapter2;
+
+//Import SLF4J classes.
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class MyAppWithConfigFile {
+
+ public static void main(String[] args) {
+ Logger logger = LoggerFactory.getLogger(MyAppWithConfigFile.class);
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ try {
+ JoranConfigurator configurator = new JoranConfigurator();
+ lc.shutdownAndReset();
+ configurator.setContext(lc);
+ configurator.doConfigure(args[0]);
+ } catch (JoranException je) {
+ StatusPrinter.print(lc.getStatusManager());
+ }
+ logger.info("Entering application.");
+ Bar bar = new Bar();
+ bar.doIt();
+ logger.info("Exiting application.");
+
+ }
+}
Added: logback/trunk/logback-examples/src/main/java/chapter2/sample-config-1.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter2/sample-config-1.xml Mon Jan 22 16:58:04 2007
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
Added: logback/trunk/logback-examples/src/main/java/chapter2/sample-config-2.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter2/sample-config-2.xml Mon Jan 22 16:58:04 2007
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <appender name="FILE"
+ class="ch.qos.logback.core.FileAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ <File>sample-log.txt</File>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
Added: logback/trunk/logback-examples/src/main/java/chapter2/sample-config-3.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter2/sample-config-3.xml Mon Jan 22 16:58:04 2007
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <appender name="FILE"
+ class="ch.qos.logback.core.FileAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ <File>sample-log.txt</File>
+ </appender>
+
+ <logger name="chapter2">
+ <level value="info" />
+ </logger>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
Added: logback/trunk/logback-site/src/site/xdocTemplates/manual/architecture.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/xdocTemplates/manual/architecture.xml Mon Jan 22 16:58:04 2007
@@ -0,0 +1,1037 @@
+<document>
+ <!--
+
+ Warning: do not use any auto-format function on this file.
+ Since "source" divs use pre as white-space, it affects the
+ look of the code parts in this document.
+
+ -->
+
+
+ <body>
+ <h2>Chapter 2: Architecture</h2>
+ <div class="author">
+ Authors: Ceki Gülcü, Sébastien Pennec
+ </div>
+
+
+ <table>
+ <tr>
+ <td valign="top" align="top">
+ <a rel="license"
+ href="http://creativecommons.org/licenses/by-nc-sa/2.5/">
+ <img alt="Creative Commons License"
+ style="border-width: 0"
+ src="http://creativecommons.org/images/public/somerights20.png" />
+ </a>
+ </td>
+ <td>
+ <p>Copyright © 2000-2006, QOS.ch</p>
+
+ <p>
+ <!--Creative Commons License-->
+ This work is licensed under a
+ <a rel="license"
+ href="http://creativecommons.org/licenses/by-nc-sa/2.5/">
+ Creative Commons
+ Attribution-NonCommercial-ShareAlike 2.5
+ License
+ </a>
+ .
+ <!--/Creative Commons License-->
+ </p>
+ </td>
+ </tr>
+ </table>
+
+
+ <h2>Logback architecture</h2>
+
+ <p>
+ Logback's basic architecture is sufficiently generic so as to
+ apply under different circumstances. At present time, logback is
+ divided into three modules, Core, Classic and Access.
+ </p>
+
+ <p>
+ The <em>core</em> module lays the groundwork for the other two
+ modules. The <em>classic</em> module extends <em>core</em>. The
+ classic module corresponds to a significantly improved
+ version of log4j. Logback-classic natively implements the <a
+ href="http://www.slf4j.org">SLF4J API</a> so that you can
+ readily switch back and forth between logback and other logging
+ systems such as log4j or JDK14 Logging. The third module called
+ <em>access</em> integrates with Servlet containers to provide
+ HTTP-access log functionality. The access module will be covered
+ in a <a href="access.html">separate document</a>.
+ </p>
+ <p>
+ In the reminder of this document, we will write "logback" to refer to the
+ logback classic module.
+ </p>
+
+ <h2>Logger, Appenders and Layouts</h2>
+
+ <p>
+ Logback has three main types: <code>Logger</code>,
+ <code>Appender</code> and <code>Layout</code>. These three types of components work
+ together to enable developers to log messages according to
+ message type and level, and to control at runtime how these
+ messages are formatted and where they are reported.
+ </p>
+ <p>
+ The Logger class is part of the classic module. On the other
+ hand, the <code>Appender</code> and <code>Layout</code> interfaces
+ are part of the core module. For the sake of genericity,
+ logback-core has no notion of loggers.
+ </p>
+
+ <h3>Logger context</h3>
+
+ <p>The first and foremost advantage of any logging API over plain
+ <code>System.out.println</code> resides in its ability to disable
+ certain log statements while allowing others to print
+ unhindered. This capability assumes that the logging space, that
+ is, the space of all possible logging statements, is categorized
+ according to some developer-chosen criteria. In logback, this
+ categorization is an inherent part of loggers.
+ </p>
+
+ <p>
+ Loggers are named entities. Their names are case-sensitive and
+ they follow the hierarchical naming rule:
+ </p>
+ <div class="definition">
+ <div class="deftitle">Named Hierarchy</div>
+ <p>
+ A logger is said to be an ancestor of another logger if
+ its name followed by a dot is a prefix of the descendant
+ logger name. A logger is said to be a parent of a child
+ logger if there are no ancestors between itself and the
+ descendant logger.
+ </p>
+ </div>
+
+ <p>
+ For example, the logger named <code>"com.foo"</code>
+ is a parent of the logger named <code>"com.foo.Bar"</code>.
+ Similarly, <code>"java"</code>
+ is a parent of <code>"java.util"</code> and an ancestor of
+ <code>"java.util.Vector"</code>.
+ This naming scheme should be familiar to most developers.
+ </p>
+ <p>
+ The root logger resides at the top of the logger hierarchy. It
+ is exceptional in that it is part of every hierarchy at its
+ inception. Like every logger, it can be retrieved by its name,
+ as follows:
+ </p>
+ <div class="source"><pre>Logger rootLogger = LoggerFactory.getLogger(<a href="apidocs/constant-values.html#ch.qos.logback.classic.LoggerContext.ROOT_NAME">LoggerContext.<em>ROOT_NAME</em></a>);</pre></div>
+
+ <p>
+ All other loggers are also retrieved with the class static
+ <code>getLogger</code> method found in the <a
+ href="http://www.slf4j.org/api/org/slf4j/Logger.html">org.slf4j.LoggerFactory</a>
+ class. This method takes the name of the desired logger as a
+ parameter. Some of the basic methods in the <code>Logger</code>
+ interface are listed below.
+ </p>
+
+ <div class="source"><pre>package org.slf4j;
+public interface Logger {
+
+ // Printing methods:
+ public void debug(String message);
+ public void info(String message);
+ public void warn(String message);
+ public void error(String message);
+ public void fatal(String message);
+}</pre></div>
+
+ <p>
+ Loggers may be assigned levels. The set of possible levels, that
+ is DEBUG, INFO, WARN and ERROR are defined in the
+ <code>ch.qos.logback.classic.Level</code> class. Note that in
+ logback, the level class is final and cannot be derived, as a
+ much more flexible approach exist in the form of Marker objects.
+ </p>
+
+ <p>
+ If a given logger is not assigned a level, then it inherits
+ one from its closest ancestor with an assigned level. More
+ formally:
+ </p>
+
+ <div class="definition">
+ <div class="deftitle">Level Inheritance</div>
+ <p>
+ The effective level for a given logger <em>L</em>, is equal to
+ the first non-null level in its hierarchy, starting at
+ <em>L</em> itself and proceeding upwards in the hierarchy
+ towards the root logger.
+ </p>
+ </div>
+
+ <p>
+ To ensure that all loggers can eventually inherit a level, the
+ root logger always has an assigned level. By default, this level
+ is DEBUG.
+ </p>
+ <p>
+ Below are four examples with various assigned level values and
+ the resulting effective (inherited) levels according to the
+ level inheritance rule.
+ </p>
+
+ <em>Example 1</em>
+ <table>
+ <tr>
+ <th>
+ Logger name
+ </th>
+ <th>
+ Assigned level
+ </th>
+
+ <th>
+ Effective level
+ </th>
+ </tr>
+ <tr>
+ <td>root</td>
+ <td>DEBUG</td>
+ <td>DEBUG</td>
+ </tr>
+ <tr>
+ <td>X</td>
+ <td>none</td>
+ <td>DEBUG</td>
+ </tr>
+
+ <tr>
+ <td>X.Y</td>
+ <td>none</td>
+ <td>DEBUG</td>
+ </tr>
+ <tr>
+ <td>X.Y.Z</td>
+ <td>none</td>
+ <td>DEBUG</td>
+ </tr>
+ </table>
+
+ <p> In example 1 above, only the root logger is assigned a level.
+ This level value, <code>DEBUG</code>, is inherited by the other
+ loggers <code>X</code>, <code>X.Y</code> and <code>X.Y.Z</code>
+ </p>
+
+ <em>Example 2</em>
+ <table>
+ <tr>
+ <th>
+ Logger name
+ </th>
+ <th>
+ Assigned level
+ </th>
+
+ <th>
+ Effective level
+ </th>
+ </tr>
+ <tr align="left">
+ <td>root</td>
+ <td>ERROR</td>
+ <td>ERROR</td>
+ </tr>
+ <tr align="left">
+ <td>X</td>
+ <td>INFO</td>
+ <td>INFO</td>
+ </tr>
+
+ <tr align="left">
+ <td>X.Y</td>
+ <td>DEBUG</td>
+ <td>DEBUG</td>
+ </tr>
+ <tr align="left">
+ <td>X.Y.Z</td>
+ <td>WARN</td>
+ <td>WARN</td>
+ </tr>
+ </table>
+
+ <p>In example 2 above, all loggers have an assigned level value.
+ Level inheritence does not come into play.
+ </p>
+
+ <em>Example 3</em>
+ <table>
+ <tr>
+ <th>
+ Logger name
+ </th>
+ <th>
+ Assigned level
+ </th>
+ <th>
+ Effective level
+ </th>
+ </tr>
+ <tr align="left">
+ <td>root</td>
+ <td>DEBUG</td>
+ <td>DEBUG</td>
+ </tr>
+
+ <tr align="left">
+ <td>X</td>
+ <td>INFO</td>
+ <td>INFO</td>
+ </tr>
+ <tr align="left">
+ <td>X.Y</td>
+ <td>none</td>
+ <td>INFO</td>
+ </tr>
+ <tr align="left">
+ <td>X.Y.Z</td>
+ <td>ERROR</td>
+ <td>ERROR</td>
+ </tr>
+ </table>
+ <p>
+ In example 3 above, the loggers <code>root</code>, <code>X</code>
+ and <code>X.Y.Z</code> are assigned the levels <code>DEBUG</code>,
+ <code>INFO</code> and <code>ERROR</code>
+ respectively. Logger <code>X.Y</code>
+ inherits its level value from its parent <code>X</code>.
+ </p>
+ <em>Example 4</em>
+ <table>
+
+ <tr>
+ <th>
+ Logger name
+ </th>
+ <th>
+ Assigned level
+ </th>
+ <th>
+ Effective level
+ </th>
+ </tr>
+ <tr align="left">
+ <td>root</td>
+ <td>DEBUG</td>
+ <td>DEBUG</td>
+ </tr>
+
+ <tr align="left">
+ <td>X</td>
+ <td>INFO</td>
+ <td>INFO</td>
+ </tr>
+ <tr align="left">
+ <td>X.Y</td>
+ <td>none</td>
+ <td>INFO</td>
+ </tr>
+ <tr align="left">
+ <td>X.Y.Z</td>
+ <td>none</td>
+ <td>INFO</td>
+ </tr>
+ </table>
+
+
+ <p>In example 4 above, the loggers <code>root</code> and
+ <code>X</code> and are assigned the levels <code>DEBUG</code> and
+ <code>INFO</code> respectively. The loggers <code>X.Y</code> and
+ <code>X.Y.Z</code> inherit their level value from their nearest
+ parent <code>X</code>, which has an assigned level.
+ </p>
+
+ <h3>Printing methods</h3>
+
+ <p>By definition, the printing method determines the level of a
+ logging request. For example, if <code>L</code> is a logger
+ instance, then the statement <code>L.info("..")</code> is a
+ logging statement of level INFO.
+ </p>
+
+ <p>A logging request is said to be <em>enabled</em> if its level
+ is higher than or equal to the level of its logger. Otherwise, the
+ request is said to be <em>disabled</em>. A logger without an
+ assigned level will inherit one from the context. This rule is
+ summarized below.
+ </p>
+
+ <div class="definition">
+ <div class="deftitle">Basic Selection Rule</div>
+
+ <p>A log request of level <em>p</em> in a logger with an
+ effective level <em>q</em>, is enabled if <em>p >= q</em>.
+ </p>
+ </div>
+
+ <p>
+ This rule is at the heart of logback. It assumes
+ that levels are ordered as follows:
+ <code>DEBUG < INFO < WARN < ERROR< OFF</code>.
+ </p>
+
+ <p>In a more graphic way, here is how the selection rule works. In
+ the following table, the vertical header shows the the level of
+ the logging request, designated by <em>p</em>, while the
+ horizontal header shows effective level of the logger, designated
+ by <em>q</em>.
+ </p>
+
+ <table>
+ <tr>
+ <th><span style="align:center"><em>p</em>/<em>q</em></span></th>
+ <th>DEBUG</th>
+ <th>INFO</th>
+ <th>WARN</th>
+ <th>ERROR</th>
+ <th>OFF</th>
+ </tr>
+ <tr>
+ <th>DEBUG</th>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ </tr>
+ <tr>
+ <th>INFO</th>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ </tr>
+ <tr>
+ <th>WARN</th>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ </tr>
+ <tr>
+ <th>ERROR</th>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="redBold">NO</span></td>
+ </tr>
+ </table>
+
+ <p>Here is an example of the basic selection rule.</p>
+
+ <div class="source"><pre>// get a logger instance named "com.foo", with an <span class="blue">INFO</span> level.
+Logger logger = LoggerFactory.getLogger("com.foo");
+//set its Level to <span class="blue">INFO</span>
+logger.setLevel(Level. <span class="blue">INFO</span>);
+Logger barlogger = LoggerFactory.getLogger("com.foo.Bar");
+
+// This request is enabled, because <span class="green bold">WARN</span> >= <span class="blue">INFO</span>
+logger.<span class="green bold">warn</span>("Low fuel level.");
+
+// This request is disabled, because <span class="green bold">DEBUG</span> < <span class="blue">INFO</span>.
+logger.<span class="green bold">debug</span>("Starting search for nearest gas station.");
+
+// The logger instance barlogger, named "com.foo.Bar",
+// will inherit its level from the logger named
+// "com.foo" Thus, the following request is enabled
+// because <span class="green bold">INFO</span> >= <span class="blue">INFO</span>.
+barlogger.<span class="green bold">info</span>("Located nearest gas station.");
+
+// This request is disabled, because <span class="green bold">DEBUG</span> < <span class="blue">INFO</span>.
+barlogger.<span class="green bold">debug</span>("Exiting gas station search");</pre></div>
+
+ <h3>Retrieving Loggers</h3>
+ <p>
+ Calling the <code><a href="/apidocs/org/slf4j/LoggerFactory.html#getLogger(java.lang.String)">LoggerFactory.getLogger</a></code>
+ method with the same name will always return a reference to
+ the exact same logger object.
+ </p>
+
+ <p>For example, in</p>
+ <div class="source"><pre>Logger x = LoggerFactory.getLogger("wombat");
+Logger y = LoggerFactory.getLogger("wombat");</pre></div>
+
+ <p>
+ <code>x</code> and <code>y</code> refer to
+ <em>exactly</em> the same logger object.
+ </p>
+
+ <p>
+ Thus, it is possible to configure a logger and then to
+ retrieve the same instance somewhere else in the code
+ without passing around references. In fundamental
+ contradiction to biological parenthood, where parents always
+ preceed their children, logback loggers can be
+ created and configured in any order. In particular, a
+ "parent" logger will find and link to its descendants even
+ if it is instantiated after them.
+ </p>
+ <p>
+ Configuration of the logback environment is typically done
+ at application initialization. The preferred way is by
+ reading a configuration file. This approach will be
+ discussed shortly.
+ </p>
+ <p>
+ Logback makes it easy to name loggers by <em>software
+ component</em>. This can be accomplished by instantiating a
+ logger in each class, with the logger name equal to the fully
+ qualified name of the class. This is a useful and
+ straightforward method of defining loggers. As the log output
+ bears the name of the generating logger, this naming strategy
+ makes it easy to identify the origin of a log message. However,
+ this is only one possible, albeit common, strategy for naming
+ loggers. Logback does not restrict the possible set of
+ loggers. As a developer, you are free to name loggers as you
+ wish.
+ </p>
+
+ <p>Nevertheless, naming loggers after the class where they are
+ located seems to be the best general strategy known so far.
+ </p>
+
+ <h3>Appenders and Layouts</h3>
+
+ <p>
+ The ability to selectively enable or disable logging requests
+ based on their logger is only part of the picture. Logback
+ allows logging requests to print to multiple destinations. In
+ logback speak, an output destination is called an
+ appender. Currently, appenders exist for the console, files,
+ remote socket servers, to MySQL, PostgreSQL, Oracle and other
+ databases, JMS, and remote UNIX Syslog daemons.
+
+ <!--It is also possible to log asynchronously. -->
+ </p>
+
+ <p>More than one appender can be attached to a logger.</p>
+
+ <p> The <code><a href="apidocs/ch/qos/logback/classic/Logger.html#addAppender(ch.qos.logback.core.Appender)">addAppender</a></code> method adds an appender to a
+ given logger. Each enabled logging request for a given logger
+ will be forwarded to all the appenders in that logger as well as
+ the appenders higher in the hierarchy. In other words, appenders are
+ inherited additively from the logger hierarchy. For example, if a
+ console appender is added to the root logger, then all enabled
+ logging requests will at least print on the console. If in
+ addition a file appender is added to a logger, say <em>L</em>,
+ then enabled logging requests for <em>L</em> and <em>L</em>'s
+ children will print on a file <em>and</em> on the console. It is
+ possible to override this default behavior so that appender
+ accumulation is no longer additive by setting the additivity flag
+ of a logger to false.
+ </p>
+
+ <p>
+ The rules governing appender additivity are summarized
+ below.
+ </p>
+ <div class="definition">
+
+ <div class="deftitle">Appender Additivity</div>
+
+ <p>
+ The output of a log statement of logger <em>L</em>
+ will go to all the appenders in <em>L</em>
+ and its ancestors. This is the meaning of the term
+ "appender additivity".
+ </p>
+
+ <p>
+ However, if an ancestor of logger <em>L</em>, say
+ <em>P</em>, has the additivity flag set to false, then
+ <em>L</em>'s output will be directed to all the appenders in
+ <em>L</em> and it's ancestors upto and including
+ <em>P</em> but not the appenders in any of the ancestors of
+ <em>P</em>.
+ </p>
+
+ <p>
+ Loggers have their additivity flag set to true by
+ default.
+ </p>
+
+ </div>
+ The table below shows an example:
+
+ <table class="bodyTable">
+ <tr>
+ <th>Logger Name</th>
+ <th>Attached Appenders</th>
+ <th>Additivity Flag</th>
+ <th>Output Targets</th>
+ <th>Comment</th>
+ </tr>
+ <tr>
+ <td>root</td>
+ <td>A1</td>
+ <td>not applicable</td>
+ <td>A1</td>
+
+ <td>Since the root logger stands at the top of the logger
+ hiearchy, the additivity flag does not apply to it.
+ </td>
+ </tr>
+ <tr>
+ <td>x</td>
+ <td>A-x1, A-x2</td>
+ <td>true</td>
+ <td>A1, A-x1, A-x2</td>
+ <td>Appenders of "x" and of root.</td>
+ </tr>
+ <tr>
+ <td>x.y</td>
+ <td>none</td>
+ <td>true</td>
+ <td>A1, A-x1, A-x2</td>
+ <td>Appenders of "x" and of root.</td>
+ </tr>
+ <tr>
+ <td>x.y.z</td>
+ <td>A-xyz1</td>
+ <td>true</td>
+ <td>A1, A-x1, A-x2, A-xyz1</td>
+ <td>Appenders of "x.y.z", "x" and of root.</td>
+ </tr>
+ <tr>
+ <td>security</td>
+ <td>A-sec</td>
+ <td class="blue"><span class="blue">false</span></td>
+ <td>A-sec</td>
+
+ <td>
+ No appender accumulation since the additivity flag is set to
+ <code>false</code>. Only appender A-sec will be used.
+ </td>
+ </tr>
+ <tr>
+ <td>security.access</td>
+ <td>none</td>
+ <td>true</td>
+ <td>A-sec</td>
+ <td>
+ Only appenders of "security" because the additivity
+ flag in "security" is set to
+ <code>false</code>.
+ </td>
+ </tr>
+ </table>
+
+
+ <p>
+ More often than not, users wish to customize not only the
+ output destination but also the output format. This is
+ accomplished by associating a <em>layout</em>
+ with an appender. The layout is responsible for formatting
+ the logging request according to the user's wishes, whereas
+ an appender takes care of sending the formatted output to
+ its destination. The <code>PatternLayout</code>, part of the standard
+ logback distribution, lets the user specify the output
+ format according to conversion patterns similar to the C
+ language <code>printf</code>
+ function.
+ </p>
+
+ <p>
+ For example, the PatternLayout with the conversion pattern
+ "%-4relative [%thread] %-5level %logger{32} - %msg%n" will output something akin to:
+ </p>
+
+ <div class="source"><pre>176 [main] DEBUG chapter2.HelloWorld2 - Hello world.</pre></div>
+
+ <p>
+ The first field is the number of milliseconds elapsed since
+ the start of the program. The second field is the thread
+ making the log request. The third field is the level of the
+ log request. The fourth field is the name of the logger
+ associated with the log request. The text after the '-' is
+ the message of the request.
+ </p>
+
+ <h3>Parameterized logging</h3>
+
+ <p>
+ Given that loggers in logback-classic implement the <a
+ href="http://www.slf4j.org/api/org/slf4j/Logger.html">SLF4J's
+ Logger interface</a>, certain printing methods admit more than
+ one parameter. These printing method variants are mainly
+ intended to improve performance while minimizing the impact on
+ the readability of the code.
+ </p>
+
+ <p>
+ For some Logger <code>logger</code>, writing,
+ </p>
+
+ <div class="source"><pre>logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));</pre></div>
+
+ <p>
+ incurs the cost of constructing the message parameter, that
+ is converting both integer <code>i</code> and <code>entry[i]</code>
+ to a String, and concatenating intermediate strings. This,
+ regardless of whether the message will be logged or not.
+ </p>
+
+ <p>
+ One possible way to avoid the cost of parameter construction
+ is by surrounding the log statement with a test. Here is an
+ example.
+ </p>
+
+ <div class="source"><pre>if(logger.isDebugEnabled()) {
+ logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
+}</pre></div>
+
+
+ <p>
+ This way you will not incur the cost of parameter
+ construction if debugging is disabled for <code>logger</code>.
+ On the other hand, if the logger is enabled for the DEBUG
+ level, you will incur the cost of evaluating whether the
+ logger is enabled or not, twice: once in <code>debugEnabled</code>
+ and once in <code>debug</code>.
+ This is an insignificant overhead because evaluating a
+ logger takes less than 1% of the time it takes to actually
+ log a request.
+ </p>
+
+
+
+ <h4>Better alternative</h4>
+
+ <p>
+ There exists a convenient alternative based on message
+ formats. Assuming <code>entry</code> is an object, you can write:
+ </p>
+
+
+ <div class="source"><pre>Object entry = new SomeObject();
+logger.debug("The entry is {}.", entry);</pre></div>
+
+ <p>
+ After evaluting whether to log or not, and only if the decision
+ is positive, will the logger implementation format the message
+ and replace the '{}' pair with the string value of
+ <code>entry</code>. In other words, this form does not incur
+ the cost of parameter construction in case the log statement is
+ disabled.
+ </p>
+
+
+ <p>
+ The following two lines will yield the exact same output.
+ However, in case of a <em>disabled</em>
+ logging statement, the second variant will outperform the first variant by a
+ factor of at least 30.
+ </p>
+
+ <div class="source"><pre>logger.debug("The new entry is "+entry+".");
+logger.debug("The new entry is {}.", entry);</pre></div>
+
+
+ <p>
+ A two argument variant is also availalble. For example, you
+ can write:
+ </p>
+
+ <div class="source"><pre>logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);</pre></div>
+
+ <p>If three or more arguments need to be passed, an
+ <code>Object[]</code> variant is also availalble. For example, you
+ can write:
+ </p>
+
+
+ <div class="source"><pre>Object[] paramArray = {newVal, below, above};
+logger.debug("Value {} was inserted between {} and {}.", paramArray);</pre></div>
+
+ <h3>Configuration</h3>
+
+ <p>Inserting log requests into the application code requires a
+ fair amount of planning and effort. Observation shows that
+ approximately four percent of code is dedicated to
+ logging. Consequently, even moderately sized applications will
+ contain thousands of logging statements embedded within its
+ code. Given their number, it becomes imperative to manage these
+ log statements without the need to modify them manually.
+ </p>
+
+ <p>The logback environment is fully configurable programmatically.
+ However, it is far more flexible to configure logback using
+ configuration files. In logback, configuration files are written
+ in XML format.
+ </p>
+
+ <p>Existing log4j users can convert their
+ <em>log4j.properties</em> files to <em>logback.xml</em> using our <a
+ href="http://logback.qos.ch/translator/">PropertiesTranslator</a>
+ web-application.
+ </p>
+
+ <p>
+ Configuring logback from a XML file is an easy task. One just needs to
+ instanciate a <code>JoranConfigurator</code> and pass the configuration
+ file, as the following example demonstrate.
+ </p>
+
+ <em>Example 1.4: Logback configuration from file ((<a
+ href="xref/chapter2/MyAppWithConfigFile.html">logback-examples/src/main/java/chapter2/MyAppWithConfigFile.java</a>)</em>
+
+<div class="source"><pre>package chapter2;
+
+//Import SLF4J classes.
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class MyAppWithConfigFile {
+
+ public static void main(String[] args) {
+ Logger logger = LoggerFactory.getLogger(MyAppWithConfigFile.class);
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ JoranConfigurator configurator = new JoranConfigurator();
+ configurator.setContext(lc);
+ configurator.doConfigure(args[0]);
+
+ logger.info("Entering application.");
+ Bar bar = new Bar();
+ bar.doIt();
+ logger.info("Exiting application.");
+
+ StatusPrinter.print(lc.getStatusManager());
+ }
+}</pre></div>
+
+
+ <p>This class defines a logger instance variable.
+ It then instantiates a <code>Bar</code>
+ object. The <code>Bar</code> class is listed below:
+ </p>
+
+ <em>Example 1.3: Sample logging class (<a href="xref/chapter2/Bar.html">logback-examples/src/main/java/chapter2/Bar.java</a>)</em>
+<div class="source"><pre>package chapter2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class Bar {
+
+ Logger logger = LoggerFactory.getLogger(Bar.class);
+
+ public void doIt() {
+ logger.debug("doing my job");
+ }
+}</pre></div>
+
+ <p><em>MyAppWithConfigFile</em> configures logback by using the
+ <code>JoranConfigurator</code>. Joran is a XML interpreter, similar to the
+ commons-digester API, but offering several advantages over
+ commons-digester. Here, it parses the xml file and runs actions
+ depending on the tags it finds. To setup the <code>JoranConfigurator</code>
+ properly, we passed the <code>LoggerContext</code>. A
+ <code>LoggerContext</code> is the class that creates and manages
+ Loggers in logback. It is also the class that implements the
+ <code>org.slf4j.ILoggerFactory</code> interface.
+ </p>
+ <p>
+ All
+ other classes only need to retrieve an instance of
+ <code>org.slf4j.Logger</code> by calling
+ <code>LoggerFactory.getLogger()</code>, and then log away. For
+ example, the only dependence of the <code>Bar</code> class is on
+ <code>org.slf4j.Logger</code> and
+ <code>org.slf4j.LoggerFactory</code>. Except code that configures
+ logback (if such code exists) user code does not need to depend on
+ logback, but on SLF4J instead.
+ </p>
+
+ <p>Let us configure logback with the
+ next XML configuration file:</p>
+
+ <em>Example 1.5: Basic configuration with a xml file (logback-examples/src/main/java/chapter2/sample-config-1.xml)</em>
+<div class="source"><pre><?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration></pre></div>
+
+ <p>We first created an <code>Appender</code>, named <em>STDOUT</em>
+ that is of <code>ConsoleAppender</code> type. Its layout is managed
+ by a <code>PatternLayout</code>, that uses the value of the <em>pattern</em> parameter
+ to generate the logging statement. We then configured the root
+ logger, set its level to DEBUG, and linked the newly configured
+ <code>ConsoleAppender</code> to the root logger.</p>
+
+ <p>Note that we've set the root logger level explicitly. Since root
+ logger have a DEBUG level by default we could have omitted this.</p>
+
+ <p>To run this example, use this command:</p>
+
+<div class="source"><pre>java chapter2.MyAppWithConfigFile src/main/java/chapter2/sample-config-1.xml</pre></div>
+
+ <p>
+ Here is what you should see in the console:
+ </p>
+
+<div class="source"><pre>18:15:26.718 [main] INFO chapter2.MyAppWithConfigFile - Entering application.
+18:15:26.718 [main] DEBUG chapter2.Bar - doing my job
+18:15:26.718 [main] INFO chapter2.MyAppWithConfigFile - Exiting application.</pre></div>
+
+
+ <p>Logging to the console is a rather simple example. Let's now
+ configure logback so that it logs on the console, but also to a
+ custom file.</p>
+
+<em>Example 1.6: Configuring logback with multiple appenders (logback-examples/src/main/java/chapter2/sample-config-2.xml)</em>
+<div class="source"><pre><?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <appender name="FILE"
+ class="ch.qos.logback.core.FileAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ <File>sample-log.txt</File>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration></pre></div>
+
+ <p>Now, all the logging statements are directed to the console and
+ to a file named <em>sample-log.txt</em>. As you can see, the
+ configuration needed to add an Appender is rather small. The options
+ are declared as xml element, in either Appender configuration. They are
+ read and their value are assigned to the corresponding attribute in
+ the specified java class.
+ </p>
+
+ <p>Suppose that we do not want to see the DEBUG level statements in
+ the chapter2 package anymore. This is done by adding the following
+ bold xml snippet to the configuration file, right before the
+ <code><root></code> element.</p>
+
+<em>Example 1.7: Configuring a specific logger (logback-examples/src/main/java/chapter2/sample-config-3.xml)</em>
+<div class="source"><pre><?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <appender name="FILE"
+ class="ch.qos.logback.core.FileAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %class - %msg%n</pattern>
+ </layout>
+ <File>sample-log.txt</File>
+ </appender>
+<b>
+ <logger name="chapter2">
+ <level value="info" />
+ </logger>
+</b>
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
+</pre></div>
+
+ <p>Once done, the output is modified to show only statements of level INFO and higher:</p>
+
+<div class="source"><pre>0 [main] INFO chapter2.MyAppWithConfigFile - Entering application.
+0 [main] INFO chapter2.MyAppWithConfigFile - Exiting application.</pre></div>
+
+ <p>Note that to obtain these different logging behaviors we did not need to recompile code.
+ We could just as easily have logged to a UNIX Syslog daemon, redirected all chapter2 output
+ to a log visualizer, or forwarded logging events to a remote logback server,
+ which would log according to local server policy, for example by forwarding the log event
+ to a second logback server.</p>
+
+
+ <p>
+ Until now, we always had to specifically load the configuration file and pass it
+ to a logback component. However, this step is not necessary in most cases. When logback
+ is not configured by instanciating <code>JoranConfigurator</code> objects, it follows
+ a simple policy to configure itself.
+ </p>
+
+ <ul>
+ <p>Logback first tries to find a file called <em>logback.xml</em> within the classpath.</p>
+ <p>If no such file is found, it checks for another file called <em>logback-test.xml</em>.</p>
+ <p>In case none of these files are found, logback configures itself automatically using the
+ <a href="../xref/ch/qos/logback/classic/BasicConfigurator.html"><code>BasicConfigurator</code>
+ </a> class.</p>
+ </ul>
+
+ <p>
+ The first two checks allow for two environments to cooperate nicely. When the application
+ using logback is in development and test process, a special file can be used to setup
+ a logging environment that is developer-friendly. Once in production environment, the
+ presence of a <em>logback.xml</em> file overrides any <em>logback-test.xml</em>
+ configuration.
+ </p>
+
+ <p>
+ The last step is meant to provide very basic logging functionnality in case no configuration
+ file is provided. In that case, the logging requests are output to the console.
+ </p>
+
+ <p>
+ Letting logback load its configuration file is the most often used way of
+ configuring. It allows the user to only import SLF4J classes in her code.
+ </p>
+
+ <p>
+ The last step of logback's configuration policy permits the use of a minimal
+ logging configuration right out of the box. Remember the very first example of
+ this short introduction. The output was generated due to this feature.
+ </p>
+ </body>
+</document>
Modified: logback/trunk/logback-site/src/site/xdocTemplates/manual/index.xml
==============================================================================
--- logback/trunk/logback-site/src/site/xdocTemplates/manual/index.xml (original)
+++ logback/trunk/logback-site/src/site/xdocTemplates/manual/index.xml Mon Jan 22 16:58:04 2007
@@ -61,6 +61,12 @@
<ul>
<li><p>
+ <a href="introduction.html"><b>Chapter 1: Introduction to logback</b></a>
+ </p></li>
+ <li><p>
+ <a href="joran.html"><b>Chapter 2: Architecture</b></a>
+ </p></li>
+ <li><p>
<a href="joran.html"><b>Chapter 3: Logback configuration with Joran</b></a>
</p></li>
Added: logback/trunk/logback-site/src/site/xdocTemplates/manual/introduction.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/xdocTemplates/manual/introduction.xml Mon Jan 22 16:58:04 2007
@@ -0,0 +1,265 @@
+<document>
+ <!--
+
+ Warning: do not use any auto-format function on this file.
+ Since "source" divs use pre as white-space, it affects the
+ look of the code parts in this document.
+
+ -->
+
+
+ <body>
+ <h2>Introduction</h2>
+ <div class="author">
+ Authors: Ceki Gülcü, Sébastien Pennec
+ </div>
+
+
+ <table>
+ <tr>
+ <td valign="top" align="top">
+ <a rel="license"
+ href="http://creativecommons.org/licenses/by-nc-sa/2.5/">
+ <img alt="Creative Commons License"
+ style="border-width: 0"
+ src="http://creativecommons.org/images/public/somerights20.png" />
+ </a>
+ </td>
+ <td>
+ <p>Copyright © 2000-2006, QOS.ch</p>
+
+ <p>
+ <!--Creative Commons License-->
+ This work is licensed under a
+ <a rel="license"
+ href="http://creativecommons.org/licenses/by-nc-sa/2.5/">
+ Creative Commons
+ Attribution-NonCommercial-ShareAlike 2.5
+ License
+ </a>
+ .
+ <!--/Creative Commons License-->
+ </p>
+ </td>
+ </tr>
+ </table>
+
+
+ <h2>Introduction</h2>
+
+ <p>
+ Logback is intended as a successor to the popular log4j project.
+ It was designed by Ceki Gülcü, the log4j 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 <code>Status</code> 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.
+ </p>
+
+ <h2>First Baby Step</h2>
+
+ <div class="highlight">
+ <p>
+ In order to run the examples in this introduction, you need
+ to make sure that certain jar files are present on the
+ classpath.
+ Please refer to the <a href="setup.html">setup page</a>
+ for further details.
+ </p>
+ </div>
+
+ <h3>Requirements</h3>
+
+ <p>Logback-classic module requires the presence
+ <em>slf4j-api.jar</em>, <em>logback-core.jar</em> in addition to
+ <em>logback-classic.jar</em> on the classpath.
+ </p>
+
+
+ <p>Let us now begin experimenting with logback.</p>
+
+<em>Example 1.1: Basic template for logging (<a href="xref/chapter1/HelloWorld1.html">logback-examples/src/main/java/chapter1/HelloWorld1.java</a>)</em>
+<div class="source"><pre>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.");
+
+ }
+}</pre></div>
+
+ <p>
+ The <code>HelloWorld</code> class is defined in the
+ <code>chapter1</code> package. It starts by importing the <code>Logger</code>
+ and <code>LoggerFactory</code>
+ classes defined in the SLF4J API, more specifically within the <code>org.slf4j</code>
+ package.
+ </p>
+
+
+ <p>
+ On the first line of the main() method, the variable named <code>logger</code>
+ is assigned a <code>Logger</code>
+ instance retreived by invoking the static method <code>getLogger</code>
+ in the <code>LoggerFactory</code> class.
+ This logger is named "chapter1.HelloWorld1". The main method proceeds to call the
+ <code>debug</code> 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".
+ </p>
+
+ <p>
+ You will note that the above example does not reference any
+ logback classes. In most cases, as far as logging is
+ concerned, your classes will need to import only SLF4J
+ classes. In principle, you will have to import logback
+ classes only for configuring logback. Thus, the vast
+ majority of your classes will only be cognizant of SLF4J API
+ and oblivious to the existence of logback.
+ </p>
+
+
+ <p>You can launch the first
+ sample application, <em>chapter1.HelloWord1</em> with the command:
+ </p>
+ <div class="source"><pre>java chapter1.HelloWorld1</pre></div>
+
+ <p>
+ Launching the <code>HelloWorld1</code>
+ application will output a single line on the console. By virtue of
+ to logback's default configuration policy, when no default file
+ is found to configure logback explicitely, logback will add a
+ <code>ConsoleAppender</code> to the root logger.
+ </p>
+
+<div class="source"><pre>20:49:07.962 [main] DEBUG chapter1.HelloWorld1 - Hello world.</pre></div>
+
+ <p>
+ 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
+ <code>StatusManager</code>. For the time being, let us instruct logback to print its
+ internal state. This is accomplished by a static method in
+ the <code>LoggerStatusPrinter</code>
+ class.
+ </p>
+
+<em>Example 1.2: Printing Logger Status (<a href="xref/chapter1/HelloWorld2.html">logback-examples/src/main/java/chapter1/HelloWorld2.java</a>)</em>
+<div class="source"><pre>package chapter1;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+<b>import ch.qos.logback.classic.util.LoggerStatusPrinter;</b>
+
+public class HelloWorld2 {
+
+ public static void main(String[] args) {
+ Logger logger = LoggerFactory.getLogger("chapter1.HelloWorld2");
+ logger.debug("Hello world.");
+ <b>LoggerStatusPrinter.printStatusInDefaultContext();</b>
+ }
+}</pre></div>
+
+
+ <p>Running the <code>HelloWorld2</code> application will produce
+ the following output:</p>
+
+<div class="source"><pre>20:49:07.962 [main] DEBUG chapter1.HelloWorld2 - Hello world.
+|-INFO in ch.qos.logback.classic.BasicConfigurator at 1c1ea29 - Setting up default configuration.</pre></div>
+
+
+ <p>
+ Logback explains that it configured itself using its default
+ policy, which is a basic <code>ConsoleAppender</code>.
+ An <code>Appender</code> 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.
+ </p>
+
+ <p>
+ The previous examples are rather simple. However, actual logging
+ in a larger application would not be any different. The general
+ pattern logging statements will not change. Only the configuration
+ process will be different since you will certainly need a more
+ specific configuration than what logback provides by default.
+ As you will see later on in this document,
+ configuring logback can be done in different flexible and
+ powerfull ways. Note that, normally, you won't need to invoke
+ <code>LoggerStatusPrinter</code>
+ after your log statements.
+ </p>
+
+ <p>
+ Here is a list of the three required steps in order to enable
+ logging in your application.
+ </p>
+
+ <ol>
+
+ <li>Configure the logback environment. You can do so in several
+ more or less sophisticated ways. More on this later.</li>
+
+ <li>In every class where you wish to perform logging, retrieve a
+ <code>Logger</code> instance by invoking the
+ <code>org.slf4j.LoggerFactory</code> class'
+ <code>getLogger()</code> method, passing the current class name
+ or the class itself as parameter.</li>
+
+ <li>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.</li>
+ </ol>
+
+ <h2>Building logback</h2>
+
+<p>
+Like many java applications today, logback relies on <a href="http://maven.apache.org">
+Maven 2</a> as its build tool. Maven 2 is a free open source build tool that requires
+one or more build files names <em>pom.xml</em> which already ship with logback
+distributions.
+</p>
+
+<p>
+Building all logback components is mostly done by issuing the <em>mvn compile</em>
+line in a terminal or command window. Maven 2 will automatically download the required
+external libraries and use them. However, a library cannot be downloaded from
+the Maven 2 repository. Libraries such as <code>JMS</code>
+from sun require a separate download and to issue a command to install their
+jars into your local repository. The required command will be presented
+by Maven 2 in your console when trying to compile logback.
+</p>
+
+<p>
+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. In particular you may not call the modified version <em>logback</em>
+or claim that it is endorsed by the QOS.ch.
+</p>
+
+
+
+
+
+
+
+
+ </body>
+</document>
More information about the logback-dev
mailing list