[LOGBack-dev] svn commit: r438 - in logback/trunk/logback-site: . src/site src/site/xdocTemplates
noreply.seb at qos.ch
noreply.seb at qos.ch
Wed Aug 9 19:30:14 CEST 2006
Author: seb
Date: Wed Aug 9 19:30:13 2006
New Revision: 438
Added:
logback/trunk/logback-site/src/site/xdocTemplates/documentation.xml
logback/trunk/logback-site/src/site/xdocTemplates/license.xml
logback/trunk/logback-site/src/site/xdocTemplates/shortIntro.xml
Modified:
logback/trunk/logback-site/pom.xml
logback/trunk/logback-site/src/site/site.xml
logback/trunk/logback-site/src/site/xdocTemplates/download.xml
logback/trunk/logback-site/src/site/xdocTemplates/repos.xml
Log:
modified files so that the project can be used in a multi-module environment
Modified: logback/trunk/logback-site/pom.xml
==============================================================================
--- logback/trunk/logback-site/pom.xml (original)
+++ logback/trunk/logback-site/pom.xml Wed Aug 9 19:30:13 2006
@@ -2,14 +2,19 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback</artifactId>
+ <version>0.2-SNAPSHOT</version>
+ </parent>
<modelVersion>4.0.0</modelVersion>
<groupId>ch.qos.logback</groupId>
- <artifactId>lb-topLevel</artifactId>
+ <artifactId>site</artifactId>
<packaging>jar</packaging>
- <version>0.1</version>
- <name>Logback Home</name>
+ <version>${parent.version}</version>
+ <name>Logback Site</name>
<url>http://logback.qos.ch</url>
@@ -18,8 +23,7 @@
<url>http://www.qos.ch</url>
</organization>
<inceptionYear>2005</inceptionYear>
-
-
+
<build>
<resources>
<resource>
@@ -33,13 +37,6 @@
</resource>
</resources>
- <extensions>
- <extension>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-ssh</artifactId>
- <version>1.0-beta-1</version>
- </extension>
- </extensions>
</build>
<reporting>
@@ -51,9 +48,10 @@
<xdocDirectory>
${project.build.outputDirectory}/generated-site
</xdocDirectory>
+ <outputDirectory>${project.parent.basedir}/target/site</outputDirectory>
</configuration>
</plugin>
- <!-- plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>
maven-project-info-reports-plugin
@@ -61,19 +59,11 @@
<reportSets>
<reportSet>
<reports>
- <report>index</report>
</reports>
</reportSet>
</reportSets>
- </plugin -->
+ </plugin>
</plugins>
</reporting>
-
- <distributionManagement>
- <site>
- <id>pixie</id>
- <url>scp://pixie/var/www/logback.qos.ch/htdocs/</url>
- </site>
- </distributionManagement>
</project>
\ No newline at end of file
Modified: logback/trunk/logback-site/src/site/site.xml
==============================================================================
--- logback/trunk/logback-site/src/site/site.xml (original)
+++ logback/trunk/logback-site/src/site/site.xml Wed Aug 9 19:30:13 2006
@@ -15,19 +15,23 @@
</bannerLeft>
<body>
+ <!--
<links>
<item name="Core Module" href="http://logback.qos.ch/core/" />
<item name="Classic Module" href="http://logback.qos.ch/classic/"/>
<item name="Access Module" href="http://logback.qos.ch/access/"/>
</links>
+ -->
<menu name="${project.name}">
<item name="Introduction" href="index.html"/>
<item name="News" href="news.html" />
<item name="Download" href="download.html" />
+ <item name="Documentation" href="documentation.html" />
<item name="Mailing Lists" href="mailinglist.html" />
- <item name="Source Repositories" href="repos.html" />
+ <item name="Source Repository" href="repos.html" />
<item name="Bug Report" href="bugreport.html"/>
+ <item name="License" href="license.html" />
</menu>
</body>
</project>
\ No newline at end of file
Added: logback/trunk/logback-site/src/site/xdocTemplates/documentation.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/xdocTemplates/documentation.xml Wed Aug 9 19:30:13 2006
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="ceki at qos ddoott ch ">Ceki Gulcu</author>
+ <title>Logback project Docs</title>
+ </properties>
+
+ <body>
+
+ <div class="section">
+ <h2>Documentation</h2>
+ </div>
+
+ <p>Here are some documents about the logback project modules.</p>
+ <p>
+ This section is pretty light at the moment, but will grow
+ with the developping of $logback.
+ </p>
+
+ <ul>
+ <li>
+ <a href="apidocs/index.html">Logback Javadoc</a>
+ </li>
+ <li>
+ <a href="shortIntro.html">A short introduction to logback classic</a>
+ </li>
+ </ul>
+
+ </body>
+</document>
\ No newline at end of file
Modified: logback/trunk/logback-site/src/site/xdocTemplates/download.xml
==============================================================================
--- logback/trunk/logback-site/src/site/xdocTemplates/download.xml (original)
+++ logback/trunk/logback-site/src/site/xdocTemplates/download.xml Wed Aug 9 19:30:13 2006
@@ -3,30 +3,60 @@
<properties>
<author email="ceki at qos ddoott ch ">Ceki Gulcu</author>
- <title>${pom.name} download</title>
+ <title>Logback project download</title>
</properties>
<body>
- <h2>Download links</h2>
- <p>
- Logback Modules can be downloaded by visiting their specific
- download pages:
- </p>
+ <div class="section">
+ <h2>Download links</h2>
+ </div>
<p>
- <a href="core/download.html">Core Module download page</a>
- </p>
- <p>
- <a href="classic/download.html">
- Classic Module download page
- </a>
- </p>
- <p>
- <a href="access/download.html">
- Access Module download page
- </a>
+ Logback modules are available as downloads including full source code, class files
+ and documentation.
</p>
+ <ul>
+ <li>
+ <a href="dist/logback-core-${pom.version}.zip">
+ logback-core-${pom.version}.zip
+ </a>
+ </li>
+
+ <li>
+ <a href="dist/logback-core-${pom.version}.tar.gz">
+ logback-core-${pom.version}.tar.gz
+ </a>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <a href="dist/logback-classic-${pom.version}.zip">
+ logback-classic-${pom.version}.zip
+ </a>
+ </li>
+
+ <li>
+ <a href="dist/logback-classic-${pom.version}.tar.gz">
+ logback-classic-${pom.version}.tar.gz
+ </a>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <a href="dist/logback-access-${pom.version}.zip">
+ logback-access-${pom.version}.zip
+ </a>
+ </li>
+
+ <li>
+ <a href="dist/logback-access-${pom.version}.tar.gz">
+ logback-access-${pom.version}.tar.gz
+ </a>
+ </li>
+ </ul>
+
+
</body>
-</document>
+</document>
\ No newline at end of file
Added: logback/trunk/logback-site/src/site/xdocTemplates/license.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/xdocTemplates/license.xml Wed Aug 9 19:30:13 2006
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="ceki at qos ddoott ch ">Ceki Gulcu</author>
+ <title>Logback project License</title>
+ </properties>
+
+ <body>
+
+ <div class="section">
+ <h2>Logback License</h2>
+ </div>
+
+ <p>
+ Logback source code and binaries are distributed
+ under the
+ <a href="http://www.gnu.org/licenses/lgpl.html">
+ GNU Lesser General Public License
+ </a>
+ as published by the Free Software Foundation.
+ </p>
+
+ <div class="source">
+ <p>
+Logback: the reliable, generic, fast and flexible
+logging library for Java.<br/>
+
+Copyright (C) 2000-2006, QOS.ch <br/>
+
+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.
+ </p>
+ </div>
+
+
+ </body>
+</document>
\ No newline at end of file
Modified: logback/trunk/logback-site/src/site/xdocTemplates/repos.xml
==============================================================================
--- logback/trunk/logback-site/src/site/xdocTemplates/repos.xml (original)
+++ logback/trunk/logback-site/src/site/xdocTemplates/repos.xml Wed Aug 9 19:30:13 2006
@@ -2,30 +2,82 @@
<document>
<properties>
- Authors: Ceki Gülcü, Sébastien Pennec
- <title>logback source repositories</title>
+ <author email="ceki at qos ddoott ch ">Ceki Gulcu</author>
+ <title>Logback source repository</title>
</properties>
<body>
- <h2>Download links</h2>
+
+ <div class="section">
+ <h2>Source Repository</h2>
+ </div>
<p>
- Logback source repositories can be accessed by visiting their specific pages:
+ To enable logback developers to work together, we
+ keep the source code in revision control systems called
+ Subversion. Developers have write access to the Subversion
+ repository, enabling them to make changes to the source
+ code. Everyone has read access to the repositories, so you
+ may download the most up-to-date development version of the
+ software. Note that the latest version in the Subversion
+ repository many not work as expected, it may not even
+ compile properly. If you are looking for a stable release of
+ the source code, you should download an official
+ distribution instead of the latest version in the Subversion
+ repositories.
+
+ There are several ways to access the Subversion
+ repositories:
</p>
+ <div class="section">
+ <h2>Web Access</h2>
+ </div>
<p>
- <a href="core/repos.html">Core source repository</a>
+ If you just wish to browse around or download a few
+ individual files, the best tool is the web-based ViewCVS
+ interface for CVS repositories and ViewCVS interface for
+ Subversion or go straight to the public repositories at:
</p>
<p>
- <a href="classic/repos.html">
- Classic source repository
+ <a href="http://svn.qos.ch/viewcvs/logback/core/trunk">
+ Logback core SVN Repository
</a>
</p>
<p>
- <a href="access/repos.html">
- Access source repository
+ <a href="http://svn.qos.ch/viewcvs/logback/classic/trunk">
+ Logback classic SVN Repository
+ </a>
+ </p>
+ <p>
+ <a href="http://svn.qos.ch/viewcvs/logback/access/trunk">
+ Logback access SVN Repository
</a>
</p>
+ <div class="section">
+ <h2>Checking out a read-only copy</h2>
+ </div>
+ <p>
+ To access the Subversion repositories anonymously, you will
+ need a Subversion client.
+
+ To check out one of the logback project modules, issue one of the following commands:
+ </p>
+
+ <div class="source">svn co http://svn.qos.ch/repos/logback/core/trunk</div>
+
+ <div class="source">svn co http://svn.qos.ch/repos/logback/classic/trunk</div>
+
+ <div class="source">svn co http://svn.qos.ch/repos/logback/access/trunk</div>
+
+ <div class="section">
+ <p>
+ Note that anonymous access allows read-only access only.
+ For read-write access please contact the logback
+ <a href="../mailinglist.html">developer list</a>
+ .
+ </p>
+ </div>
</body>
-</document>
+</document>
\ No newline at end of file
Added: logback/trunk/logback-site/src/site/xdocTemplates/shortIntro.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/xdocTemplates/shortIntro.xml Wed Aug 9 19:30:13 2006
@@ -0,0 +1,1147 @@
+<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>Short 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-nd/2.5/">
+ <img alt="Creative Commons License" border="0"
+ valign="top" align="top"
+ src="http://creativecommons.org/images/public/somerights20.png" />
+ </a>
+ </td>
+ <td>
+ <p>Copyright © 2000-2006, QOS.ch</p>
+
+ <p>
+ This work is licensed under a
+ <a rel="license"
+ href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
+ Creative Commons Attribution-Noncommercial-No
+ Derivative Works 2.5 License
+ </a>
+ .
+ </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 founder of the
+ log4j project. It builds upon a decade long experience gained in
+ designing industrial-strength logging systems. The resulting
+ product is at faster and has a smaller footprint than all the
+ 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, to cite a few. For its own error
+ reporting, logback relies on
+ <code>Status</code>
+ objects which come in handy in contexts other than logging.
+ </p>
+
+ <p>
+ This document presents the more basic concepts in logback,
+ probably just enough to get you started.
+ </p>
+
+ <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 Core module lays the groundwork for the other two modules.
+ The Classic module extends Core. Classic can be assimilated to
+ an 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
+ Access module integrates with Servlet containers to provide
+ HTPP-access log functionality. The Access module will be covered
+ in a separate document.
+ </p>
+ <p>
+ In this document, we will use the word logback to refer to the
+ logback classic module.
+ </p>
+
+ <h2>First Baby Step</h2>
+
+ <p>
+ After you have added the jar files
+ <em>logback-core.jar</em>
+ and
+ <em>logback-classic.jar</em>
+ to your classpath, you can begin experimenting with logback.
+ </p>
+
+<div class="source"><em>Example 1.1: Basic template for logging (examples/chapter1/HelloWorld1.java)</em>
+package chapter1;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HelloWorld1 {
+
+ public static void main(String[] args) {
+
+ Logger logger = LoggerFactory.getLogger(HelloWorld1.class);
+ logger.debug("Hello world.");
+
+ }
+}</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 as defined in the SLF4J API, more specifically in the <code>org.slf4j</code>
+ package.
+ </p>
+
+
+ <p>
+ On line 10, 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 its
+ <code>debug</code> method with the argument "Hello world." We say that the main
+ method contains a logging statement of level debug containing 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>
+ <b>ceki: compile?</b>
+ You can compile and run this class with the command:
+ </p>
+
+ <div class="source">java chapter1.HelloWorld1</div>
+
+ <p>
+ Suprisingly enough, launching the <code>HelloWorld1</code>
+ application will not produce <em>any</em> output.
+ Logback does not posses a default configuration.
+ Without a valid configuration, logback will be as silent as a mummy.
+ </p>
+
+ <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 tell logback to print its
+ internal state. This is accomplished by a static method in
+ the <code>LoggerStatusPrinter</code>
+ class.
+ </p>
+
+<div class="source"><em>Example 1.2: Printing Logger Status (examples/chapter1/HelloWorld2.java)</em>
+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(HelloWorld2.class);
+ logger.debug("Hello world.");
+ <b>LoggerStatusPrinter.printStatusInDefaultContext();</b>
+ }
+}</div>
+
+
+ <p>Running the <code>HelloWorld2</code> application will produce
+ the following output:</p>
+
+<div class="source">ERROR in Logger[chapter1.HelloWorld2] - \
+No appenders present in context [default] for logger [chapter1.HelloWorld2].</div>
+
+
+ <!-- ========= CEKI: STOPPED HERE =================== -->
+
+ <p>
+ Logback is complaining that no appenders were configured for the
+ default context. An Appender is a class that can be seen as an
+ output destination. Appenders exist for many different
+ destinations including the console, files, and many more. Users
+ can also easily create their own Appenders for any specific
+ situation.
+ </p>
+
+ <p>
+ Configuring logback can be done a different ways. The
+ simplest but less flexible way is by calling the
+ <code>BasicConfigurator</code> class, like in the following code snippet.
+ </p>
+ <div class="source"><em>Example 1.3: Configuring before logging (examples/chapter1/HelloWorld3.java)</em>
+package chapter1;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+<b>import ch.qos.logback.BasicConfigurator;</b>
+import ch.qos.logback.classic.util.LoggerStatusPrinter;
+
+public class HelloWorld3 {
+
+ public static void main(String[] args) {
+ Logger logger = LoggerFactory.getLogger(HelloWorld3.class);
+ <b>BasicConfigurator.configureDefaultContext();</b>
+ logger.debug("Hello world.");
+ LoggerStatusPrinter.printStatusInDefaultContext();
+
+ }
+}</div>
+
+ <p>
+ Let's run the <code>HelloWorld3</code>
+ application again. Now, the <code>BasicConfigurator</code>
+ will create a simple <code>ConsoleAppender</code>.
+ The logging request will then be propagated to the
+ Appender and the console will output the following:
+ </p>
+<div class="source">0 [main] DEBUG chapter1.HelloWorld3 - Hello world.</div>
+
+ <p>
+ This example is very simple. However, actual logging in a larger
+ application is not much more complicated. The logging statement
+ will barely change. Only the configuration process will be
+ different, since you don't need (nor should) configure the
+ logging context in each and every class that will require
+ logging. As well, the LoggerStatusPrinter will certainly not be
+ used after all the logging statements.
+ </p>
+
+ <p>
+ These are the three steps that are required to allow full logging in any application.
+ </p>
+
+ <ol>
+ <li>Configure the logback environment. You can do it using several
+ sophisticated ways. The BasicConfigurator is the simplest but also least flexible.</li>
+ <li>In every class where you wish to perform logging, retrieve a Logger
+ instance by invoking the LoggerFactory and passing the current class as the parameter.</li>
+ <li>Use this logger instance by invoking its printing methods, namely
+ the debug(), info(), warn() and error() methods. This will produce logging on the
+ configured devices.</li>
+ </ol>
+
+ <div class="section">
+ <h2>Logger, Appenders and Layouts</h2>
+ </div>
+ <p>
+ Logback has three main components: Loggers,
+ Appenders and Layouts. 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>
+ Loggers are defined in the classic module. On the other
+ hand, Appenders and Layouts are defined in the core module
+ of logback.
+ </p>
+
+ <h3>Logger context</h3>
+
+ <p>
+ The first and foremost advantage of any logging API over
+ plain System.out.println 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.
+ </p>
+
+ <p>
+ In logback, Loggers are named entities. Their names are case-sensitive and they follow the
+ contextual naming rule:
+ </p>
+ <div class="definition">
+ <div class="deftitle">Named Context</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 context.
+ It is exceptional in a way that is always exists. Like every
+ logger, it can be retrieved by its name, like this:
+ </p>
+ <div class="source">Logger rootLogger = LoggerFactory.getLogger("root");</div>
+
+ <p>
+ All other loggers are retrieved with the class static
+ LoggerFactory.getLogger method. This method takes the name
+ of the desired logger as a parameter. Some of the basic
+ methods in the Logger interface are listed below.
+ </p>
+
+ <div class="source">package org.slf4j;
+public interface Logger {
+
+ // Printing methods:
+ public void debug(Object message);
+ public void info(Object message);
+ public void warn(Object message);
+ public void error(Object message);
+ public void fatal(Object message);
+}</div>
+
+ <p>
+ Loggers may be assigned levels. The set of possible levels,
+ that is DEBUG, INFO, WARN and ERROR are defined in the
+ <em>ch.qos.logback.classic.Level</em> class. The level class cannot
+ be sub-classed as a much better 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 inherited level for a given logger <em>L</em>,
+ is equal to the first non-null level in the logger context, starting at
+ <em>L</em> and proceeding upwards in the context 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.
+ </p>
+ <p>
+ Below are four examples with various assigned level values
+ and the resulting inherited levels according to the above
+ rule.
+ </p>
+
+ <table>
+ <tr>
+ <th>
+ Logger
+ <br />
+ name
+ </th>
+ <th>
+ Assigned
+ <br />
+ level
+ </th>
+
+ <th>
+ Inherited
+ <br />
+ level
+ </th>
+ </tr>
+ <tr>
+ <td>root</td>
+ <td>L<sub>root</sub></td>
+ <td>L<sub>root</sub></td>
+ </tr>
+ <tr>
+ <td>X</td>
+ <td>none</td>
+ <td>L<sub>root</sub></td>
+ </tr>
+
+ <tr>
+ <td>X.Y</td>
+ <td>none</td>
+ <td>L<sub>root</sub></td>
+ </tr>
+ <tr>
+ <td>X.Y.Z</td>
+ <td>none</td>
+ <td>L<sub>root</sub></td>
+ </tr>
+ </table>
+ <p>
+ In example 1 above, only the root logger is assigned a
+ level.
+ </p>
+ This level value, <code>L<sub>root</sub></code>, is inherited by the other loggers
+ <code>X</code>, <code>X.Y</code> and <code>X.Y.Z</code>
+ <table>
+ <tr>
+ <th>
+ Logger
+ <br />
+ name
+ </th>
+ <th>
+ Assigned
+ <br />
+ level
+ </th>
+
+ <th>
+ Inherited
+ <br />
+ level
+ </th>
+ </tr>
+ <tr align="left">
+ <td>root</td>
+ <td>L<sub>root</sub></td>
+ <td>L<sub>root</sub></td>
+ </tr>
+ <tr align="left">
+ <td>X</td>
+ <td>L<sub>x</sub></td>
+ <td>L<sub>x</sub></td>
+ </tr>
+
+ <tr align="left">
+ <td>X.Y</td>
+ <td>L<sub>xy</sub></td>
+ <td>L<sub>xy</sub></td>
+ </tr>
+ <tr align="left">
+ <td>X.Y.Z</td>
+ <td>L<sub>xyz</sub></td>
+ <td>L<sub>xyz</sub></td>
+ </tr>
+ </table>
+
+ <p>
+ In example 2, all loggers have an assigned level value.
+ There is no need for level inheritence.
+ </p>
+
+ <table>
+ <tr>
+ <th>
+ Logger
+ <br />
+ name
+ </th>
+ <th>
+ Assigned
+ <br />
+ level
+ </th>
+ <th>
+ Inherited
+ <br />
+ level
+ </th>
+ </tr>
+ <tr align="left">
+ <td>root</td>
+ <td>L<sub>root</sub></td>
+ <td>L<sub>root</sub></td>
+ </tr>
+
+ <tr align="left">
+ <td>X</td>
+ <td>L<sub>x</sub></td>
+ <td>L<sub>x</sub></td>
+ </tr>
+ <tr align="left">
+ <td>X.Y</td>
+ <td>none</td>
+ <td>L<sub>x</sub></td>
+ </tr>
+ <tr align="left">
+ <td>X.Y.Z</td>
+ <td>L<sub>xyz</sub></td>
+ <td>L<sub>xyz</sub></td>
+ </tr>
+ </table>
+ <p>
+ In example 3, the loggers <code>root</code>, <code>X</code>
+ and <code>X.Y.Z</code> are assigned the levels <code>L<sub>root</sub></code>,
+ <code>L<sub>x</sub></code> and <code>L<sub>xyz</sub></code>
+ respectively. The logger <code>X.Y</code>
+ inherits its level value from its parent <code>X</code>.
+ </p>
+ <table>
+
+ <tr>
+ <th>
+ Logger
+ <br />
+ name
+ </th>
+ <th>
+ Assigned
+ <br />
+ level
+ </th>
+ <th>
+ Inherited
+ <br />
+ level
+ </th>
+ </tr>
+ <tr align="left">
+ <td>root</td>
+ <td>L<sub>root</sub></td>
+ <td>L<sub>root</sub></td>
+ </tr>
+
+ <tr align="left">
+ <td>X</td>
+ <td>L<sub>x</sub></td>
+ <td>L<sub>x</sub></td>
+ </tr>
+ <tr align="left">
+ <td>X.Y</td>
+ <td>none</td>
+ <td>L<sub>x</sub></td>
+ </tr>
+ <tr align="left">
+ <td>X.Y.Z</td>
+ <td>none</td>
+ <td>L<sub>x</sub></td>
+ </tr>
+ </table>
+
+ <p>
+ In example 4, the loggers <code>root</code> and <code>X</code>
+ and are assigned the levels <code>L<sub>root</sub></code> and
+ <code>L<sub>x</sub></code> respectively. The loggers <code>X.Y</code> and
+ <code>X.Y.Z</code> inherits their level value from their nearest
+ parent <code>X</code> having 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 request 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 (either assigned or inherited,
+ whichever is appropriate) 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. For the standard levels, we have
+ <code>DEBUG < INFO < WARN < ERROR</code>.
+ </p>
+
+ <p>
+ In a more graphic way, here is how the selection rule works: in the following
+ table, the horizontal header shows the level of the logging request, while the
+ vertical header shows the level of the logger.
+ </p>
+
+ <table>
+ <tr>
+ <td></td>
+ <th>DEBUG</th>
+ <th>INFO</th>
+ <th>WARN</th>
+ <th>ERROR</th>
+ </tr>
+ <tr>
+ <th>DEBUG</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>
+ </tr>
+ <tr>
+ <th>INFO</th>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ </tr>
+ <tr>
+ <th>WARN</th>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="greenBold">YES</span></td>
+ <td><span class="greenBold">YES</span></td>
+ </tr>
+ <tr>
+ <th>ERROR</th>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="redBold">NO</span></td>
+ <td><span class="greenBold">YES</span></td>
+ </tr>
+ </table>
+
+ <p>Here is an example of this rule.</p>
+
+ <div class="source">// get a logger instance named "com.foo", with an <span class="blue">INFO</span>level.
+Logger logger = LoggerFactory.getLogger("com.foo");
+Logger barlogger = LoggerFactory.getLogger("com.foo.Bar");
+
+// This request is enabled, because <span class="green">WARN</span> >= <span class="blue">INFO</span>
+logger.<span class="green">warn</span>("Low fuel level.");
+
+// This request is disabled, because <span class="green">DEBUG</span> < <span class="blue">INFO</span>.
+logger.<span class="green">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">INFO</span> >= <span class="blue">INFO</span>.
+barlogger.<span class="green">info</span>("Located nearest gas station.");
+
+// This request is disabled, because<span class="green">DEBUG</span> < <span class="blue">INFO</span>.
+barlogger.<span class="green">debug</span>("Exiting gas station search");</div>
+
+ <p>
+ Calling the <code>getLogger</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">Logger x = LoggerFactory.getLogger("wombat");
+Logger y = LoggerFactory.getLogger("wombat");</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 statically 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. The developer is free to name the
+ loggers as desired.
+ </p>
+ <p>
+ Nevertheless, naming loggers after the class where they are
+ located seems to be the best 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, 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 addAppender 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 context. In other words, appenders
+ are inherited additively from the logger context. 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 and on the console.
+ It is possible to override this default behavior so that appender
+ accumulation is no longer additive by setting the additivity
+ flag 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>Added 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>
+ The root logger is anonymous but can be accessed
+ with the Logger.getRootLogger() method. There is no
+ default appender attached to root.
+ </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 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 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 in "x.y.z", "x" and root.</td>
+ </tr>
+ <tr>
+ <td>security</td>
+ <td>A-sec</td>
+ <td class="blue">false</td>
+ <td>A-sec</td>
+ <td>
+ No appender accumulation since the additivity flag
+ is set to
+ <code>false</code>.
+ </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 PatternLayout, 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
+ "%r [%t] %-5p %c - %m%n" will output something akin to:
+ </p>
+
+ <div class="source">176 [main] INFO org.foo.Bar - Located nearest gas station.</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 statement. The fourth field is the name of the logger
+ associated with the log request. The text after the '-' is
+ the message of the statement.
+ </p>
+
+ <h4>More sophitsicated ways of logging</h4>
+
+ <p>
+ If you are a SLF4J user (if not, you should be...), you'll
+ notice that the methods used to request logging do not only
+ take a String as a parameter. Some methods allow more
+ sophisticated parameter configurations.
+ </p>
+
+ <p>
+ For some Logger <code>logger</code>, writing,
+ </p>
+
+ <div class="source">logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));</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">if(logger.isDebugEnabled()) {
+ logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
+}</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 statement.
+ </p>
+
+ <h4>Better alternative based on format messages</h4>
+
+ <p>
+ There exists a very convenient alternative based on message
+ formats. Assuming <code>entry</code> is an object, you can write:
+ </p>
+
+
+ <div class="source">Object entry = new SomeObject(); logger.debug("The entry is {}.", entry);</div>
+
+ <p>
+ After evaluting whether to log or not, and only if the
+ decision is affirmative, will the logger implementation
+ format the message and replace the '{}' pair with the string
+ value of <code>entry</code>.
+ In other words, tis 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, the second form will outperform the first form by a
+ factor of at least 30, in case of a <em>disabled</em>
+ logging statement.
+ </p>
+
+ <div class="source">logger.debug("The new entry is "+entry+".");
+logger.debug("The new entry is {}.", entry);</div>
+
+
+ <p>
+ A two argument variant is also availalble. For example, you
+ can write:
+ </p>
+
+ <div class="source">logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);</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">logger.debug("Value {} was inserted between {} and {}.", new Object[] {newVal, below, above});</div>
+
+ <h3>Configuration</h3>
+
+ <p>
+ Inserting log requests into the application code requires
+ a fair amount of planning and effort. Observation shows that
+ approximately 4 percent of code is dedicated to logging. Consequently,
+ even moderately sized applications will have thousands of logging
+ statements embedded within their 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. Currently, configuration files must be written in
+ XML format.
+ </p>
+ <p>
+ Let us give a taste of how this is done with the help of an
+ imaginary application MyApp that uses logback.
+ </p>
+<div class="source"><em>Example 1.4: Basic configuration (examples/chapter1/MyApp.java)</em>
+package chapter1;
+
+// Import SLF4J classes.
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import ch.qos.logback.BasicConfigurator;
+
+public class MyApp {
+
+ public static void main(String[] args) {
+
+ // Set up a simple configuration that logs on the console.
+ BasicConfigurator.configureDefaultContext();
+
+ Logger logger = LoggerFactory.getLogger(MyApp.class);
+
+ logger.info("Entering application.");
+ Bar bar = new Bar();
+ bar.doIt();
+ logger.info("Exiting application.");
+ }
+}</div>
+ <p>
+ This class begins by defining a static logger instance variable
+ with the name MyApp. It then uses the Bar class, defined as shown below:
+ </p>
+<div class="source">class Bar {
+
+ Logger logger = LoggerFactory.getLogger(Bar.class);
+
+ public void doIt() {
+ logger.debug("doing my job");
+ }
+}</div>
+ <p>
+ The invocation of the BasicConfigurator create, as we have seen,
+ a simple yet sufficient logback setup. By default,
+ the root Logger is assigned to Level.DEBUG.
+ </p>
+ <p>The BasicConfigurator has to be called only once. Any other class that wishes to
+ issue log statements only has to import the <em>Logger class</em> and use it.</p>
+ <p>
+ The output of MyApp is:
+ </p>
+<div class="source">0 [main] INFO ch.qos.logback.classic.examples.MyApp - Entering application.
+0 [main] DEBUG ch.qos.logback.classic.examples.Bar - doing my job
+0 [main] INFO ch.qos.logback.classic.examples.MyApp - Exiting application.</div>
+
+ <p>Let's configure logback to do exactly the same output, this time
+ with an XML configuration file.</p>
+
+<div class="source"><?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <param name="pattern"
+ value="%-4relative [%thread] %-5level %class - %msg%n" />
+ </layout>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration></div>
+
+ <p>We first created an Appender, named <em>STDOUT</em> that is of ConsoleAppender tye. Its layout
+ is managed by a PatternLayout, that uses the value of the "pattern" parameter to generate
+ the logging statement. We then configured the root logger, set its level to DEBUG,
+ and linked the newly configured ConsoleAppender 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 examle, use this command:</p>
+
+<div class="source">java MyApp sample-config-1.xml</div>
+
+ <p>The console output will be exactly the same as before. However, this time, we didn't need
+ to import and call the BasicConfigurator class, as you can see in the following code section:
+ </p>
+<div class="source"><em>Example 1.5: Logback configuration from file (examples/chapter1/MyAppWithConfigFile.java)</em>
+package chapter1;
+
+//Import SLF4J classes.
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+<b>import ch.qos.logback.classic.joran.JoranConfigurator;</b>
+
+public class MyAppWithConfigFile {
+
+ public static void main(String[] args) throws Exception {
+ Logger logger = (Logger) LoggerFactory.getLogger(MyAppWithConfigFile.class);
+
+ JoranConfigurator configurator = new JoranConfigurator();
+ configurator.setContext(logger.getLoggerContext());
+ configurator.doConfigure(args[0]);
+
+ logger.info("Entering application.");
+ Bar bar = new Bar();
+ bar.doIt();
+ logger.info("Exiting application.");
+ }
+}</div>
+ <p>
+ We used the JoranConfigurator class to parse the configuration file we just created.
+ Joran is a XML interpreter, similar to the commons-digester API, but offering several
+ small advantages over commons-digester. Here, it parses the xml file and runs actions depending
+ on the tags it finds.
+ </p>
+
+ <p>Logging to the console is a rather simple example. Let's now configure logback
+ so that it logs to the console, but also to a custom file.</p>
+
+<div class="source"><?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <param name="pattern"
+ value="%-4relative [%thread] %-5level %class - %msg%n" />
+ </layout>
+ </appender>
+
+ <appender name="FILE"
+ class="ch.qos.logback.core.FileAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <param name="pattern"
+ value="%-4relative [%thread] %-5level %class - %msg%n" />
+ </layout>
+ <param name="File"
+ value="sample-log.txt" />
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration></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 very small. The param element, in either
+ Appender configuration, reads the <em>name</em> attribute and assigns its value 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 chapter1 package anymore.
+ This is done by adding a <em>logger</em> element, with a nested element specifying its level value.</p>
+
+ <p>This done, the output is modified to show only statements of level INFO and higher.</p>
+
+<div class="source">0 [main] INFO chapter1.MyAppWithConfigFile - Entering application.
+0 [main] INFO chapter1.MyAppWithConfigFile - Exiting application.</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 chapter1 output
+ to an NT Event logger, 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>
+
+ </body>
+</document>
More information about the logback-dev
mailing list