[LOGBack-dev] svn commit: r404 - in logback/classic/trunk: examples/src/chapter1 src/site/xdocTemplates
noreply.seb at qos.ch
noreply.seb at qos.ch
Mon Aug 7 19:34:27 CEST 2006
Author: seb
Date: Mon Aug 7 19:34:26 2006
New Revision: 404
Added:
logback/classic/trunk/examples/src/chapter1/MyAppWithConfigFile.java
logback/classic/trunk/examples/src/chapter1/sample-config-1.xml
logback/classic/trunk/examples/src/chapter1/sample-config-2.xml
logback/classic/trunk/examples/src/chapter1/sample-config-3.xml
Modified:
logback/classic/trunk/src/site/xdocTemplates/shortIntro.xml
Log:
added an example class using configuration files and updated documentation accordingly
Added: logback/classic/trunk/examples/src/chapter1/MyAppWithConfigFile.java
==============================================================================
--- (empty file)
+++ logback/classic/trunk/examples/src/chapter1/MyAppWithConfigFile.java Mon Aug 7 19:34:26 2006
@@ -0,0 +1,28 @@
+package chapter1;
+
+//Import SLF4J classes.
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class MyAppWithConfigFile {
+
+ // Define a static logger variable so that it references the
+ // Logger instance named "MyAppWithConfigFile".
+ static Logger logger = (Logger) LoggerFactory.getLogger(MyAppWithConfigFile.class);
+
+ public static void main(String[] args) {
+ 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.");
+
+ StatusPrinter.print(logger.getLoggerContext().getStatusManager());
+ }
+}
Added: logback/classic/trunk/examples/src/chapter1/sample-config-1.xml
==============================================================================
--- (empty file)
+++ logback/classic/trunk/examples/src/chapter1/sample-config-1.xml Mon Aug 7 19:34:26 2006
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<logback: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>
+</logback:configuration>
Added: logback/classic/trunk/examples/src/chapter1/sample-config-2.xml
==============================================================================
--- (empty file)
+++ logback/classic/trunk/examples/src/chapter1/sample-config-2.xml Mon Aug 7 19:34:26 2006
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<logback: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>
+</logback:configuration>
Added: logback/classic/trunk/examples/src/chapter1/sample-config-3.xml
==============================================================================
--- (empty file)
+++ logback/classic/trunk/examples/src/chapter1/sample-config-3.xml Mon Aug 7 19:34:26 2006
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<logback: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>
+
+ <logger name="chapter1">
+ <level value="info" />
+ </logger>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</logback:configuration>
Modified: logback/classic/trunk/src/site/xdocTemplates/shortIntro.xml
==============================================================================
--- logback/classic/trunk/src/site/xdocTemplates/shortIntro.xml (original)
+++ logback/classic/trunk/src/site/xdocTemplates/shortIntro.xml Mon Aug 7 19:34:26 2006
@@ -10,148 +10,163 @@
<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>
+ <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>
+ 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>
+ <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>
+ 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>
+ 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>
-
+
<h2>First Baby Step</h2>
- <p>After you have added the jar fiiles <em>logback-core.jar</em>
- and <em>logback-classic.jar</em> to your classpath, you can begin
- experimenting with logback.
- </p>
+ <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/HelloWorld1.java)</em>
+package chapter1;
-1 package chapter1;
-2
-3 import org.slf4j.Logger;
-4 import org.slf4j.LoggerFactory;
-5
-6 public class HelloWorld1 {
-7
-8 public static void main(String[] args) {
-9
-10 Logger logger = LoggerFactory.getLogger("example/BabyStep1");
-11 logger.debug("Hello world.");
-12
-13 }
-14 }
+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 "example/BabyStep1". 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>
+ 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>
+ <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>
+ <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>
-<div class="source">package chapter1;
+ <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/HelloWorld2.java)</em>
+package chapter1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -171,43 +186,42 @@
<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>
+<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 classic 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">
+ <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 classic 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/HelloWorld3.java)</em>
package ch.qos.logback.classic.examples;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import ch.qos.logback.BasicConfigurator;
+<b>import ch.qos.logback.BasicConfigurator;</b>
import ch.qos.logback.classic.util.LoggerStatusPrinter;
public class HelloWorld3 {
- final static Logger logger = LoggerFactory.getLogger(HelloWorld1.class);
+ final static Logger logger = LoggerFactory.getLogger(HelloWorld3.class);
public static void main(String[] args) {
- BasicConfigurator.configureDefaultContext();
+ <b>BasicConfigurator.configureDefaultContext();</b>
logger.debug("Hello world.");
LoggerStatusPrinter.printStatusInDefaultContext();
@@ -216,11 +230,11 @@
</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:
+ 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 ch.qos.logback.classic.examples.HelloWorld3 - Hello world.
@@ -246,7 +260,7 @@
<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() and error() methods. This will produce logging on the
+ the debug(), info(), warn() and error() methods. This will produce logging on the
configured devices.</li>
</ol>
@@ -293,17 +307,12 @@
</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.
+ 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.
@@ -349,13 +358,9 @@
<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
- hierarchy, starting at
- <em>L</em>
- and proceeding upwards in the hierarchy towards the root
- logger.
+ The inherited level for a given logger <em>L</em>,
+ is equal to the first non-null level in the logger hierarchy, starting at
+ <em>L</em> and proceeding upwards in the hierarchy towards the root logger.
</p>
</div>
<p>
@@ -413,14 +418,8 @@
In example 1 above, only the root logger is assigned a
level.
</p>
- This level value,
- <code>Proot</code>
- , is inherited by the other loggers
- <code>X</code>
- ,
- <code>X.Y</code>
- and
- <code>X.Y.Z</code>
+ This level value, <code>Proot</code>, is inherited by the other loggers
+ <code>X</code>, <code>X.Y</code> and <code>X.Y.Z</code>
<table class="exampleTable">
<tr>
<th>
@@ -509,23 +508,11 @@
</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>Proot</code>
- ,
- <code>Px</code>
- and
- <code>Pxyz</code>
- respectively. The logger
- <code>X.Y</code>
- inherits its level value from its parent
- <code>X</code>
- .
+ In example 3, the loggers <code>root</code>, <code>X</code>
+ and <code>X.Y.Z</code> are assigned the levels <code>Proot</code>,
+ <code>Px</code> and <code>Pxyz</code>
+ respectively. The logger <code>X.Y</code>
+ inherits its level value from its parent <code>X</code>.
</p>
<table class="exampleTable">
@@ -581,37 +568,30 @@
In a more graphic way, here is how you the logger hierarchy
works:
</p>
-
+
+ <img src="images/loggerlevel.jpg" alt="loggerLevelVsMessageLevel" />
<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>
+ 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>
+ 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
+ <em>disabled</em>. A logger without an assigned level will inherit one from
the hierarchy. 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>
+ 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>
- .
+ whichever is appropriate) level <em>q</em>, is enabled if
+ <em>p >= q</em>.
</p>
</div>
@@ -619,8 +599,7 @@
<p>
This rule is at the heart of logback classic. It assumes
that levels are ordered. For the standard levels, we have
- <code>DEBUG < INFO < WARN < ERROR</code>
- .
+ <code>DEBUG < INFO < WARN < ERROR</code>.
</p>
<p>Here is an example of this rule.</p>
@@ -645,8 +624,7 @@
</div>
<p>
- Calling the
- <code>getLogger</code>
+ Calling the <code>getLogger</code>
method with the same name will always return a reference to
the exact same logger object.
</p>
@@ -656,12 +634,8 @@
Logger y = LoggerFactory.getLogger("wombat");</div>
<p>
- <code>x</code>
- and
- <code>y</code>
- refer to
- <em>exactly</em>
- the same logger object.
+ <code>x</code> and <code>y</code> refer to
+ <em>exactly</em> the same logger object.
</p>
<p>
@@ -682,8 +656,8 @@
</p>
<p>
Logback makes it easy to name loggers by
- <em>software component</em>
- . This can be accomplished by statically instantiating a
+ <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
@@ -721,14 +695,9 @@
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
+ 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>
@@ -742,28 +711,19 @@
<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>
+ 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>
- .
+ 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>
@@ -822,8 +782,7 @@
<td>
No appender accumulation since the additivity flag
is set to
- <code>false</code>
- .
+ <code>false</code>.
</td>
</tr>
<tr>
@@ -834,8 +793,7 @@
<td>
Only appenders of "security" because the additivity
flag in "security" is set to
- <code>false</code>
- .
+ <code>false</code>.
</td>
</tr>
</table>
@@ -844,16 +802,14 @@
<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>
+ 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>
+ language <code>printf</code>
function.
</p>
@@ -883,19 +839,14 @@
</p>
<p>
- For some Logger
- <code>logger</code>
- , writing,
+ 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>
+ 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>
@@ -913,15 +864,12 @@
<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
+ 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 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>
@@ -930,9 +878,7 @@
<p>
There exists a very convenient alternative based on message
- formats. Assuming
- <code>entry</code>
- is an object, you can write:
+ formats. Assuming <code>entry</code> is an object, you can write:
</p>
@@ -942,9 +888,8 @@
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
+ 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>
@@ -953,8 +898,7 @@
<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>
+ factor of at least 30, in case of a <em>disabled</em>
logging statement.
</p>
@@ -970,8 +914,7 @@
<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>
+ If three or more arguments need to be passed, an <code>Object[]</code>
variant is also availalble. For example, you can write:
</p>
@@ -999,10 +942,10 @@
Let us give a taste of how this is done with the help of an
imaginary application MyApp that uses logback classic.
</p>
-<div class="source">
-package ch.qos.logback.classic.examples;
+<div class="source"><em>Example 1.4: Basic configuration (examples/MyApp.java)</em>
+package chapter1;
-// Import logback classes.
+// Import SLF4J classes.
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -1044,6 +987,8 @@
a simple yet sufficient logback classic 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>
@@ -1053,6 +998,118 @@
0 [main] INFO ch.qos.logback.classic.examples.MyApp - Exiting application.
</div>
+ <p>Let's configure logback classic to do exactly the same output, this time
+ with an XML configuration file.</p>
+
+<div class="source">
+<?xml version="1.0" encoding="UTF-8" ?>
+<logback:configuration xmlns:logback='http://logback.qos.ch/'>
+
+ <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>
+</logback: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">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 {
+
+ // Define a static logger variable so that it references the
+ // Logger instance named "MyAppWithConfigFile".
+ static Logger logger = (Logger) LoggerFactory.getLogger(MyAppWithConfigFile.class);
+
+ public static void main(String[] args) throws Exception {
+ 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 classic
+ so that it logs to the console, but also to a custom file.</p>
+
+<div class="source"><?xml version="1.0" encoding="UTF-8" ?>
+
+<logback:configuration xmlns:logback='http://logback.qos.ch/'>
+
+ <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>
+</logback: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>
+
</body>
</document>
More information about the logback-dev
mailing list