logback-dev
Threads by month
- ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2008
- 7 participants
- 94 discussions

[JIRA] Resolved: (LBCORE-48) compression should happen in a separate thread
by Ceki Gulcu (JIRA) 25 Aug '08
by Ceki Gulcu (JIRA) 25 Aug '08
25 Aug '08
[ http://jira.qos.ch/browse/LBCORE-48?page=com.atlassian.jira.plugin.system.i… ]
Ceki Gulcu resolved LBCORE-48.
------------------------------
Fix Version/s: 0.9.10
Resolution: Fixed
Compression is done in a separate thread.
Fixed in revision 1677. See http://svn.qos.ch/viewvc?view=rev&revision=1677 for full details.
> compression should happen in a separate thread
> ----------------------------------------------
>
> Key: LBCORE-48
> URL: http://jira.qos.ch/browse/LBCORE-48
> Project: logback-core
> Issue Type: Improvement
> Components: Rolling
> Affects Versions: unspecified
> Environment: Operating System: All
> Platform: Other
> Reporter: Ceki Gulcu
> Assignee: Logback dev list
> Priority: Minor
> Fix For: 0.9.10
>
>
> During rollover, compression can bring all logging to a halt.
> This bug is related to LBCLASSIC-20.
> http://bugzilla.qos.ch/show_bug.cgi?id=55
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0
[ http://jira.qos.ch/browse/LBCLASSIC-20?page=com.atlassian.jira.plugin.syste… ]
Ceki Gulcu resolved LBCLASSIC-20.
---------------------------------
Fix Version/s: 0.9.10
Resolution: Duplicate
I am closing this issue as the requirement is not actually AsyncAppender but a way to do compression asynchronously, which very different.
I invite those really interested in AsyncAppender to create a separate issue.
> Implement AsyncAppender
> -----------------------
>
> Key: LBCLASSIC-20
> URL: http://jira.qos.ch/browse/LBCLASSIC-20
> Project: logback-classic
> Issue Type: Improvement
> Components: Other
> Affects Versions: unspecified
> Environment: Operating System: Windows
> Platform: PC
> Reporter: Anders Wallgren
> Assignee: Logback dev list
> Priority: Minor
> Fix For: 0.9.10
>
>
> Being able to write log files in the background is a requirement for production deployments of anything we would write on top of logback.
> Bonus points for including a feature to periodically flush the output.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[JIRA] Commented: (LBCORE-48) compression should happen in a separate thread
by Jonathan Komorek (JIRA) 25 Aug '08
by Jonathan Komorek (JIRA) 25 Aug '08
25 Aug '08
[ http://jira.qos.ch/browse/LBCORE-48?page=com.atlassian.jira.plugin.system.i… ]
Jonathan Komorek commented on LBCORE-48:
----------------------------------------
Is there a work around for this issue? This is freezing our production environment for about 10 minutes every night while the log files is being compressed.
> compression should happen in a separate thread
> ----------------------------------------------
>
> Key: LBCORE-48
> URL: http://jira.qos.ch/browse/LBCORE-48
> Project: logback-core
> Issue Type: Improvement
> Components: Rolling
> Affects Versions: unspecified
> Environment: Operating System: All
> Platform: Other
> Reporter: Ceki Gulcu
> Assignee: Logback dev list
> Priority: Minor
>
> During rollover, compression can bring all logging to a halt.
> This bug is related to LBCLASSIC-20.
> http://bugzilla.qos.ch/show_bug.cgi?id=55
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0
Clarify manual/joran wording
----------------------------
Key: LBSITE-16
URL: http://jira.qos.ch/browse/LBSITE-16
Project: logback-site
Issue Type: Bug
Reporter: Ceki Gulcu
Assignee: Logback dev list
Reported by Anton Tagunov in bugzilla.slf4j.org instead of here.
See http://bugzilla.slf4j.org/show_bug.cgi?id=87
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
1

svn commit: r1777 - in logback/trunk: logback-examples/src/main/java/chapter4 logback-site/src/site/pages logback-site/src/site/pages/manual
by noreply.ceki@qos.ch 25 Aug '08
by noreply.ceki@qos.ch 25 Aug '08
25 Aug '08
Author: ceki
Date: Mon Aug 25 21:54:06 2008
New Revision: 1777
Modified:
logback/trunk/logback-examples/src/main/java/chapter4/ExitWoes1.java
logback/trunk/logback-site/src/site/pages/jmxConfig.html
logback/trunk/logback-site/src/site/pages/manual/appenders.html
logback/trunk/logback-site/src/site/pages/manual/contextSelector.html
logback/trunk/logback-site/src/site/pages/manual/filters.html
logback/trunk/logback-site/src/site/pages/manual/joran.html
logback/trunk/logback-site/src/site/pages/manual/layouts.html
logback/trunk/logback-site/src/site/pages/manual/mdc.html
Log:
Related to LBSITE-16
Documentation improvements many of which have been proposed by Anton Tagunov.
Modified: logback/trunk/logback-examples/src/main/java/chapter4/ExitWoes1.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter4/ExitWoes1.java (original)
+++ logback/trunk/logback-examples/src/main/java/chapter4/ExitWoes1.java Mon Aug 25 21:54:06 2008
@@ -1,7 +1,7 @@
/**
- * Logback: the reliable, generic, fast and flexible logging framework.
+ * Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 1999-2006, QOS.ch
+ * Copyright (C) 2000-2008, 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
@@ -25,7 +25,7 @@
public static void main(String[] args) throws Exception {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
- lc.shutdownAndReset();//this is to cancel default-config.
+ lc.shutdownAndReset(); // we want to override the default-config.
WriterAppender<LoggingEvent> writerAppender = new WriterAppender<LoggingEvent>();
writerAppender.setContext(lc);
writerAppender.setLayout(new EchoLayout<LoggingEvent>());
Modified: logback/trunk/logback-site/src/site/pages/jmxConfig.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/jmxConfig.html (original)
+++ logback/trunk/logback-site/src/site/pages/jmxConfig.html Mon Aug 25 21:54:06 2008
@@ -23,45 +23,45 @@
<h2>JMX Configurator</h2>
- <p>
- As of version 0.8, logback ships with a component that allows
- configuration via JMX. Basically, it lets you reload the current
- configuration, load a new one, list loggers and modify logger levels.
+ <p>As of version 0.8, logback ships with a component that allows
+ configuration via JMX. Basically, it lets you reload the current
+ configuration, load a new one, list loggers and modify logger
+ levels.
</p>
<h3>Configuring your server</h3>
- <p>
- The first step is to make sure that your application server will
- allow the JMX Configurator to publish itself. In this document,
- we'll cover the necessary steps in Tomcat and Jetty.
+
+ <p>The first step is to make sure that your application server
+ will allow the JMX Configurator to publish itself. In this
+ document, we'll cover the necessary steps in Tomcat and Jetty.
</p>
<h4>Configuring Tomcat</h4>
- <p>
- Accessing JMX components with Tomcat requires to add the following lines
- to the <em>$TOMCAT_HOME/bin/catalina.sh</em> configuration file:
+
+ <p>Accessing JMX components with Tomcat requires to add the
+ following lines to the <em>$TOMCAT_HOME/bin/catalina.sh</em>
+ configuration file:
</p>
<div class="source"><pre>CATALINA_OPTS="-Dcom.sun.management.jmxremote"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"</pre></div>
- <p>
- Once started with these options, Tomcat's JMX compoenents can be accessed
- with JConsole by issuing the following command in a shell:
+ <p>Once started with these options, Tomcat's JMX compoenents can
+ be accessed with JConsole by issuing the following command in a
+ shell:
</p>
<div class="source"><pre>jconsole &</pre></div>
- <p>
- You might prefer to access your components via a web-based solution using MX4J.
- In that case, here are the required steps:
+ <p>You might prefer to access your components via a web-based
+ solution using MX4J. In that case, here are the required steps:
</p>
- <p>
- First, <a href="http://mx4j.sourceforge.net/">download MX4J</a>.
- Place the <em>mx4j-impl.jar</em> file in
- the <em>$TOMCAT_HOME/bin/</em> directory, and the <em>mx4j-tools.jar</em>
- in the <em>$TOMCAT_HOME/common/lib/</em> directory.
+ <p>First, <a href="http://mx4j.sourceforge.net/">download
+ MX4J</a>. Place the <em>mx4j-impl.jar</em> file in the
+ <em>$TOMCAT_HOME/bin/</em> directory, and the
+ <em>mx4j-tools.jar</em> in the <em>$TOMCAT_HOME/common/lib/</em>
+ directory.
</p>
<p>Then, add the following lines to the
@@ -87,19 +87,17 @@
mx.httpPort="8082"
protocol="AJP/1.3" /></pre></div>
- <p>
- Once Tomcat is started, you should be ableo to reach the JMX components by
- pointing a browser to the following URL:
+ <p>Once Tomcat is started, you should be able to reach the JMX
+ components by pointing a browser to the following URL:
</p>
<div class="source"><pre>http://host_name:8082/</pre></div>
<h4>Configuring Jetty</h4>
- <p>
- Configuring Jetty to publish JMX components requires a few modifications to the
- <em>$JETTY_HOME/etc/jetty.xml</em> configuration file. Here are the elements that need to be
- added:
+ <p>Configuring Jetty to publish JMX components requires a few
+ modifications to the <em>$JETTY_HOME/etc/jetty.xml</em>
+ configuration file. Here are the elements that need to be added:
</p>
<div class="source"><pre><Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer"/>
@@ -116,18 +114,17 @@
</Call>
</Get></pre></div>
- <p>
- Once Jetty is started with this configuration, all available components can be reviewed
- at this address:
+ <p>Once Jetty is started with this configuration, all available
+ components can be reviewed at this address:
</p>
<div class="source"><pre>http://host_name:8082/</pre></div>
<h3>Using the JMX Configurator</h3>
- <p>
- The next step is to declare the JMX Configurator in the logback configuration
- file. This is done by adding a single element, as shown below:
+ <p>The next step is to declare the JMX Configurator in the logback
+ configuration file. This is done by adding a single element, as
+ shown below:
</p>
<div class="source"><pre><configuration>
@@ -146,58 +143,49 @@
</root>
</configuration></pre></div>
- <p>
- Once the JMX Configurator is displayed on your screen, there are
- several operations available.
+ <p>Once the JMX Configurator is displayed on your screen, there
+ are several operations available.
</p>
<ul>
- <p>Display the logback Statuses
- </p>
- <p>Reload the configuration using the same file that was previously
- used.
- </p>
- <p>Reload the configuration using a file whose path is passed as
- a parameter.</p>
- <p>
- Reload the configuration using a file whose URL is passed as a
- parameter.
- </p>
- <p>
- Get the level of a logger
- </p>
- <p>
- Change the level setting of a specified logger.
- </p>
- <p>
- Change a list of all declared loggers.
- </p>
- <p>
- Change the level setting of a specified logger.
- </p>
+ <li>Display the logback Status </li>
+
+ <li>Reload the configuration using the same file that was previously
+ used. </li>
+
+ <li>Reload the configuration using a file whose path is passed
+ as a parameter.</li>
+
+ <li>Reload the configuration using a file whose URL is passed as
+ a parameter.</li>
+
+ <li>Get the level of a logger</li>
+ <li>Change the level setting of a specified logger.</li>
+ <li>Change a list of all declared loggers.</li>
+ <li>Change the level setting of a specified logger.</li>
</ul>
- <p>
- In the last case, you must specify the name of the logger you wish to
- alter, and its new level.
+ <p>In the last case, you must specify the name of the logger you
+ wish to alter, and its new level.
</p>
- <p>
- The level of a logger is a value that can be null, if no specific level
- has been configured for said logger. Its effective level, on the other
- hand, is given with respect to the parent loggers' levels. This value cannot
- be null, since all loggers are direct or indirect children of the root
- logger, whose level is always set. When trying to get the level or effective
- level of a logger, the name of the logger has to be passed as a parameter.
- Note that trying to get the level or effective level for a nonexistent logger
- will not return any result.
+
+ <p>The level of a logger is a value that can be null, if no
+ specific level has been configured for said logger. Its effective
+ level, on the other hand, is given with respect to the parent
+ loggers' levels. This value cannot be null, since all loggers are
+ direct or indirect children of the root logger, whose level is
+ always set. When trying to get the level or effective level of a
+ logger, the name of the logger has to be passed as a parameter.
+ Note that trying to get the level or effective level for a
+ nonexistent logger will not return any result.
</p>
- <p>
- Displaying logback Statuses via JMX can help users check the internal state
- of logback. It shows if anything has gone wrong, if rollovers occured
- as expected, and many other useful informations. It is also very useful
- when reloading a configuration, since the user can immediately see if
- the configuration file was successfully processed.
+ <p>Displaying logback status via JMX can help users check the
+ internal state of logback. It shows if anything has gone wrong, if
+ rollovers occured as expected, as well as other useful
+ information. It is also very useful when reloading a
+ configuration, since the user can immediately see if the
+ configuration file has been procsseds successfully.
</p>
Modified: logback/trunk/logback-site/src/site/pages/manual/appenders.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/appenders.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/appenders.html Mon Aug 25 21:54:06 2008
@@ -298,9 +298,10 @@
import java.io.OutputStream;
import java.io.OutputStreamWriter;
-import org.slf4j.Logger;
+
import org.slf4j.LoggerFactory;
+import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.WriterAppender;
import ch.qos.logback.core.layout.EchoLayout;
@@ -309,16 +310,19 @@
public static void main(String[] args) throws Exception {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+ lc.shutdownAndReset(); // we want to override the default-config.
WriterAppender<LoggingEvent> writerAppender = new WriterAppender<LoggingEvent>();
writerAppender.setContext(lc);
- writerAppender.setLayout(new EchoLayout<LoggingEvent>());
+ writerAppender.setLayout(new EchoLayout<<LoggingEvent>());
OutputStream os = new FileOutputStream("exitWoes1.log");
writerAppender.setWriter(new OutputStreamWriter(os));
writerAppender.setImmediateFlush(false);
writerAppender.start();
+ Logger root = lc.getLogger(LoggerContext.ROOT_NAME);
+ root.addAppender(writerAppender);
- Logger logger = LoggerFactory.getLogger(ExitWoes1.class);
+ Logger logger = lc.getLogger(ExitWoes1.class);
logger.debug("Hello world.");
}
@@ -681,11 +685,10 @@
</p>
<p>The <span class="option">FileNamePattern</span> option represents
- the file name pattern for the archived (rolled over) log files. The
- <span class="option">FileNamePattern</span> option, which is also
- required, must include an integer token, that is the string
+ the file name pattern for the archived (rolled over) log files.
+ This option is required and must include an integer token
<em>%i</em> somewhere within the pattern.
- </p>
+ </p>
<p>Here are the available options for
<code>FixedWindowRollingPolicy</code>
@@ -865,14 +868,13 @@
</p>
<p><span class="option">FileNamePattern</span> option defines the
- name of the rolled (archived) log files. Its value <span
- class="option">FileNamePattern</span> should consist of the name of
- the file, plus a suitably placed <em>%d</em> conversion specifier.
- The <em>%d</em> conversion specifier may contain a date-and-time
- pattern as specified by the <code>java.text.SimpleDateFormat</code>
- class. If the date-and-time pattern is omitted, then the default
- pattern <em>yyyy-MM-dd</em> is assumed. The following examples
- should clarify the point.
+ name of the rolled (archived) log files. Its value should consist of
+ the name of the file, plus a suitably placed <em>%d</em> conversion
+ specifier. The <em>%d</em> conversion specifier may contain a
+ date-and-time pattern as specified by the
+ <code>java.text.SimpleDateFormat</code> class. If the date-and-time
+ pattern is omitted, then the default pattern <em>yyyy-MM-dd</em> is
+ assumed. The following examples should clarify the point.
</p>
<table class="bodyTable">
Modified: logback/trunk/logback-site/src/site/pages/manual/contextSelector.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/contextSelector.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/contextSelector.html Mon Aug 25 21:54:06 2008
@@ -207,7 +207,7 @@
<div class="source"><pre><listener>
<listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
-</listener</pre></div>
+</listener></pre></div>
<p>Using the <code>ContextJNDISelector</code> might slow down your
Modified: logback/trunk/logback-site/src/site/pages/manual/filters.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/filters.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/filters.html Mon Aug 25 21:54:06 2008
@@ -54,48 +54,55 @@
<h2>Logback Classic</h2>
<a name="Filter"></a>
- <p><code>Filter</code> objects all implement the
- <a href="../xref/ch/qos/logback/core/filter/Filter.html"><code>Filter</code></a>
- abstract class. The <code>decide(Object event)</code> method is passed a
- newly created <code>LoggingEvent</code> object.
+
+ <p><code>Filter</code> objects all extend the <a
+ href="../xref/ch/qos/logback/core/filter/Filter.html"><code>Filter</code></a>
+ abstract class. The <code>decide(Object event)</code> method is
+ passed a newly created <code>LoggingEvent</code> object.
</p>
<h3>Filter chains</h3>
- <p>
- This abstract class assumes that filters be organized in a linear chain.
- Its member field next points to the next filter in the chain, or
- <code>null</code> if there are no further filters in the chain.
- Figure 6.1 depicts a sample filter chain consisting of three filters.
+
+ <p>This abstract class assumes that filters are organized in a
+ linear chain. Its member field next points to the next filter in
+ the chain, or <code>null</code> if there are no further filters in
+ the chain. Figure 6.1 depicts a sample filter chain consisting of
+ three filters.
</p>
<img src="images/chapter6/filterChain.gif" alt="A sample filter chain"/>
- <p>
- Filters are based on ternary logic. The <code>decide(Object event)</code>
- method of each filter is called in sequence. This method returns one of the
- enumerations <code>FilterReply.DENY</code>, <code>FilterReply.NEUTRAL</code> or
- <code>FilterReply.ACCEPT</code>. If the returned value is <code>FilterReply.DENY</code>,
- then the log event is dropped immediately without consulting the
- remaining filters. If the value returned is <code>FilterReply.NEUTRAL</code>,
- then the next filter in the chain is consulted. If there are no further filters
- to consult, then the logging event is processed normally.
- If the returned value is <code>FilterReply.ACCEPT</code>, then the logging
- event is processed immediately skipping the remaining filters.
+ <p>Filters are based on ternary logic. The <code>decide(Object
+ event)</code> method of each filter is called in sequence. This
+ method returns one of the <a
+ href="../xref/ch/qos/logback/core/spi/FilterReply.html"><code>FilterReply</code></a>
+ enumeration values, i.e. one of <code>FilterReply.DENY</code>,
+ <code>FilterReply.NEUTRAL</code> or
+ <code>FilterReply.ACCEPT</code>. If the returned value is
+ <code>FilterReply.DENY</code>, then the log event is dropped
+ immediately without consulting the remaining filters. If the value
+ returned is <code>FilterReply.NEUTRAL</code>, then the next filter
+ in the chain is consulted. If there are no further filters to
+ consult, then the logging event is processed normally. If the
+ returned value is <code>FilterReply.ACCEPT</code>, then the
+ logging event is processed immediately skipping the remaining
+ filters.
</p>
- <p>
- In logback-classic, <code>Filter</code> objects can only be added to <code>Appender</code>
- instances. By adding filters to an appender you can filter events by various
- criteria, such as the contents of the log message, the contents of the MDC,
- the time of day or any other part of the logging event.
+ <p>In logback-classic <code>Filter</code> objects can only be
+ added to <code>Appender</code> instances. By adding filters to an
+ appender you can filter events by various criteria, such as the
+ contents of the log message, the contents of the MDC, the time of
+ day or any other part of the logging event.
</p>
<h3>Implementing your own Filter</h3>
- <p>
- Creating your own filter is not difficult. All you have to do is extend the <code>Filter</code>
- abstract class. The only method that you will have to implement is the <code>decide()</code>
- method, allowing you to contentrate only on the behaviour of your filter.
+ <p>Creating your own filter is not difficult. All you have to do
+ is extend the <code>Filter</code> abstract class. The only method
+ that you will have to implement is the <code>decide()</code>
+ method, allowing you to contentrate only on the behaviour of your
+ filter.
</p>
<p>
@@ -168,14 +175,14 @@
<h3>Logback Filters</h3>
- <p>
- As the moment, there are two filters that ship with logback.
- <a href="../xref/ch/qos/logback/classic/LevelFilter.html">
- <code>LevelFilter</code></a> provides event filtering based on a <code>Level</code> value.
- It the event's level is equal to the configured level, the filter accepts of denies
- the event, depending on its configuration. It allows you to choose the
- behaviour of logback for a precise given level. Here is a sample configuration that
- uses <code>LevelFilter</code>.
+ <p>At the moment, there are two filters that ship with logback. <a
+ href="../xref/ch/qos/logback/classic/LevelFilter.html">
+ <code>LevelFilter</code></a> provides event filtering based on a
+ <code>Level</code> value. It the event's level is equal to the
+ configured level, the filter accepts of denies the event,
+ depending on its configuration. It allows you to choose the
+ behaviour of logback for a precise given level. Here is a sample
+ configuration that uses <code>LevelFilter</code>.
</p>
<em>Example 6.3: Sample LevelFilter configuration (logback-examples/src/main/java/chapter6/LevelFilterConfig.xml)</em>
@@ -227,131 +234,89 @@
</root>
</configuration></pre></div>
- <h3>Evaluator Filters</h3>
-
- <p>
- A special category of filters ships with logback. The
- <a href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html">
- <code>EvaluatorFilter</code></a> objects use an
- <a href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html">
- <code>EventEvaluator</code></a>
- to decide wether to accept or deny the request. This allows unprecedented
- flexibility in the way that you can affect the logging event's filtering.
- </p>
-
- <p>
- Creating a customized filter that makes use of <code>EventEvaluator</code> objects
- works the same way as seen previously, except that one must extend the
- <code>EvaluatorFilter</code> class, instead of the <code>Filter</code>
- or <code>AbstractMatcherFilter</code> classes.
- </p>
-
- <a name="EventEvaluator"></a>
- <h3>Event Evaluators</h3>
-
- <p>
- Events evaluators allow the user to enter java expressions, using
- components of a logging event, and to check each logging event
- against the compiled expression.
- </p>
-
- <p>
- Let's see a sample configuration.
- </p>
-
-<em>Example 6.5: Basic event evaluator usage (logback-examples/src/main/java/chapter6/basicEventEvaluator.xml)</em>
-<div class="source"><pre><configuration>
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
- <b><filter class="ch.qos.logback.core.filter.EvaluatorFilter">
- <evaluator name="myEval">
- <expression>message.contains("billing")</expression>
- </evaluator>
- <OnMismatch>NEUTRAL</OnMismatch>
- <OnMatch>DENY</OnMatch>
- </filter></b>
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>
- %-4relative [%thread] %-5level %logger - %msg%n
- </pattern>
- </layout>
- </appender>
+ <h3>Evaluator Filters taking Java Expressions</h3>
- <root>
- <level value="INFO" />
- <appender-ref ref="STDOUT" />
- </root>
-</configuration></pre></div>
+
+ <p>A special category of filters is implemented by the <a
+ href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html">
+ <code>EvaluatorFilter</code></a> class. These filters use an <a
+ href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html">
+ <code>EventEvaluator</code></a> object to decide wether to accept
+ or deny a request. This allows unprecedented flexibility in the
+ way that you can affect filtering of logging events.
+ </p>
- <p>
- The bold part in the previous configuration adds an <code>EvaluatorFilter</code>
- to a <code>ConsoleAppender</code>. An <code>EventEvaluator</code> is then given to
- the filter. The <em>expression</em> element contains a recognizable java expression.
- Notice that the <em>message</em> variable is defined implicitly. Logback provides
- access to the internal components of a logging event and lets the user build her
- expression at will.
+ <p>As a user, you do not need to worry about the actual
+ plumbing. All you need to do is to give a name to the evaluator
+ and to specify an <em>evaluation expression</em>, that is a
+ boolean expression in regular Java syntax. These evaluation
+ expressions are compiled on-the-fly during the interpretation of
+ the configration file. It is the users reponsibility to ensure
+ that the expression is boolean, that it evaluates to true or
+ false. In evaluation expressions, logback implicitly exposes
+ various fields of a logging event as variables. The list of these
+ implicit variables is given below. The scope of evaluation
+ expressions is limited to the logging event.
</p>
- <p>
- The implicit variables available to the <code>EventEvaluator</code> are described below:
- </p>
- <table>
- <tr>
- <th>Name</th>
- <th>Type</th>
- <th>Description</th>
+ <table class="bodyTable">
+ <tr>
+ <th>Name</th>
+ <th>Type</th>
+ <th>Description</th>
</tr>
- <tr>
- <td>event
- </td>
+ <tr>
+ <td>event</td>
<td><code>LoggingEvent</code></td>
- <td>The logging event associated with the logging request.
- All of the following variables are also available from the event. For example,
- <code>event.getMessage()</code> returns the same String value as the <em>message</em>
- variable.
- </td>
+
+ <td>The raw logging event associated with the logging
+ request. All of the following variables are also available
+ from the event. For example, <code>event.getMessage()</code>
+ returns the same String value as the <em>message</em> variable
+ described next.
+ </td>
</tr>
- <tr>
- <td>message
- </td>
- <td><code>String</code></td>
- <td>The message created with the logging request.
- </td>
+
+ <tr class="alt">
+ <td>message</td>
+ <td><code>String</code></td>
+ <td>The message of the logging request.</td>
</tr>
<tr>
- <td>logger
- </td>
+ <td>logger</td>
<td><code>LoggerRemoteView</code></td>
- <td>This object can be treated like a usual logger. In case the logging event
- is serialized and sent to a remote machine, the usual logger object is
- dropped and replaced by a <code>LoggerRemoteView</code> object, which
- performs much better when serialized.
- </td>
+ <td>This object is a proxy for the logger object where the
+ logging request was issued. It can be viewed as a regular
+ logger object. However, it has some nice performance
+ properties, especially with respect to serialization.
+ </td>
</tr>
- <tr>
- <td>level
- </td>
+
+ <tr class="alt">
+ <td>level</td>
<td><code>int</code></td>
- <td>The int value corresponding to the level. To help create easily
- expressions involving levels, the default value <em>DEBUG</em>,
- <em>INFO</em>, <em>WARN</em> and <em>ERROR</em> are also available. Thus,
- using <em>level > INFO</em> is a correct expression.
+ <td>The int value corresponding to the level. To help create
+ easily expressions involving levels, the default value
+ <em>DEBUG</em>, <em>INFO</em>, <em>WARN</em> and
+ <em>ERROR</em> are also available. Thus, using <em>level >
+ INFO</em> is a correct expression.
</td>
</tr>
<tr>
<td>timeStamp
</td>
<td><code>long</code></td>
- <td>The timestamp corresponding to the logging event's creation.
+ <td>The timestamp corresponding to the logging event's
+ creation.
</td>
</tr>
- <tr>
- <td>marker
- </td>
+ <tr class="alt">
+ <td>marker</td>
<td><code>Marker</code></td>
- <td>The <code>Marker</code> object associated with the logging request.
+ <td>The <code>Marker</code> object associated with the logging
+ request.
</td>
</tr>
<tr>
@@ -363,43 +328,74 @@
following expression: <em>mdc.get("myKey")</em>.
</td>
</tr>
- <tr>
- <td>throwable
- </td>
+ <tr class="alt">
+ <td>throwable</td>
<td><code>Throwable</code></td>
- <td>The exception that was passed to the logger when it
- was requested.
+ <td>The exception associated with the logging event
</td>
</tr>
</table>
+
- <p>
- The behaviour of the filter is also defined by its <span class="option">OnMatch</span>
- and <span class="option">OnMismatch</span> options. The configuration specifies thanks
- to these elements the replies that the <code>EvaluatorFilter</code> must give once its
- expression has been evaluated. The example above returns the value <code>FilterReply.ACCEPT</code>
- when the message of the logging event contains the String <em>important</em>.
- If <em>important</em> is not contained in the message, then the filter lets the next filter
- evaluate this logging event.
- </p>
-
- <p>
- Let us see an example of <code>EvaluatorFilter</code>. The <code>FilterEvents</code>
- class issues ten logging requests, numbered from 0 to 9.
- </p>
-
- <p>
- First, let us run the <code>FilterEvents</code> class with a configuration that does
- not contain any filters. This can be done by issuing the following command:
+ <p>The behaviour of the <code>EvaluatorFilter</code> is also
+ affected by its <span class="option">OnMatch</span> and <span
+ class="option">OnMismatch</span> options taking values of type
+ <code>FilterReply</code>, i.e. DENY, ACCEPT, NEUTRAL.
+ </p>
+
+ <p>Here is a concrete example.</p>
+
+<em>Example 6.5: Basic event evaluator usage (logback-examples/src/main/java/chapter6/basicEventEvaluator.xml)</em>
+
+<div class="source"><pre><configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <b><filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator name="myEval">
+ <expression><span class="green">message.contains("billing")</span></expression>
+ </evaluator>
+ <OnMismatch>NEUTRAL</OnMismatch>
+ <OnMatch>DENY</OnMatch>
+ </filter></b>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>
+ %-4relative [%thread] %-5level %logger - %msg%n
+ </pattern>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="INFO" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration></pre></div>
+
+ <p>The bold part in the previous configuration adds an
+ <code>EvaluatorFilter</code> to a <code>ConsoleAppender</code>. An
+ <code>EventEvaluator</code> is then injected into the
+ <code>EvaluatorFilter</code>. The <em>expression</em> element
+ corresponds to the evaluation expression described previously. The
+ expression <code>message.contains("billing")</code> returns a
+ boolean value. Notice that the <em>message</em> variable is
+ defined implicitly.
+ </p>
+
+ <p>This evalutor filter will drop all logging events whose message
+ contains the string "billing".
+ </p>
+
+ <p>The <a
+ href="../xref/chapter6/FilterEvents.html"><code>FilterEvents</code></a>
+ class issues ten logging requests, numbered from 0 to 9. Let us
+ rist run <code>FilterEvents</code> class without any filters:
</p>
<div class="source"><pre>
java chapter6.FilterEvents src/main/java/chapter6/basicConfiguration.xml
</pre></div>
- <p>
- All requests will be displayed, as shown below:
- </p>
+ <p>All requests will be displayed, as shown below:</p>
<div class="source"><pre>0 [main] INFO chapter6.FilterEvents - logging statement 0
0 [main] INFO chapter6.FilterEvents - logging statement 1
@@ -412,27 +408,15 @@
0 [main] INFO chapter6.FilterEvents - logging statement 8
0 [main] INFO chapter6.FilterEvents - logging statement 9</pre></div>
- <p>
- Suppose that we want to get rid of the billing information. We
- can use an <code>EvaluatorFilter</code> configured as follows:
- </p>
-<div class="source"><pre><configuration>
- ...
- <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
- <evaluator name="myEval">
- <expression>message.contains("billing")</expression>
- </evaluator>
- <OnMismatch>NEUTRAL</OnMismatch>
- <OnMatch>DENY</OnMatch>
- </filter>
- ...
-</configuration></pre></div>
- <p>
- This filter will deny any logging event whose message
- contains the String <em>billing</em>. If we run the <code>FilterEvents</code>
- class again, we obtain the following output:
+ <p>Suppose that we want to get rid of the billing information.
+ The <em>basicEventEvaluator.xml</em> configuration file just
+ desribed, does exactly what we want.</p>
+
+ <p>Running with filters:</p>
+ <p class="source">java chapter6.FilterEvents src/main/java/chapter6/basicEventEvaluator.xml</p>
+ <p>we obtain:
</p>
<div class="source"><pre>0 [main] INFO chapter6.FilterEvents - logging statement 0
@@ -468,12 +452,12 @@
request is issued. Their scope is wider than appender-attached filters.
</p>
- <p>
- More importantly, they are called before the <code>LoggingEvent</code> object creation.
- Their decision is made based on some of the logging event's components. They require
- no logging event instanciation, nor any other treatement to provide their
- filtering functionnalities. They are much more performant than the usual
- <code>Filter</code> objects.
+ <p>More importantly, they are called before the
+ <code>LoggingEvent</code> object creation. Their decision is made
+ based on some of the logging event's components. They require no
+ logging event instantiation, nor any other treatement to provide
+ their filtering functionnalities. They are much more performant
+ than the usual <code>Filter</code> objects.
</p>
<h3>Implementing your own TurboFilter</h3>
@@ -663,33 +647,34 @@
</p>
- <h2>Logback Access</h2>
+ <h2>Logback-access</h2>
- <p>
- Logback access benefits from most of the possibilities available
- to the classic module. <code>Filter</code> objects are available and work
- in the same way as their classic counterpart. They handle access' implementation
- of logging events: <code>AccessEvent</code>.
- Thus, a customized filter
- for logback access is follows strictly the same rules than one for the
- classic module, except for the event implemenation recieved as a parameter.
- On the other hand,
- <code>TurboFilter</code> objects are not available to the access module.
+ <p>Logback-access offers most of the features available with
+ logback-classic. <code>Filter</code> objects are available and
+ work in the same way as their logback-classic counterparts. They
+ handle access' implementation of logging events:
+ <code>AccessEvent</code>. Thus, a customized filter for logback
+ access follows strictly the same rules as those for
+ logback-classic, except for the event type recieved as parameter.
+ On the other hand, <code>TurboFilter</code> objects are supported
+ by logback-access.
</p>
<h3>Filters</h3>
- <p>
- <code>EvaluatorFilter</code> objects, with their expressions, are available to
- the access module. However, the variables that one can use to build an expression
- are different. Only the <code>AccessEvent</code> object can be used, by inserting the
- <em>event</em> variable in the expression. Although less wide than its classic
- counterpart, the access evaluation filter is just as powerfull. All the
- request and response components are reachable from the <em>event</em> variable.
+ <p><code>EvaluatorFilter</code> objects with java expressions
+ supplied in in <code>evaluator</code> configuration elements are
+ supported by logback-access. However, list implicit variables
+ available for constructing an expression are different. Only the
+ <code>AccessEvent</code> object can be used by inserting the
+ <em>event</em> variable in the expression. Nevertheless the access
+ <code>evaluator</code> is just as powerfull. All the request and
+ response components are reachable from the <em>event</em>
+ variable.
</p>
- <p>
- Here is a sample configuration that will ensure that any 404 error will be displayed:
+ <p>Here is a sample configuration that will ensure that any 404
+ error will be logged:
</p>
<em>Example 6.9: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator.xml)</em>
@@ -714,10 +699,9 @@
<appender-ref ref="STDOUT" />
</configuration></pre></div>
- <p>
- We might imagine a slightly more complex use of filters to ensure the display of 404 errors, but
- to prevent polluting the output with endless accesses to CSS files. Here is what such a configuration
- would look like:
+ <p>We might imagine a slightly more complex use of filters to
+ ensure logging of 404 errors, except those returned on access to
+ CSS resources. Here is what such a configuration would look like:
</p>
<em>Example 6.10: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml)</em>
Modified: logback/trunk/logback-site/src/site/pages/manual/joran.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/joran.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/joran.html Mon Aug 25 21:54:06 2008
@@ -460,7 +460,8 @@
the root logger is already named, it does not admit a name attribute
either. The value of the level attribute can be set to one of the
case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or
- OFF. Note that the level of the root logger cannot be inherited.
+ OFF. Note that the level of the root logger cannot be set to
+ INHERITED or NULL.
</p>
@@ -992,16 +993,15 @@
<div class="source"><pre>USER_HOME=/home/sebastien</pre></div>
<p>Nested variabled subsitution is also supported. By nested, we
- mean that the value definition of a variable contains referenced to
- other variables. Here is an example. Suppose you wish to use
- variables to specify not only the destination directory but also
- the file name, and combine those variable in a third variable
- called "destination". The properties file shown below gives an
- example.
+ mean that the value definition of a variable contains references to
+ other variables. Suppose you wish to use variables to specify not
+ only the destination directory but also the file name, and combine
+ those two variables in a third variable called "destination". The
+ properties file shown below gives an example.
</p>
- <em>Example 3.<span class="autoEx"/>: Recursive use of variables
+ <em>Example 3.<span class="autoEx"/>: Nested variable references
(logback-examples/src/main/java/chapter3/variables2.properties)</em>
<div class="source"><pre>USER_HOME=/home/sebastien
Modified: logback/trunk/logback-site/src/site/pages/manual/layouts.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/layouts.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/layouts.html Mon Aug 25 21:54:06 2008
@@ -1414,12 +1414,16 @@
<a name="ClassicHTMLLayout"></a>
- <h3>HTMLLayout</h3>
-
- <p><a href="../xref/ch/qos/logback/classic/html/HTMLLayout.html">
- <code>HTMLLayout</code></a> outputs logging events in an HTML
- table where each row of the table corresponds to a logging
- event.</p>
+ <h2>Generating logs in HTML format</h2>
+
+ <p>Logback provides a special <a
+ href="../xref/ch/qos/logback/core/Layout.html"><code>Layout</code></a>,
+ namely <a
+ href="../xref/ch/qos/logback/classic/html/HTMLLayout.html">
+ <code>HTMLLayout</code></a>, to generate logs directly in HTML
+ format. <code>HTMLLayout</code> outputs logging events in an HTML
+ table where each row of the table corresponds to a logging
+ event.</p>
<p>Here is a sample output produced by <code>HTMLLayout</code>
using its default CSS stylesheet:</p>
@@ -1438,11 +1442,11 @@
<code>PatternLayout</code> with <code>HTMLLayout</code> is that
conversion specifiers should not be separated by space characters
or more generally by literal text. Each specifier found in the
- pattern willa result in a separate column, in particular for each
- literal text in the pattern, wasting valuable real estate on your
- screen.
- </p>
-
+ pattern will result in a separate column. Likewise a separate
+ column will be generated for each block of literal text found in
+ the pattern potentially wasting valuable real estate on your
+ screen.</p>
+
<p>Here is simple but functional configuration file illustrating
the use of <code>HTMLLayout</code>.
</p>
@@ -1488,18 +1492,19 @@
<h3>Stack traces</h3>
- <p> If you use the <em>%em</em> conversion word, to display stack
- traces, a table column will be created to display exception stack
- traces. In most cases the column will be empty, wasting screen
+ <p> If you use the <em>%em</em> conversion word to display stack
+ traces, a table column will be created to display stack traces. In
+ most cases the column will be empty, wasting screen
real-estate. Moreover, printing a stack trace on a separate column
- does yield very readable results. Fortunately, the <em>%ex</em>
- conversion word is not the only way to display stack traces.
+ does not yield very readable results. Fortunately, the
+ <em>%ex</em> conversion word is not the only way to display stack
+ traces.
</p>
<p>A better solution is available through implementations of
<code>IThrowableRenderer</code> interface. Such an implementation
- can assigned to <code>HTMLLayout</code> to manage the display data
- related to exceptions. By default, a
+ can be assigned to <code>HTMLLayout</code> to manage the display
+ data related to exceptions. By default, a
<a href="../xref/ch/qos/logback/classic/html/DefaultThrowableRenderer.html">
<code>DefaultThrowableRenderer</code></a> is assigned to each
<code>HTMLLayout</code> instance. It writes exceptions on a
@@ -1508,12 +1513,12 @@
</p>
<p>If for some reason, you still wish to use the <em>%ex</em>
- pattern, then you can specify
- <a href="../xref/ch/qos/logback/core/html/NOPThrowableRenderer.html">
- <code>NOPThrowableRenderer</code></a> in the configuration file
- in order to disable displaying a separate row for the stack
- trace. We don't have the faintest idea why you would want to do
- that, but if you did, you could.
+ pattern, then you can specify <a
+ href="../xref/ch/qos/logback/core/html/NOPThrowableRenderer.html">
+ <code>NOPThrowableRenderer</code></a> in the configuration file in
+ order to disable displaying a separate row for the stack trace. We
+ don't have the faintest idea why you would want to do that, but if
+ you wished, you could.
</p>
<h3>CSS</h3>
@@ -1522,8 +1527,8 @@
is controlled through a Cascading Style Sheet (CSS). In the
absence of specific instructions, <code>HTMLLayout</code> will
default to its internal CSS. However, your can instruct
- <code>HTMLLayout</code> you use an external CSS file. For this
- purpose, a <code>cssBuilder</code> element can be nested within a
+ <code>HTMLLayout</code> to use an external CSS file. For this
+ purpose a <code>cssBuilder</code> element can be nested within a
<code><layout></code> element, as shown below.
</p>
@@ -1600,268 +1605,249 @@
<a name="AccessPatternLayout"></a>
<h3>PatternLayout</h3>
- <p> <a href="../xref/ch/qos/logback/access/PatternLayout.html">
+
+ <p><a href="../xref/ch/qos/logback/access/PatternLayout.html">
<code>PatternLayout</code></a> in logback-access can be configured
- in the same way as it's classic counterpart, with the notable
- exception of the available conversion specifiers, as appropriate
- for HTTP servlet request and response.
- </p>
+ much in the same way as its classic counterpart. However it
+ features additional conversion specifiers suited for logging
+ particular bits of information availalbe only in HTTP servlet
+ requests and HTTP servlet responses.
+ </p>
<p>Below is a list of conversion specifiers for
<code>PatternLayout</code> in logback-access.</p>
<table class="bodyTable" border="0" CELLPADDING="8">
- <th align="center">Conversion Word</th>
- <th align="center">Effect</th>
-
- <tr class="a">
- <td align="center"><b>a / remoteIP</b></td>
- <td>
- <p>
- Remote IP address.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>A / localIP</b></td>
- <td>
- <p>
- Local IP address.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>b / B / byteSent</b></td>
- <td>
- <p>
- Response's content length.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>h / clientHost</b></td>
- <td>
- <p>
- Remote host.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>H / protocol</b></td>
- <td>
- <p>
- Request protocol.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>l</b></td>
- <td>
- <p>
- Remote log name. In logback-access, this converter always
- returns the value "-".
- </p>
- </td>
- </tr>
-
- <tr class="a">
- <td align="center"><b>reqParameter{paramName}</b></td>
- <td>
- <p>
- Parameter of the response.
- </p>
- <p>This conversion word takes the first option in braces and looks
- for the corresponding parameter in the request.</p>
- <p><b>%reqParameter{input_data}</b>
- displays the corresponding parameter.</p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>i{header} / header{header}</b></td>
- <td>
- <p>
- Request header.
- </p>
- <p>This conversion word takes the first option in braces and looks
- for the corresponding header in the request.</p>
- <p><b>%header{Referer}</b> displays the referer of the request.</p>
- <p>
- If no option is specified, it displays every available header.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>m / requestMethod</b></td>
- <td>
- <p>
- Request method.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>r / requestURL</b></td>
- <td>
- <p>
- URL requested.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>s / statusCode</b></td>
- <td>
- <p>
- Status code of the request.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>t / date</b></td>
- <td>
- <p>
- Used to output the date of the logging event.
- The date conversion specifier may be followed by
- a set of braces containing a date and time
- pattern strings used by
- <code>java.text.SimpleDateFormat</code>
- .
- <em>ABSOLUTE</em>
- ,
- <em>DATE</em>
- or
- <em>ISO8601</em>
- can also be used.
+ <tr>
+ <th align="center">Conversion Word</th>
+ <th align="center">Effect</th>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>a / remoteIP</b></td>
+ <td>
+ <p>
+ Remote IP address.
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>A / localIP</b></td>
+ <td>
+ <p>
+ Local IP address.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>b / B / byteSent</b></td>
+ <td>
+ <p>
+ Response's content length.
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>h / clientHost</b></td>
+ <td>
+ <p>
+ Remote host.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>H / protocol</b></td>
+ <td>
+ <p>
+ Request protocol.
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>l</b></td>
+ <td>
+ <p>
+ Remote log name. In logback-access, this converter always
+ returns the value "-".
+ </p>
+ </td>
+ </tr>
+
+ <tr class="a">
+ <td align="center"><b>reqParameter{paramName}</b></td>
+ <td>
+ <p>
+ Parameter of the response.
+ </p>
+ <p>This conversion word takes the first option in braces and looks
+ for the corresponding parameter in the request.</p>
+ <p><b>%reqParameter{input_data}</b>
+ displays the corresponding parameter.</p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>i{header} / header{header}</b></td>
+ <td>
+ <p>
+ Request header.
+ </p>
+ <p>This conversion word takes the first option in braces and looks
+ for the corresponding header in the request.</p>
+ <p><b>%header{Referer}</b> displays the referer of the request.</p>
+ <p>
+ If no option is specified, it displays every available header.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>m / requestMethod</b></td>
+ <td>
+ <p>
+ Request method.
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>r / requestURL</b></td>
+ <td>
+ <p>
+ URL requested.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>s / statusCode</b></td>
+ <td>
+ <p>
+ Status code of the request.
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>t / date</b></td>
+ <td>
+ <p>Used to output the date of the logging event. The date
+ conversion specifier may be followed by a set of braces
+ containing a date and time pattern strings used by
+ <code>java.text.SimpleDateFormat</code>. <em>ABSOLUTE</em>,
+ <em>DATE</em> or <em>ISO8601</em> are also valid values.
</p>
- <p>
- For example,
- <b>%d{HH:mm:ss,SSS}</b>
- ,
- <b>
- %d{dd MMM yyyy ;HH:mm:ss,SSS}
- </b>
- or
- <b>%d{DATE}</b>
- . If no date format specifier is given then
- ISO8601 format is assumed.
+ <p>For example, <b>%d{HH:mm:ss,SSS}</b>,
+ <b>%d{dd MMM yyyy ;HH:mm:ss,SSS}</b> or
+ <b>%d{DATE}</b>. If no date format specifier is given then
+ ISO8601 format is assumed.
</p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>u / user</b></td>
- <td>
- <p>
- Remote user.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>U / requestURI</b></td>
- <td>
- <p>
- Requested URI.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>v / server</b></td>
- <td>
- <p>
- Server name.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>localPort</b></td>
- <td>
- <p>
- Local port.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>reqAttribute{attributeName}</b></td>
- <td>
- <p>
- Attribute of the request.
- </p>
- <p>This conversion word takes the first option in braces and looks
- for the corresponding attribute in the request.</p>
- <p><b>%reqAttribute{SOME_ATTRIBUTE}</b>
- displays the corresponding attribute.</p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>reqCookie{cookie}</b></td>
- <td>
- <p>
- Request cookie.
- </p>
- <p>This conversion word takes the first option in braces and looks
- for the corresponding cookie in the request.</p>
- <p><b>%cookie{COOKIE_NAME}</b> displays corresponding cookie.</p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>responseHeader{header}</b></td>
- <td>
- <p>
- Header of the response.
- </p>
- <p>This conversion word takes the first option in braces and looks
- for the corresponding header in the response.</p>
- <p><b>%header{Referer}</b> displays the referer of the response.</p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>requestContent</b></td>
- <td>
- <p>
- This conversion word displays the content of the request, that is the
- request's <code>InputStream</code>. It is used in conjunction with a
- <a href="../xref/ch/qos/logback/access/servlet/TeeFilter.html">
- <code>TeeFilter</code></a>, a <code>javax.servlet.Filter</code> that
- replaces the original <code>HttpServletRequest</code>
- by a <a href="../xref/ch/qos/logback/access/servlet/TeeHttpServletRequest.html">
- <code>TeeHttpServletRequest</code></a>. The latter object allows
- access to the requet's <code>InputStream</code> multiple times without
- any loss of data.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>fullRequest</b></td>
- <td>
- <p>This converter outputs the data associated with the
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>u / user</b></td>
+ <td>
+ <p>
+ Remote user.
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>U / requestURI</b></td>
+ <td>
+ <p>
+ Requested URI.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>v / server</b></td>
+ <td>
+ <p>Server name.</p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>localPort</b></td>
+ <td>
+ <p>Local port.</p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>reqAttribute{attributeName}</b></td>
+ <td>
+ <p>Attribute of the request.</p>
+ <p>This conversion word takes the first option in braces and looks
+ for the corresponding attribute in the request.</p>
+ <p><b>%reqAttribute{SOME_ATTRIBUTE}</b>
+ displays the corresponding attribute.</p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>reqCookie{cookie}</b></td>
+ <td>
+ <p>Request cookie.</p>
+ <p>This conversion word takes the first option in braces and looks
+ for the corresponding cookie in the request.</p>
+ <p><b>%cookie{COOKIE_NAME}</b> displays corresponding cookie.</p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>responseHeader{header}</b></td>
+ <td>
+ <p>
+ Header of the response.
+ </p>
+ <p>This conversion word takes the first option in braces and looks
+ for the corresponding header in the response.</p>
+ <p><b>%header{Referer}</b> displays the referer of the response.</p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>requestContent</b></td>
+ <td>
+ <p>This conversion word displays the content of the request,
+ that is the request's <code>InputStream</code>. It is used
+ in conjunction with a <a
+ href="../xref/ch/qos/logback/access/servlet/TeeFilter.html">
+ <code>TeeFilter</code></a>, a
+ <code>javax.servlet.Filter</code> that replaces the original
+ <code>HttpServletRequest</code> by a <a
+ href="../xref/ch/qos/logback/access/servlet/TeeHttpServletRequest.html">
+ <code>TeeHttpServletRequest</code></a>. The latter object
+ allows access to the requet's <code>InputStream</code>
+ multiple times without any loss of data.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>fullRequest</b></td>
+ <td>
+ <p>This converter outputs the data associated with the
request, including all headers and request contents.
- </p>
- </td>
- </tr>
- <tr class="b">
- <td align="center"><b>responseContent</b></td>
- <td>
- <p>
- This conversion word displays the content of the response, that is the
- response's <code>InputStream</code>. It is used in conjunction with a
+ </p>
+ </td>
+ </tr>
+ <tr class="b">
+ <td align="center"><b>responseContent</b></td>
+ <td>
+ <p>This conversion word displays the content of the
+ response, that is the response's
+ <code>InputStream</code>. It is used in conjunction with a
<a href="../xref/ch/qos/logback/access/servlet/TeeFilter.html">
- <code>TeeFilter</code></a>, a <code>javax.servlet.Filter</code> that
- replaces the original <code>HttpServletResponse</code>
- by a <a href="../xref/ch/qos/logback/access/servlet/TeeHttpServletResponse.html">
- <code>TeeHttpServletResponse</code></a>. The latter object allows
- access to the requet's <code>InputStream</code> multiple times without
- any loss of data.
- </p>
- </td>
- </tr>
- <tr class="a">
- <td align="center"><b>fullResponse</b></td>
- <td>
- <p>
- This conversion word takes all the available data
+ <code>TeeFilter</code></a>, a
+ <code>javax.servlet.Filter</code> that replaces the original
+ <code>HttpServletResponse</code> by a <a
+ href="../xref/ch/qos/logback/access/servlet/TeeHttpServletResponse.html">
+ <code>TeeHttpServletResponse</code></a>. The latter object
+ allows access to the requet's <code>InputStream</code>
+ multiple times without any loss of data.
+ </p>
+ </td>
+ </tr>
+ <tr class="a">
+ <td align="center"><b>fullResponse</b></td>
+ <td>
+ <p>This conversion word takes all the available data
associatede with the response, inclusing all headers of the
response and response contents.
- </p>
- </td>
- </tr>
- </table>
+ </p>
+ </td>
+ </tr>
+ </table>
<p>Logback access' <code>PatternLayout</code> also recognize three keywords, which
act like shortcuts to a certain pattern.</p>
@@ -1887,10 +1873,10 @@
which displays client host, remote log name, user, date, requested URL, status code
and response's content length</p>
- <p>The <em>combined</em> keyword is a shortcut to
- <em>%h %l %u %t \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\"</em>. This pattern begins
- much like the <em>common</em> pattern but also displays two request headers, namely
- referer, and user-agent.</p>
+ <p>The <em>combined</em> keyword is a shortcut for <em>%h %l %u %t
+ \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\"</em>. This pattern
+ begins much like the <em>common</em> pattern but also displays two
+ request headers, namely referer, and user-agent.</p>
<a name="AccessHTMLLayout"></a>
<h3>HTMLLayout</h3>
@@ -1898,37 +1884,49 @@
<p>The <a
href="../xref/ch/qos/logback/access/html/HTMLLayout.html"><code>HTMLLayout</code></a>
class found in logback-access is similar to the <a
- href="#ClassicHTMLLayout"><code>HTMLLayout</code></a> class found
- in logback-classic.
+ href="#ClassicHTMLLayout"><code>HTMLLayout</code></a> class from
+ logback-classic.
</p>
<p>By default, it will create a table containing the following data:</p>
<ul>
- <p>Remote IP</p>
- <p>Date</p>
- <p>Request URL</p>
- <p>Status code</p>
- <p>Content Length</p>
+ <li>Remote IP</li>
+ <li>Date</li>
+ <li>Request URL</li>
+ <li>Status code</li>
+ <li>Content Length</li>
</ul>
- <p>Here is a sample output produced by <code>HTMLLayout</code> in logback-access:</p>
+ <p>Here is a sample output produced by <code>HTMLLayout</code> in
+ logback-access:</p>
<img src="images/htmlLayoutAccess.gif" alt="Access HTML Layout Sample Image"/>
- <p>What is better than a real world example? Our own log4j
+ <p>What can be better than a real world example? Our own log4j
properties to logback <a
href="http://logback.qos.ch/translator/">translator</a> makes use
of logback-access to showcase a live ouput, using a
<code>RollingFileAppender</code> and <code>HTMLLayout</code>.</p>
- <p>You can see the file by <a
- href="http://logback.qos.ch/translator/logs/access.html">following
- this link</a>.</p>
-
- <p>Just like any access log, each visit the <a
- href="http://logback.qos.ch/translator/">translator</a>
- web-application will add a new entry to the access logs.
- </p>
+ <p>What can be better than a real world example? Our own log4j
+ properties for logback <a
+ href="http://logback.qos.ch/translator/">translator</a> makes use
+ of logback-access to demonstrate live ouput from
+ <code>RollingFileAppender</code> with <code>HTMLLayout</code>.</p>
+
+
+ <p>On every new user request to our <a
+ href="http://logback.qos.ch/translator/">translator</a>
+ web-application, a new entry will be added to the access logs,
+ which you can view by <a
+ href="http://logback.qos.ch/translator/logs/access.html">following
+ this link</a>.</p>
+
+
+
+
+
+
<script src="../templates/footer.js"></script>
</div>
Modified: logback/trunk/logback-site/src/site/pages/manual/mdc.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/mdc.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/mdc.html Mon Aug 25 21:54:06 2008
@@ -50,12 +50,11 @@
the SLF4J API: Mapped Diagnostic Contexts (MDC).
</p>
- <p>
- To uniquely stamp each request, the user puts contextual
- information into the <code><a
- href="http://www.slf4j.org/api/org/slf4j/MDC.html">MDC</a></code>,
- the abbreviation of Mapped Diagnostic Context. The public
- interface of the MDC class is shown below.
+ <p>To uniquely stamp each request, the user puts contextual
+ information into the <code><a
+ href="http://www.slf4j.org/api/org/slf4j/MDC.html">MDC</a></code>,
+ the abbreviation of Mapped Diagnostic Context. The salient parts
+ of the MDC class is shown below.
</p>
<div class="source"><pre>package org.slf4j;
@@ -73,9 +72,6 @@
//Clear all entries in the MDC.
<b>public static void clear();</b>
-
- //Returns the keys in the MDC as a Set. The returned value can be null.
- <b>public static Set<String> getKeys();</b>
}</pre></div>
<p>The <code>MDC</code> class contains only static methods. It
@@ -615,6 +611,28 @@
are unaffected. Furthermore, any given thread will contain correct
MDC data any point in time.</p>
+
+
+ <h3>MDC And Managed Threads</h3>
+
+ <p>A copy of mapped diagnostic context can not always be inherited
+ by worker thread from the initiating thread. This is the case when
+ <code>java.util.concurrent.Executors</code> is used for thread
+ management. For instance, <code>newCachedThreadPool</code> method
+ creates a <code>ThreadPoolExecutor</code> and like other thread
+ pooling code it has intricate thread creation logic.
+ </p>
+
+ <p>In such cases, it is recommended that
+ <code>MDC.getCopyOfContextMap()</code> is invoked on the original
+ (master) thread before submitting a task to the executor. When the
+ task runs, as its first action, it should invoke
+ <code>MDC.setContextMapValues()</code> to associate the stored copy
+ of the orinal MDC values with the new <code>Executor</code> managed
+ thread.
+ </p>
+
+
<script src="../templates/footer.js"></script>
</div>
</body>
1
0

[JIRA] Resolved: (LBSITE-15) logback mail lists cannot be reached again
by Ceki Gulcu (JIRA) 25 Aug '08
by Ceki Gulcu (JIRA) 25 Aug '08
25 Aug '08
[ http://jira.qos.ch/browse/LBSITE-15?page=com.atlassian.jira.plugin.system.i… ]
Ceki Gulcu resolved LBSITE-15.
------------------------------
Fix Version/s: unspecified
Resolution: Fixed
The hardware failure behind this issue has been solved with a new machine. Moreover, both the DNS and email servers are now duplicated.
> logback mail lists cannot be reached again
> ------------------------------------------
>
> Key: LBSITE-15
> URL: http://jira.qos.ch/browse/LBSITE-15
> Project: logback-site
> Issue Type: Bug
> Components: other
> Affects Versions: unspecified
> Environment: Operating System: All
> Platform: All
> URL: http://www.dnsstuff.com/tools/dnsreport.ch?domain=qos.ch
> Reporter: Ralph Goers
> Assignee: Logback dev list
> Fix For: unspecified
>
>
> Hi,
> my emails to the logback mail lists are consitently bouncing. A quick check on qos.ch DNS configuration shows there are serious problems with it. Likely this is why your mail server appears to never be available.
> See for example this report: http://www.dnsstuff.com/tools/dnsreport.ch?domain=qos.ch
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

25 Aug '08
wrong docs for variable substitution
------------------------------------
Key: LBSITE-17
URL: http://jira.qos.ch/browse/LBSITE-17
Project: logback-site
Issue Type: Bug
Components: Documentation
Reporter: Ceki Gulcu
Assignee: Logback dev list
Rob Ross reports:
Also, on Chapter 3 of the current Logback documentation manual, when it discusses variable substitution it mentions "Recursive Substitution." Well, if you re-read that section carefully I think you'll agree that this example is in fact NOT doing any kind of *recursion*, it is just using multiple variables. They are not even being nested. So I would suggest calling it something other than "recursion." The people that will read this manual are programmers, and we all know (or should know ) what recursion is, and I think this will just confuse people.
reference http://www.qos.ch/pipermail/logback-user/2008-July/000492.html
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
1
[ http://jira.qos.ch/browse/LBSITE-8?page=com.atlassian.jira.plugin.system.is… ]
Ceki Gulcu resolved LBSITE-8.
-----------------------------
Resolution: Fixed
Initial references to SLF4J now reference the SLF4J site. This should help newbies find the SLF4J project more easily.
> Provide links to externals
> --------------------------
>
> Key: LBSITE-8
> URL: http://jira.qos.ch/browse/LBSITE-8
> Project: logback-site
> Issue Type: Bug
> Components: Documentation
> Affects Versions: unspecified
> Environment: Operating System: All
> Platform: All
> Reporter: Sebastian Davids
> Assignee: Logback dev list
>
> Provide at least links to SLF4J on the documentation pages and possibly on the main menu.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

svn commit: r1776 - in logback/trunk/logback-site/src/site/pages: . manual
by noreply.ceki@qos.ch 24 Aug '08
by noreply.ceki@qos.ch 24 Aug '08
24 Aug '08
Author: ceki
Date: Sun Aug 24 23:58:15 2008
New Revision: 1776
Modified:
logback/trunk/logback-site/src/site/pages/manual/introduction.html
logback/trunk/logback-site/src/site/pages/setup.html
Log:
LBSITE-8
Add references to SLF4J in the manual, so that new users have an easier time to find it.
Modified: logback/trunk/logback-site/src/site/pages/manual/introduction.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/introduction.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/introduction.html Sun Aug 24 23:58:15 2008
@@ -69,6 +69,10 @@
<em>logback-classic.jar</em> on the classpath.
</p>
+ <p>The <em>logback-*.jar</em> files are part of the logback
+ distribution whereas <em>slf4j-api-${slf4j.version}.jar</em> ships
+ with <a href="http://www.slf4j.org">SLF4J</a>, a separate project.
+ </p>
<p>Let us now begin experimenting with logback.</p>
@@ -88,24 +92,24 @@
}
}</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><code>HelloWorld</code> class is defined in the
+ <code>chapter1</code> package. It starts by importing the <a
+ href="http://slf4j.org/api/org/slf4j/Logger.html"><code>Logger</code></a>
+ and <a
+ href="http://slf4j.org/api/org/slf4j/LoggerFactory.html"><code>LoggerFactory</code></a>
+ 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
- retrieved by invoking the static <code>getLogger</code> method
- from 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>On the first line of the main() method, the variable named
+ <code>logger</code> is assigned a <code>Logger</code> instance
+ retrieved by invoking the static <code>getLogger</code> method
+ from 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>Note that the above example does not reference any logback
@@ -130,14 +134,12 @@
<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>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>
@@ -164,11 +166,16 @@
<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@1c1ea29 - Setting up default configuration.</pre></div>
+<div class="source"><pre>12:49:22.203 [main] DEBUG chapter1.HelloWorld2 - Hello world.
+12:49:22,078 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
+12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
+12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
+</pre></div>
- <p>Logback explains that it configured itself using its default
+ <p>Logback explains that having failed to find the
+ <em>logback-test.xml</em> and <em>logback.xml</em> configuration
+ files (discussed later), 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
@@ -177,6 +184,9 @@
appropriate for their specific situation.
</p>
+ <p>Note that in case of errors, logback will automatically print its
+ internal state on the console.</p>
+
<p>The previous examples are rather simple. Actual logging in a
larger application would not be that different. The general pattern
for logging statements would not change. nly the configuration
Modified: logback/trunk/logback-site/src/site/pages/setup.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/setup.html (original)
+++ logback/trunk/logback-site/src/site/pages/setup.html Sun Aug 24 23:58:15 2008
@@ -33,6 +33,11 @@
<li>slf4j-api-${slf4j.version}.jar</li>
</ul>
+ <p>The <em>logback-*.jar</em> files are part of the logback
+ distribution whereas <em>slf4j-api-${slf4j.version}.jar</em> ships
+ with <a href="http://www.slf4j.org">SLF4J</a>, a separate project.
+ </p>
+
<h3>Running from the command line</h3>
<p>Assuming your current directory is
1
0

svn commit: r1775 - in logback/trunk: logback-examples/src/main/java/chapter3 logback-site/src/site/pages logback-site/src/site/pages/manual
by noreply.ceki@qos.ch 23 Aug '08
by noreply.ceki@qos.ch 23 Aug '08
23 Aug '08
Author: ceki
Date: Sun Aug 24 00:25:55 2008
New Revision: 1775
Added:
logback/trunk/logback-examples/src/main/java/chapter3/containingConfig.xml
- copied, changed from r1772, /logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml
logback/trunk/logback-site/src/site/pages/joran.html
Removed:
logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml
Modified:
logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml
logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml
logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml
logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml
logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml
logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties
logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties
logback/trunk/logback-site/src/site/pages/documentation.html
logback/trunk/logback-site/src/site/pages/manual/joran.html
Log:
- ongoing work on the documentation
Chapter3 has been split into two parts, the fist part on logback configuration and a second part on Joran as a standalone framework
Copied: logback/trunk/logback-examples/src/main/java/chapter3/containingConfig.xml (from r1772, /logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml)
==============================================================================
--- /logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/containingConfig.xml Sun Aug 24 00:25:55 2008
@@ -2,6 +2,11 @@
<configuration>
- <include file="path/to/configuration/file" />
+ <include file="src/main/java/chapter3/includedConfig.xml" />
+
+ <root level="DEBUG">
+ <appender-ref ref="includedConsole" />
+ </root>
+
</configuration>
Modified: logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml Sun Aug 24 00:25:55 2008
@@ -2,16 +2,10 @@
<included>
- <appender name="redirectConsole"
- class="ch.qos.logback.core.ConsoleAppender">
+ <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<param name="Pattern" value="%d - %m%n" />
</layout>
</appender>
- <root>
- <level value="DEBUG" />
- <appender-ref ref="redirectConsole" />
- </root>
-
</included>
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml Sun Aug 24 00:25:55 2008
@@ -1,9 +1,9 @@
<configuration>
- <substitutionProperty name="user.home.dir" value="/home/sebastien" />
+ <substitutionProperty name="USER_HOME" value="/home/sebastien" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
- <file>${user.home.dir}/myApp.log</file>
+ <file>${USER_HOME}/myApp.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%msg%n</Pattern>
</layout>
Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml Sun Aug 24 00:25:55 2008
@@ -1,18 +1,9 @@
<configuration>
- <appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${user.home.dir}/myApp.log</file>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>${USER_HOME}/myApp.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml Sun Aug 24 00:25:55 2008
@@ -2,19 +2,10 @@
<substitutionProperty file="variables1.properties" />
- <appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${user.home.dir}/myApp.log</file>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>${USER_HOME}/myApp.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml Sun Aug 24 00:25:55 2008
@@ -2,19 +2,10 @@
<substitutionProperty file="variables2.properties" />
- <appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${destination}</file>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>${destination}/myApp.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
Modified: logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties Sun Aug 24 00:25:55 2008
@@ -1 +1 @@
-user.home.dir=/Users/seb
\ No newline at end of file
+USER_HOME=/home/sebastien
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties (original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties Sun Aug 24 00:25:55 2008
@@ -1,3 +1,3 @@
-user.home.dir=/Users/seb
+USER_HOME=/home/sebastien
fileName=myApp.log
-destination=${user.home.dir}/${fileName}
\ No newline at end of file
+destination=${USER_HOME}/${fileName}
\ No newline at end of file
Modified: logback/trunk/logback-site/src/site/pages/documentation.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/documentation.html (original)
+++ logback/trunk/logback-site/src/site/pages/documentation.html Sun Aug 24 00:25:55 2008
@@ -38,7 +38,11 @@
<li>
<a href="dependencies.html">Dependencies per module</a>
</li>
-
+
+ <li>
+ <a href="joran.html">Using Joran in your applications</a>
+ </li>
+
<li>
<a href="jmxConfig.html">How to use the logback JMX Configurator</a>
</li>
Added: logback/trunk/logback-site/src/site/pages/joran.html
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/pages/joran.html Sun Aug 24 00:25:55 2008
@@ -0,0 +1,512 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+<title>Using Joran</title>
+<link rel="stylesheet" type="text/css" media="screen" href="css/site.css" />
+<link rel="stylesheet" type="text/css" media="print" href="css/print.css" />
+
+</head>
+<body>
+ <script type="text/javascript">prefix='./'</script>
+ <script type="text/javascript" src="templates/header.js"></script>
+<div id="left">
+ <script type="text/javascript" src="templates/left.js"></script>
+</div>
+<div id="right"><script type="text/javascript" src="templates/right.js"></script></div>
+<div id="content">
+
+ <h2>Using Joran in your own applications</h2>
+
+ <p>As we've seen, logback relies on Joran, a mature, flexible and
+ powerful configuration framework. Many of the capabilities offered
+ by logback modules are possible with the help of Joran.
+ </p>
+
+ <p>Joran is actually a generic configuration system which can be
+ used independently of logging. To emphaises this point, we should
+ mention that the logback-core module does not have a notion of
+ loggers. In that spirit, many of the examples related to this
+ tutorial, have nothing to do with loggers, appenders or layouts.
+ </p>
+
+ <p class="red" style="text-decoration: line-through;">The examples
+ for this chapter can be found under
+ <em>LOGBACK_HOME/logback-examples/src/main/java/chapter3</em>.
+ </p>
+
+ <p>To install joran, simply <a href="../download.html">download</a>
+ logback and add <em>logback-core-${version}.jar</em> to your
+ classpath.</p>
+
+ <h2>Historical perspective</h2>
+
+ <p>One of the most powerful features of the Java language is
+ reflection. Reflection makes it possible to configure software
+ systems declaratively. For example, many important properties of an
+ EJB are configured with the <em>ejb.xml</em> file. While EJBs are
+ written in Java, many of their properties are specified within the
+ <em>ejb.xml</em> file. Similarly, logback settings can be specified
+ in a configuration file, expressed in XML format.
+ </p>
+
+ <p>In log4j, logback's predecessor, <code>DOMConfigurator</code>
+ which shipped with log4j version 1.2.x could also parse
+ configuration files written in XML. The <code>DOMConfigurator</code>
+ was written in a way that forced to tweak it each time the structure
+ of the configuration file changed. The modified code had to be
+ recompiled and redeployed. Just as importantly, the code of the
+ DOMConfigurator consists of loops dealing with children elements
+ containing many interspersed if/else statements. One could not help
+ but notice that that particular code reeked of redundancy. The <a
+ href="http://jakarta.apache.org/commons/digester/">digester
+ project</a> has shown that it is possible to parse XML files using
+ pattern matching rules. At parse time, digester will apply the rules
+ that match previously stated patterns. Rule classes are usually
+ quite small and specialized. Consequently, they are relatively easy
+ to understand and to maintain.
+ </p>
+
+ <p>Joran is heavily inspired by the commons-digester project but
+ uses a slightly different terminology. In commons-digester, a rule
+ can be seen as consisting of a pattern and a rule, as shown by the
+ <code>Digester.addRule(String pattern, Rule rule)</code> method. We
+ find it unnecessarily confusing to have a rule to consist of itself,
+ not recursively but with a different meaning. In Joran, a rule
+ consists of a pattern and an action. An action is invoked when a
+ match occurs for the corresponding pattern. This relation between
+ patterns and actions lies at the core of Joran. Quite remarkably,
+ one can deal with quite complex requirements by using simple
+ patterns, or more precisely with exact matches and wildcard
+ matches. For example, the pattern <em>a/b</em> will match a
+ <code><b></code> element nested within an <code><a></code>
+ element but not a <code><c></code> element, even if nested within
+ a <code><b></code> element. It is also possible to match a
+ particular XML element, regardless of its nesting level, by using
+ the <em>*</em> wildcard character. For example, the pattern
+ <em>*/a</em> will match an <code><a></code> element at any
+ nesting position within the document. Other types of patterns, for
+ example <em>a/*</em>, are not currently supported by Joran.
+ </p>
+
+ <h2>SAX or DOM?</h2>
+
+ <p>Due to the event-based architecture of the SAX API, a tool based
+ on SAX cannot easily deal with forward references, that is,
+ references to elements which are defined later than the current
+ element being processed. Elements with cyclical references are
+ equally problematic. More generally, the DOM API allows the user to
+ perform searches on all the elements and make forward jumps.
+ </p>
+
+ <p>This extra flexibility initially led us to choose the DOM API as
+ the underlying parsing API for Joran. After some experimentation, it
+ quickly became clear that dealing with jumps to distant elements
+ while parsing the DOM tree did not make sense when the
+ interpretation rules were expressed in the form of patterns and
+ actions. <em>Joran only needs to be given the elements in the XML
+ document in a sequential, depth-first order.</em>
+ </p>
+
+ <p>Joran was first implemented in DOM. However, the author migrated
+ to SAX in order to benefit location information, available only with
+ the SAX API. Location information allows Joran to display the exact
+ line and column number where an error occured, which comes in quite
+ handy when hunting down problems.
+ </p>
+
+
+ <h2>Actions</h2>
+
+ <p>Actions extend the
+ <code>ch.qos.logback.core.joran.action.Action</code> class which
+ consists of the following abstract methods.
+ </p>
+
+
+<div class="source"><pre>package ch.qos.logback.core.joran.action;
+
+import org.xml.sax.Attributes;
+import ch.qos.logback.core.joran.spi.ExecutionContext;
+
+public abstract class Action {
+
+
+ /**
+ * Called when the parser first encounters an element.
+ */
+ public abstract void begin(ExecutionContext ec,
+ String name,
+ Attributes attributes);
+
+ /**
+ * Called when the parser encounters the element end. At
+ * this stage, we can assume that child elements, if any,
+ * have been processed.
+ */
+ public abstract void end(ExecutionContext ec, String name);
+}</pre></div>
+
+ <p>Thus, every action must implement the begin and end methods.</p>
+
+
+ <h2>Execution context</h2>
+
+ <p>To allow various actions to collaborate, the invocation of begin
+ and end methods include an execution context as the first
+ parameter. The execution context includes an object stack, an object
+ map, an error list and a reference to the Joran interpreter invoking
+ the action. Please see the
+ <code>ch.qos.logback.core.joran.spi.ExecutionContext</code> class
+ for the exact list of fields contained in the execution context.
+ </p>
+
+ <p>Actions can collaborate together by fetching, pushing or popping
+ objects from the common object stack, or by putting and fetching
+ keyed objects on the common object map. Actions can report any error
+ conditions by adding error items on the execution context's
+ <code>StatusManager</code>.
+ </p>
+
+ <a name="helloWorld"></a>
+ <h3>A hello world example</h3>
+
+ <p>The <em>logback-examples/src/main/java/chapter3/helloWorld/</em>
+ directory includes a trivial action and Joran interpreter setup
+ which just displays <em>Hello World</em> when a <hello-world>
+ element is encountered in an XML file. It also includes the basic
+ steps which are necessary to set up and invoke a Joran interpreter.
+ </p>
+
+ <p>The <em>hello.xml</em> file contains only one element, without
+ any other nested elements. The <a
+ href="../xref/chapter3/helloWorld/HelloWorldAction.html">
+ <code>HelloWorldAction</code></a> class is a trivial implementation:
+ it only prints "Hello World" in the console when it's
+ <code>begin()</code> method is called.
+ </p>
+
+ <p> <a
+ href="../xref/chapter3/helloWorld/HelloWorld.html"><code>HelloWorld</code></a>
+ is a class that sets up the Joran interpreter, with the minimal
+ steps necessary:
+ </p>
+
+ <ul>
+ <li>It creates a <code>RuleStore</code> and a <code>Context</code></li>
+ <li>It adds the <em>hello-world</em> pattern, with it's corresponding action</li>
+ <li>It creates a Joran interpreter, and passes the <code>RuleStore</code></li>
+ <li>It creates a SAX parser and parses the given file, specifying the newly created
+ Joran interpreter as the <code>ContentHandler</code></li>
+ </ul>
+
+ <p>It's last step is to print the content of the
+ <code>Context</code>. Since Joran uses logback's powerfull
+ <code>Status</code> objects for error reporting, one can have a good
+ feedback on what happened during the parsing.
+ </p>
+
+ <p>In this example, the parsing is rather simple. The
+ <em>hello-world</em> element will activate
+ <code>HelloWorldAction</code>'s <code>begin()</code> and
+ <code>end()</code> methods. In the first method, a simple call to
+ <code>System.out.println()</code> will be issued, displaying
+ <em>Hello World</em> in the console.
+ </p>
+
+ <a name="calculator"></a>
+ <h3>Collaborating actions</h3>
+
+ <p>The <em>logback-examples/src/main/java/joran/calculator/</em>
+ directory includes several actions which collaborate together
+ through the common object stack in order to accomplish simple
+ computations.
+ </p>
+
+ <p>The <em>calculator1.xml</em> file contains a <code>computation</code>
+ element, with a nested <code>literal</code> element.
+ </p>
+
+ <p>In the <a href="../xref/chapter3/calculator/Calculator1.html">
+ <code>Calculator1</code></a> class, we declare various patterns and
+ actions, that will collaborate and calculate a result based on the
+ xml file. The simple <em>calculator1.xml</em> file only creates a
+ computation and declares a literal value. The resulting parsing is
+ pretty simple:
+ </p>
+
+ <ul>
+ <li>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
+ <code>ComputationAction1</code></a> class' <code>begin()</code> method
+ is called</li>
+ <li>The <a href="../xref/chapter3/calculator/LiteralAction.html">
+ <code>LiteralAction</code></a> class' <code>begin()</code> and <code>end()</code>
+ methods are called</li>
+ <li>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
+ <code>ComputationAction1</code></a> class' <code>end()</code> method
+ is called</li>
+ </ul>
+ <p>What is interesting here is the way that the Actions collaborate.
+ The <code>LiteralAction</code> reads a literal value and pushes it
+ in the object stack maintained by the
+ <code>ExecutionContext</code>. Once done, any other action can pop
+ the value to read or modify it. Here, the <code>end()</code> method
+ of the <code>ComputationAction1</code> class pops the value from the
+ stack and prints it.
+ </p>
+
+ <p>The <em>calculator2.xml</em> file is a bit more complex, but much
+ more interesting.</p>
+
+ <p>It contains the following elements:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Calculator configuration file (logback-examples/src/main/java/chapter3/calculator/calculator2.xml)</em>
+ <div class="source"><pre><computation name="toto">
+ <literal value="7"/>
+ <literal value="3"/>
+ <add/>
+ <literal value="3"/>
+ <multiply/>
+</computation></pre></div>
+
+ <p>Here, there are obviously more actions that will be part of the
+ computation.
+ </p>
+
+ <p>When called, the <a
+ href="../xref/chapter3/calculator/AddAction.html">
+ <code>AddAction</code></a> class will remove the two integers at the
+ bottom of the stack, add them and push the resulting integer at the
+ top of the stack, for further use.</p>
+
+ <p>Later in the computation, the <a
+ href="../xref/chapter3/calculator/MultiplyAction.html">
+ <code>MultiplyAction</code></a> class will be called. It will take
+ the last two integers from the stack, multiply them and push the
+ result in the stack.</p>
+
+ <p>We have here two examples of action whose <code>begin()</code>
+ method behaves in a certain, predictable way, but whose
+ <code>end()</code> methods are empty.</p>
+
+ <p>Finally, a <em>calculator3.xml</em> is also provided, to
+ demonstrate the possibility elements that contain instances of the
+ same element. Here's the content of <em>calculator3.xml</em>:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Calculator configuration file
+ (logback-examples/src/main/java/chapter3/calculator/calculator3.xml)</em>
+
+<div class="source"><pre><computation name="toto">
+ <computation>
+ <literal value="7"/>
+ <literal value="3"/>
+ <add/>
+ </computation>
+
+ <literal value="3"/>
+ <multiply/>
+</computation></pre></div>
+
+ <p>Much like the use of parentheses in an algebrical equation, the
+ presence of a <code>computation</code> element nested in another is
+ managed by the <a
+ href="../xref/chapter3/calculator/ComputationAction2.html">
+ <code>ComputationAction2</code></a> class using an internal
+ stack. The well-formedness of XML will guarantee that a value saved
+ by one <code>begin()</code> will be consumed only by the matching
+ <code>end()</code> method.</p>
+
+ <a name="newRule"></a>
+
+ <h3>New-rule action</h3>
+
+ <p>Joran includes an action which allows the Joran interpreter to
+ lean new rules on the fly while interpreting the XML file containing
+ the new rules. See the
+ <em>logback-examples/src/main/java/joran/newRule/</em> directory for
+ sample code.
+ </p>
+
+ <p>In this package, the <a
+ href="../xref/chapter3/newRule/NewRuleCalculator.html">
+ <code>NewRuleCalculator</code></a> class contains the same setup as
+ we have seen so far, but for one line:</p>
+
+ <p class="source">ruleStore.addRule(new
+ Pattern("/computation/new-rule"), new NewRuleAction());</p>
+
+ <p>By adding this line, we ask Joran to allow new rules to be learnt
+ at parsing time. It works pretty much like the other rules: it has a
+ <code>begin()</code> and <code>end()</code> method, and is called each time
+ the parser finds a <em>new-rule</em> element.</p>
+
+ <p>When called, the <code>begin()</code> method looks for a
+ <em>pattern</em> and a <em>actionClass</em> attribute. The action
+ class is then instanciated and added to the <code>RuleStore</code>,
+ along with its corresponding pattern.</p>
+
+ <p>Here is how new rules can be declared in an xml file:</p>
+
+<div class="source"><pre><new-rule pattern="*/computation/literal"
+actionClass="chapter3.calculator.LiteralAction"/></pre></div>
+
+ <p>Using new rule declarations, the preceding example, involving the
+ calculation, could be expressed this way:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Configuration file using new
+ rules on the fly
+ (logback-examples/src/main/java/chapter3/newrule/new-rule.xml)</em>
+
+<div class="source"><pre><computation name="toto">
+ <new-rule pattern="*/computation/literal"
+ actionClass="chapter3.calculator.LiteralAction"/>
+ <new-rule pattern="*/computation/add"
+ actionClass="chapter3.calculator.AddAction"/>
+ <new-rule pattern="*/computation/multiply"
+ actionClass="chapter3.calculator.MultiplyAction"/>
+
+ <computation>
+ <literal value="7"/>
+ <literal value="3"/>
+ <add/>
+ </computation>
+
+ <literal value="3"/>
+ <multiply/>
+</computation></pre></div>
+
+ <a name="implicit"></a>
+ <h3>Implicit actions </h3>
+
+ <p>The rules defined thus far are called explicit rules because they
+ require an explicit pattern, hence fixing the tag name of the
+ elements for which they apply.
+ </p>
+
+ <p>In highly extensible systems, the number and type of components
+ to handle are innumerable so that it would become very tedious or
+ even impossible to list all the applicable patterns by name.
+ </p>
+
+ <p>At the same time, even in highly extensible systems one can
+ observe well-defined patterns linking the various parts
+ together. Implicit rules come in very handy when processing
+ components composed of sub-components unknown ahead of time. For
+ example, Apache Ant is capable of handling tasks which contain tags
+ unknown at compile time by looking at methods whose names start with
+ <em>add</em>, as in <code>addFile</code>, or
+ <code>addClassPath</code>. When Ant encounters an embedded tag
+ within a task, it simply instantiates an object that matches the
+ signature of the task class' add method and attaches the resulting
+ object to the parent.
+ </p>
+
+ <p>Joran includes similar capability in the form of implicit
+ actions. Joran keeps a list of implicit actions which can be applied
+ if no explicit pattern matches the current XML element. However,
+ applying an implicit action may not be always appropriate. Before
+ executing the implicit action, Joran asks an implicit action whether
+ it is appropriate in the current context. Only if the action replies
+ affirmatively does Joran interpreter invoke the (implicit)
+ action. This extra step makes it possible to support multiple
+ implicit actions or obviously none, if no implicit action is
+ appropriate for a given situation.
+ </p>
+
+ <p>For example, the <a
+ href="../xref/ch/qos/logback/core/joran/action/NestedComponentIA.html">
+ <code>NestedComponentIA</code></a> extending <a
+ href="../xref/ch/qos/logback/core/joran/action/ImplicitAction.html">
+ <code>ImplicitAction</code></a> , will instantiate the class
+ specified in a nested component and attach it to the parent
+ component by using setter method of the parent component and the
+ nested element's name. Under certain circumstances, a nested action
+ needs to be applied to an element say <a> and also to another
+ element <b> nested within <a>. The current implementation of
+ <code>NestedComponentIA</code> is capable of handling multiply
+ nested elements requiring intervention by the same implicit action.
+ </p>
+
+ <p>Both <code>ImplicitAction</code> and
+ <code>NestedComponentIA</code> are located in the
+ <code>ch.qos.logback.core.joran.action</code> package.
+ </p>
+
+ <p>Refer to the
+ <em>logback-examples/src/main/java/joran/implicit</em> directory for
+ an example of an implicit action.
+ </p>
+
+ <p>In that directory, you will find two actions classes, one xml
+ file and one class containing the setup of Joran.</p>
+
+ <p>The <a href="../xref/chapter3/implicit/NOPAction.html">
+ <code>NOPAction</code></a> class does nothing. It is used to set the
+ context of the <em>foo</em> element, using this line:</p>
+
+ <p class="source">ruleStore.addRule(new Pattern("*/foo"), new NOPAction());</p>
+
+ <p>After that, the implicit action, namely <a
+ href="../xref/chapter3/implicit/PrintMeImplicitAction.html">
+ <code>PrintMeImplicitAction</code></a>, is added to the
+ <code>RuleStore</code>. This is done by simply adding a new instance
+ of the action to the <code>Joran interpreter</code></p>
+
+ <p class="source">ji.addImplicitAction(new
+ PrintMeImplicitAction());</p>
+
+ <p>When called, the <code>isApplicable()</code> method of
+ <code>PrintMeImplicitAction</code> checks the value of the
+ <em>printme</em> attribute. If the value is <code>true</code>, the
+ implicit action is applicable: its <code>begin()</code> method will
+ be called.</p>
+
+ <p>The <em>implicit1.xml</em> file contains the following lines:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Usage of implicit rules
+ (logback-examples/src/main/java/chapter3/implicit/implicit1.xml)</em>
+<div class="source"><pre><foo>
+
+ <xyz printme="true">
+ <abc printme="true"/>
+ </xyz>
+
+ <xyz/>
+
+ <foo printme="true"/>
+
+</foo></pre></div>
+
+ <p>As you can see, the first element will be printed, since it has a
+ <em>printme</em> attribute, which bears the value
+ <code>true</code>.</p>
+
+ <p>The second element will not be printed, because no <em>printme</em> attibute is present.</p>
+
+ <p>The last element will not be printed, although the required
+ attribute is present. This is because implicit rules are called
+ only if no explicit rules are defined. Since we added a
+ <code>NOPAction</code> with the <em>*/foo</em> pattern, it will be
+ used instead of the <code>PrintMeImplicitAction</code>.</p>
+
+ <p>Running the example yields the following output:</p>
+
+<div class="source"><pre>Element <xyz> asked to be printed.
+Element <abc> asked to be printed.
+ERROR in ch.qos.logback.core.joran.spi.ExecutionContext@1c5c1 - no applicable action \
+for <xyz>, current pattern is [/foo/xyz]</pre></div>
+
+ <p>The last line was printed because of a call to
+ <code>StatusPrinter</code> at the end of the main class.</p>
+
+ <h3>Non goals</h3>
+
+ <p>The Joran API is not intended to be used to parse documents with
+ thousands of elements.
+ </p>
+
+
+<script src="templates/footer.js"></script>
+</div>
+</body>
+</html>
Modified: logback/trunk/logback-site/src/site/pages/manual/joran.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/joran.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/joran.html Sun Aug 24 00:25:55 2008
@@ -5,7 +5,7 @@
<title>Chapter3: Logback configuration & Joran</title>
<link rel="stylesheet" type="text/css" media="screen" href="../css/site.css" />
<link rel="stylesheet" type="text/css" media="print" href="../css/print.css" />
-<link type="text/css" rel="stylesheet" href="../ghighlighter/Styles/SyntaxHighlighter.css"></link>
+
</head>
<body>
@@ -881,24 +881,22 @@
<h4>Variable substitution</h4>
- <p>All option <em>values</em> admit variable substitution. The
- syntax of variable substitution is similar to that of Unix
- shells. The string between an opening <em>${</em> and closing
- <em>}</em> is interpreted as a key. The value of the substituted
- variable can be defined as a system property in the configuration
- file itself or in a separate file linked to the configuration
- file. The value of the key is first searched in configuration file
- or linked properties file, and if not found there, it is then
- searched in system properties. The corresponding value replaces
- <em>${aKey}</em> sequence. For example, if <em>java.home.dir</em>
- system property is set to <em>/home/xyz</em>, then every occurrence
- of the sequence <em>${java.home.dir}</em> will be interpreted as
- <em>/home/xyz</em>.
- </p>
-
- <p>The first example shows a declared property at the beginning of
- the configuration file. It is then used further down the file to
- specify the place to create the output file.
+ <p>In principle, variable substitution can occur at any point where
+ a value can be specified. The syntax of variable substitution is
+ similar to that of Unix shells. The string between an opening
+ <em>${</em> and closing <em>}</em> is interpreted as a key. The
+ value of the substituted variable can be defined in the
+ configuration file itself, in an external properties file or as a
+ system property. The corresponding value replaces <em>${aKey}</em>
+ sequence. For example, if <em>java.home.dir</em> system property is
+ set to <em>/home/xyz</em>, then every occurrence of the sequence
+ <em>${java.home.dir}</em> will be interpreted as <em>/home/xyz</em>.
+ </p>
+
+ <p>The next example shows a variable, a.k.a. a substitution
+ property, declared the beginning of the configuration file. It is
+ then used further down the file to specify the location of the
+ output file.
</p>
<em>Example 3.<span class="autoEx"/>: Simple Variable substitution
@@ -907,21 +905,13 @@
<div class="source"><pre><configuration>
- <b><substitutionProperty name="user.home.dir" value="/Users/seb" /></b>
+ <b><substitutionProperty name="USER_HOME" value="/home/sebastien" /></b>
<appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
- <b><file>${user.home.dir}/myApp.log</file></b>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
+ class="ch.qos.logback.core.FileAppender">
+ <b><file>${USER_HOME}/myApp.log</file></b>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
@@ -932,9 +922,13 @@
</configuration></pre></div>
- <p>The next example shows the use of a System property to achieve the same result. The
- property is not declared anywhere, thus logback will look for it in the System properties.
+ <p>The next example shows the use of a System property to achieve
+ the same result. The property is not declared in the configuration
+ file, thus logback will look for it in the System properties. Java
+ system properties can be set on the command line.
</p>
+
+ <p class="source">java -DUSER_HOME="/home/sebastien" MyApp2</p>
<em>Example 3.<span class="autoEx"/>: System Variable substitution
(logback-examples/src/main/java/chapter3/variableSubstitution2.xml)
@@ -943,18 +937,10 @@
<div class="source"><pre><configuration>
<appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
- <b><file>${user.home.dir}/myApp.log</file></b>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
+ class="ch.qos.logback.core.FileAppender">
+ <b><file>${USER_HOME}/myApp.log</file></b>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
@@ -964,7 +950,8 @@
</root>
</configuration></pre></div>
- <p>When many variables are used, it is often more convenient to
+
+ <p>When multiple variables are needed, it may be more convenient to
create a separate file that will contain all the variables. Here is
how one can do such a setup.
</p>
@@ -978,19 +965,11 @@
<b><substitutionProperty file="variables1.properties" /></b>
- <appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
- <b><file>${user.home.dir}/myApp.log</file></b>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
+ <appender name="FILE"
+ class="ch.qos.logback.core.FileAppender">
+ <b><file>${USER_HOME}/myApp.log</file></b>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
@@ -1000,56 +979,53 @@
</root>
</configuration></pre></div>
-<p>
-This configuration file contains a link to another file called <em>variables1.properties</em>.
-The variables contained in that other file will be read and will thus be available to the
-logback configuration file. Here is what the <em>variable.properties</em> file looks like.
-</p>
-
-<em>Example 3.<span class="autoEx"/>: Variable file (logback-examples/src/main/java/chapter3/variables1.properties)</em>
-<div class="source"><pre>user.home.dir=/Users/seb</pre></div>
-
-<p>
-Nothing more is needed to declare the variable.
-</p>
-
-<p>
-Recursive subsitution is also available. If the user wants to use variables to
-specify not only the destination directory but also the file name, here is what she
-would write in her <em>variables1.properties</em> file.
-</p>
-
-
-<em>Example 3.<span class="autoEx"/>: Recursive use of variables
-(logback-examples/src/main/java/chapter3/variables2.properties)</em>
-<div class="source"><pre>user.home.dir=/Users/seb
+ <p>This configuration file contains a reference to a file named
+ <em>variables1.properties</em>. The variables contained in that
+ file will be read defined within the context of the logback
+ configuration file. Here is what the <em>variable.properties</em>
+ file might look like.
+ </p>
+
+ <em>Example 3.<span class="autoEx"/>: Variable file
+ (logback-examples/src/main/java/chapter3/variables1.properties)</em>
+
+ <div class="source"><pre>USER_HOME=/home/sebastien</pre></div>
+
+ <p>Nested variabled subsitution is also supported. By nested, we
+ mean that the value definition of a variable contains referenced to
+ other variables. Here is an example. Suppose you wish to use
+ variables to specify not only the destination directory but also
+ the file name, and combine those variable in a third variable
+ called "destination". The properties file shown below gives an
+ example.
+ </p>
+
+
+ <em>Example 3.<span class="autoEx"/>: Recursive use of variables
+ (logback-examples/src/main/java/chapter3/variables2.properties)</em>
+
+ <div class="source"><pre>USER_HOME=/home/sebastien
fileName=myApp.log
-destination=${user.home.dir}/${fileName}</pre></div>
+<b>destination=${USER_HOME}/${fileName}</b></pre></div>
- <p>In the configuration file, only the last variable,
- <em>${destination}</em> will be used, as shown below:
+ <p>Note that in the properties file above, "destination" is
+ composed out of two other variables, namely "USER_HOME" and
+ "fileName".
</p>
-
- <em>Example 3.<span class="autoEx"/>: Variable substitution using a separate file
+
+ <em>Example 3.<span class="autoEx"/>: Variable substitution using
+ a separate file
(logback-examples/src/main/java/chapter3/variableSubstitution4.xml)</em>
<div class="source"><pre><configuration>
- <substitutionProperty file="variables1.properties" />
+ <substitutionProperty file="variables2.properties" />
<appender name="FILE"
- class="ch.qos.logback.core.rolling.RollingFileAppender">
+ class="ch.qos.logback.core.FileAppender">
<b><file>${destination}</file></b>
- <rollingPolicy
- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>
- myApp-%d{yyyy-MM-dd-HH}.log
- </FileNamePattern>
- </rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %date %level [%thread] %logger{10} [%file : %line] %msg%n
- </Pattern>
+ <Pattern>%msg%n</Pattern>
</layout>
</appender>
@@ -1059,546 +1035,62 @@
</root>
</configuration></pre></div>
+ <h3>Default substitution values for variables</h3>
+
+ <p>Under certain circumstances, it may be desirable for a variable
+ to have a default value in case it is not declared or its value is
+ null. As in the <a
+ href="http://tldp.org/LDP/abs/html/parameter-substitution.html">Bash
+ shell</a>, default values can be specified using the <b>":-"</b>
+ operator. For example, assuming <em>aKey</em> is not defined,
+ <code>"${aKey<b>:-golden</b>}"</code> will be interpreted as
+ "golden".</p>
+
+
<a name="Include"></a>
<h3>File inclusion</h3>
- <p> It is possible to include configuration elements into a
- <em>logback.xml</em> configuration file. This is done by using a
- <em>include</em> element, as shown in the example below:
+ <p>Joran supports including parts of a configuration file from
+ another file. This is done by declaring a <code><include></code>
+ element, as shown below:
</p>
<em>Example 3.<span class="autoEx"/>: File include
- (logback-examples/src/main/java/chapter3/redirectConfig.xml)</em>
+ (logback-examples/src/main/java/chapter3/containingConfig.xml)</em>
<div class="source"><pre><configuration>
- <b><include file="path/to/configuration/file"/></b>
- </configuration></pre></div>
+ <b><include file="src/main/java/chapter3/includedConfig.xml"/></b>
- <p>The target file must have its elements nested inside an
- <em>included</em> element. For example, a
- <code>ConsoleAppender</code> would be declared this way:
+ <root level="DEBUG">
+ <appender-ref ref="includedConsole" />
+ </root>
+
+</configuration></pre></div>
+
+ <p>The target file MUST have its elements nested inside an
+ <code><included></code> element. For example, a
+ <code>ConsoleAppender</code> could be declared as:
</p>
<em>Example 3.<span class="autoEx"/>: File include
(logback-examples/src/main/java/chapter3/includedConfig.xml)</em>
- <div class="source"><pre><included>
-
- <appender name="redirectConsole"
- class="ch.qos.logback.core.ConsoleAppender">
+ <div class="source"><pre><b class="green"><included></b>
+ <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
- <param name="Pattern" value="%d - %m%n" />
+ <Pattern>"%d - %m%n"</Pattern>
</layout>
</appender>
+<b class="green"></included></b></pre></div>
- <root>
- <level value="DEBUG" />
- <appender-ref ref="redirectConsole" />
- </root>
-
-</included></pre></div>
-
- <p>The file to be included can be referenced as a URL or as a
- resource. To reference a URL use the <code>url</code> attribute
- instead of the file attribute in the previous example. To reference
- a resource, use the <code>resource</code> attribute instead of the
- file attribute in the previous example.
- </p>
-
-
- <a name="Joran"></a>
- <h2>Using Joran in your own application</h2>
-
- <p>As we've seen, logback relies on Joran, a mature, flexible and
- powerful configuration framework. Many of the capabilities offered
- by logback modules are possible with the help of Joran.
- </p>
-
- <p>Joran is actually a generic configuration system which can be
- used independently of logging. To emphaises this point, we should
- mention that the logback-core module does not have a notion of
- loggers. In that spirit, many of the examples related to this
- tutorial, have nothing to do with loggers, appenders or layouts.
- </p>
-
- <p>The examples for this chapter can be found under
- <em>LOGBACK_HOME/logback-examples/src/main/java/chapter3</em>.
- </p>
-
- <p>To install joran, simply <a href="../download.html">download</a>
- logback and add <em>logback-core-VERSION.jar</em> to your classpath.</p>
-
- <h2>Historical perspective</h2>
-
- <p>One of the most powerful features of the Java language is
- reflection. Reflection makes it possible to configure software systems
- declaratively. For example, many important properties of an EJB are
- configured with the <em>ejb.xml</em> file. While EJBs are written in Java, many
- of their properties are specified within the <em>ejb.xml</em> file. Similarly,
- logback settings can be specified in a configuration file, expressed
- in XML format.
- </p>
-
- <p>In log4j, logback's predecessor, <code>DOMConfigurator</code>
- that shipped with log4j version 1.2.x can parse configuration files
- written in XML. The <code>DOMConfigurator</code> was written in a
- way that forced to tweak it each time the structure of the
- configuration file changed. The modified code had to be recompiled
- and redeployed. Just as importantly, the code of the DOMConfigurator
- consists of loops dealing with children elements containing many
- interspersed if/else statements. One could not help but notice that
- that particular code reeked of redundancy. The <a
- href="http://jakarta.apache.org/commons/digester/">digester
- project</a> has shown that it is possible to parse XML files using
- pattern matching rules. At parse time, digester will apply the rules
- that match previously stated patterns. Rule classes are usually
- quite small and specialized. Consequently, they are relatively easy
- to understand and to maintain.
- </p>
-
- <p>Joran is heavily inspired by the commons-digester project but
- uses a slightly different terminology. In commons-digester, a rule
- can be seen as consisting of a pattern and a rule, as shown by the
- <code>Digester.addRule(String pattern, Rule rule)</code> method. We
- find it unnecessarily confusing to have a rule to consist of itself,
- not recursively but with a different meaning. In Joran, a rule
- consists of a pattern and an action. An action is invoked when a
- match occurs for the corresponding pattern. This relation between
- patterns and actions lies at the core of Joran. Quite remarkably,
- one can deal with quite complex requirements by using simple
- patterns, or more precisely with exact matches and wildcard
- matches. For example, the pattern <em>a/b</em> will match a
- <code><b></code> element nested within an <code><a></code>
- element but not a <code><c></code> element, even if nested within
- a <code><b></code> element. It is also possible to match a
- particular XML element, regardless of its nesting level, by using
- the <em>*</em> wildcard character. For example, the pattern
- <em>*/a</em> will match an <code><a></code> element at any
- nesting position within the document. Other types of patterns, for
- example <em>a/*</em>, are not currently supported by Joran.
- </p>
-
- <h2>SAX or DOM?</h2>
-
- <p>Due to the event-based architecture of the SAX API, a tool based
- on SAX cannot easily deal with forward references, that is,
- references to elements which are defined later than the current
- element being processed. Elements with cyclical references are
- equally problematic. More generally, the DOM API allows the user to
- perform searches on all the elements and make forward jumps.
- </p>
-
- <p>This extra flexibility initially led us to choose the DOM API as
- the underlying parsing API for Joran. After some experimentation, it
- quickly became clear that dealing with jumps to distant elements
- while parsing the DOM tree did not make sense when the
- interpretation rules were expressed in the form of patterns and
- actions. <em>Joran only needs to be given the elements in the XML
- document in a sequential, depth-first order.</em>
- </p>
-
- <p>Joran was first implemented in DOM. However, the author migrated
- to SAX in order to benefit form the location information provided to
- the user, that is, to an
- <code>org.w3.sax.ContentHandler</code>. With the help of location
- information, it becomes possible to display essential error reports
- to the user which include exact line and column. This extra
- information turns out to be handy in hunting down problems.
- </p>
-
-
- <h2>Actions</h2>
-
- <p>Actions extend the
- <code>ch.qos.logback.core.joran.action.Action</code> class which
- consists of the following abstract methods.
+ <p>The file to be included can be referenced as a file, as a URL or
+ as a resource. To reference a file use the <span
+ class="attr">file</span> attribute. To reference a URL use the <span
+ class="attr">url</span> attribute. To reference a resource, use the
+ <span class="attr">resource</span> attribute.
</p>
-<div class="source"><pre>package ch.qos.logback.core.joran.action;
-
-import org.xml.sax.Attributes;
-import ch.qos.logback.core.joran.spi.ExecutionContext;
-
-public abstract class Action {
-
-
- /**
- * Called when the parser first encounters an element.
- */
- public abstract void begin(ExecutionContext ec,
- String name,
- Attributes attributes);
-
- /**
- * Called when the parser encounters the element end. At
- * this stage, we can assume that child elements, if any,
- * have been processed.
- */
- public abstract void end(ExecutionContext ec, String name);
-}</pre></div>
-
- <p>Thus, every action must implement the begin and end methods.</p>
-
-
- <h2>Execution context</h2>
-
- <p>To allow various actions to collaborate, the invocation of begin
- and end methods include an execution context as the first
- parameter. The execution context includes an object stack, an object
- map, an error list and a reference to the Joran interpreter invoking
- the action. Please see the
- <code>ch.qos.logback.core.joran.spi.ExecutionContext</code> class
- for the exact list of fields contained in the execution context.
- </p>
-
- <p>Actions can collaborate together by fetching, pushing or popping
- objects from the common object stack, or by putting and fetching
- keyed objects on the common object map. Actions can report any error
- conditions by adding error items on the execution context's
- <code>StatusManager</code>.
- </p>
-
- <a name="helloWorld"></a>
- <h3>A hello world example</h3>
-
- <p>The <em>logback-examples/src/main/java/chapter3/helloWorld/</em>
- directory includes a trivial action and Joran interpreter setup
- which just displays <em>Hello World</em> when a <hello-world>
- element is encountered in an XML file. It also includes the basic
- steps which are necessary to set up and invoke a Joran interpreter.
- </p>
-
- <p>The <em>hello.xml</em> file contains only one element, without
- any other nested elements. The <a
- href="../xref/chapter3/helloWorld/HelloWorldAction.html">
- <code>HelloWorldAction</code></a> class is a trivial implementation:
- it only prints "Hello World" in the console when it's
- <code>begin()</code> method is called.
- </p>
-
- <p> <a
- href="../xref/chapter3/helloWorld/HelloWorld.html"><code>HelloWorld</code></a>
- is a class that sets up the Joran interpreter, with the minimal
- steps necessary:
- </p>
-
- <ul>
- <li>It creates a <code>RuleStore</code> and a <code>Context</code></li>
- <li>It adds the <em>hello-world</em> pattern, with it's corresponding action</li>
- <li>It creates a Joran interpreter, and passes the <code>RuleStore</code></li>
- <li>It creates a SAX parser and parses the given file, specifying the newly created
- Joran interpreter as the <code>ContentHandler</code></li>
- </ul>
-
- <p>It's last step is to print the content of the
- <code>Context</code>. Since Joran uses logback's powerfull
- <code>Status</code> objects for error reporting, one can have a good
- feedback on what happened during the parsing.
- </p>
-
- <p>In this example, the parsing is rather simple. The
- <em>hello-world</em> element will activate
- <code>HelloWorldAction</code>'s <code>begin()</code> and
- <code>end()</code> methods. In the first method, a simple call to
- <code>System.out.println()</code> will be issued, displaying
- <em>Hello World</em> in the console.
- </p>
-
- <a name="calculator"></a>
- <h3>Collaborating actions</h3>
-
- <p>The <em>logback-examples/src/main/java/joran/calculator/</em>
- directory includes several actions which collaborate together
- through the common object stack in order to accomplish simple
- computations.
- </p>
-
- <p>The <em>calculator1.xml</em> file contains a <code>computation</code>
- element, with a nested <code>literal</code> element.
- </p>
-
- <p>In the <a href="../xref/chapter3/calculator/Calculator1.html">
- <code>Calculator1</code></a> class, we declare various patterns and
- actions, that will collaborate and calculate a result based on the
- xml file. The simple <em>calculator1.xml</em> file only creates a
- computation and declares a literal value. The resulting parsing is
- pretty simple:
- </p>
-
- <ul>
- <li>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
- <code>ComputationAction1</code></a> class' <code>begin()</code> method
- is called</li>
- <li>The <a href="../xref/chapter3/calculator/LiteralAction.html">
- <code>LiteralAction</code></a> class' <code>begin()</code> and <code>end()</code>
- methods are called</li>
- <li>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
- <code>ComputationAction1</code></a> class' <code>end()</code> method
- is called</li>
- </ul>
- <p>What is interesting here is the way that the Actions collaborate.
- The <code>LiteralAction</code> reads a literal value and pushes it
- in the object stack maintained by the
- <code>ExecutionContext</code>. Once done, any other action can pop
- the value to read or modify it. Here, the <code>end()</code> method
- of the <code>ComputationAction1</code> class pops the value from the
- stack and prints it.
- </p>
-
- <p>The <em>calculator2.xml</em> file is a bit more complex, but much
- more interesting.</p>
-
- <p>It contains the following elements:</p>
-
- <em>Example 3.<span class="autoEx"/>: Calculator configuration file (logback-examples/src/main/java/chapter3/calculator/calculator2.xml)</em>
- <div class="source"><pre><computation name="toto">
- <literal value="7"/>
- <literal value="3"/>
- <add/>
- <literal value="3"/>
- <multiply/>
-</computation></pre></div>
-
- <p>Here, there are obviously more actions that will be part of the
- computation.
- </p>
-
- <p>When called, the <a
- href="../xref/chapter3/calculator/AddAction.html">
- <code>AddAction</code></a> class will remove the two integers at the
- bottom of the stack, add them and push the resulting integer at the
- top of the stack, for further use.</p>
-
- <p>Later in the computation, the <a
- href="../xref/chapter3/calculator/MultiplyAction.html">
- <code>MultiplyAction</code></a> class will be called. It will take
- the last two integers from the stack, multiply them and push the
- result in the stack.</p>
-
- <p>We have here two examples of action whose <code>begin()</code>
- method behaves in a certain, predictable way, but whose
- <code>end()</code> methods are empty.</p>
-
- <p>Finally, a <em>calculator3.xml</em> is also provided, to
- demonstrate the possibility elements that contain instances of the
- same element. Here's the content of <em>calculator3.xml</em>:</p>
-
- <em>Example 3.<span class="autoEx"/>: Calculator configuration file
- (logback-examples/src/main/java/chapter3/calculator/calculator3.xml)</em>
-
-<div class="source"><pre><computation name="toto">
- <computation>
- <literal value="7"/>
- <literal value="3"/>
- <add/>
- </computation>
-
- <literal value="3"/>
- <multiply/>
-</computation></pre></div>
-
- <p>Much like the use of parentheses in an algebrical equation, the
- presence of a <code>computation</code> element nested in another is
- managed by the <a
- href="../xref/chapter3/calculator/ComputationAction2.html">
- <code>ComputationAction2</code></a> class using an internal
- stack. The well-formedness of XML will guarantee that a value saved
- by one <code>begin()</code> will be consumed only by the matching
- <code>end()</code> method.</p>
-
- <a name="newRule"></a>
-
- <h3>New-rule action</h3>
-
- <p>Joran includes an action which allows the Joran interpreter to
- lean new rules on the fly while interpreting the XML file containing
- the new rules. See the
- <em>logback-examples/src/main/java/joran/newRule/</em> directory for
- sample code.
- </p>
-
- <p>In this package, the <a
- href="../xref/chapter3/newRule/NewRuleCalculator.html">
- <code>NewRuleCalculator</code></a> class contains the same setup as
- we have seen so far, but for one line:</p>
-
- <p class="source">ruleStore.addRule(new
- Pattern("/computation/new-rule"), new NewRuleAction());</p>
-
- <p>By adding this line, we ask Joran to allow new rules to be learnt
- at parsing time. It works pretty much like the other rules: it has a
- <code>begin()</code> and <code>end()</code> method, and is called each time
- the parser finds a <em>new-rule</em> element.</p>
-
- <p>When called, the <code>begin()</code> method looks for a
- <em>pattern</em> and a <em>actionClass</em> attribute. The action
- class is then instanciated and added to the <code>RuleStore</code>,
- along with its corresponding pattern.</p>
-
- <p>Here is how new rules can be declared in an xml file:</p>
-
-<div class="source"><pre><new-rule pattern="*/computation/literal"
-actionClass="chapter3.calculator.LiteralAction"/></pre></div>
-
- <p>Using new rule declarations, the preceding example, involving the
- calculation, could be expressed this way:</p>
-
- <em>Example 3.<span class="autoEx"/>: Configuration file using new
- rules on the fly
- (logback-examples/src/main/java/chapter3/newrule/new-rule.xml)</em>
-
-<div class="source"><pre><computation name="toto">
- <new-rule pattern="*/computation/literal"
- actionClass="chapter3.calculator.LiteralAction"/>
- <new-rule pattern="*/computation/add"
- actionClass="chapter3.calculator.AddAction"/>
- <new-rule pattern="*/computation/multiply"
- actionClass="chapter3.calculator.MultiplyAction"/>
-
- <computation>
- <literal value="7"/>
- <literal value="3"/>
- <add/>
- </computation>
-
- <literal value="3"/>
- <multiply/>
-</computation></pre></div>
-
- <a name="implicit"></a>
- <h3>Implicit actions </h3>
-
- <p>The rules defined thus far are called explicit rules because they
- require an explicit pattern, hence fixing the tag name of the
- elements for which they apply.
- </p>
-
- <p>In highly extensible systems, the number and type of components
- to handle are innumerable so that it would become very tedious or
- even impossible to list all the applicable patterns by name.
- </p>
-
- <p>At the same time, even in highly extensible systems one can
- observe well-defined patterns linking the various parts
- together. Implicit rules come in very handy when processing
- components composed of sub-components unknown ahead of time. For
- example, Apache Ant is capable of handling tasks which contain tags
- unknown at compile time by looking at methods whose names start with
- <em>add</em>, as in <code>addFile</code>, or
- <code>addClassPath</code>. When Ant encounters an embedded tag
- within a task, it simply instantiates an object that matches the
- signature of the task class' add method and attaches the resulting
- object to the parent.
- </p>
-
- <p>Joran includes similar capability in the form of implicit
- actions. Joran keeps a list of implicit actions which can be applied
- if no explicit pattern matches the current XML element. However,
- applying an implicit action may not be always appropriate. Before
- executing the implicit action, Joran asks an implicit action whether
- it is appropriate in the current context. Only if the action replies
- affirmatively does Joran interpreter invoke the (implicit)
- action. This extra step makes it possible to support multiple
- implicit actions or obviously none, if no implicit action is
- appropriate for a given situation.
- </p>
-
- <p>For example, the <a
- href="../xref/ch/qos/logback/core/joran/action/NestedComponentIA.html">
- <code>NestedComponentIA</code></a> extending <a
- href="../xref/ch/qos/logback/core/joran/action/ImplicitAction.html">
- <code>ImplicitAction</code></a> , will instantiate the class
- specified in a nested component and attach it to the parent
- component by using setter method of the parent component and the
- nested element's name. Under certain circumstances, a nested action
- needs to be applied to an element say <a> and also to another
- element <b> nested within <a>. The current implementation of
- <code>NestedComponentIA</code> is capable of handling multiply
- nested elements requiring intervention by the same implicit action.
- </p>
-
- <p>Both <code>ImplicitAction</code> and
- <code>NestedComponentIA</code> are located in the
- <code>ch.qos.logback.core.joran.action</code> package.
- </p>
-
- <p>Refer to the
- <em>logback-examples/src/main/java/joran/implicit</em> directory for
- an example of an implicit action.
- </p>
-
- <p>In that directory, you will find two actions classes, one xml
- file and one class containing the setup of Joran.</p>
-
- <p>The <a href="../xref/chapter3/implicit/NOPAction.html">
- <code>NOPAction</code></a> class does nothing. It is used to set the
- context of the <em>foo</em> element, using this line:</p>
-
- <p class="source">ruleStore.addRule(new Pattern("*/foo"), new NOPAction());</p>
-
- <p>After that, the implicit action, namely <a
- href="../xref/chapter3/implicit/PrintMeImplicitAction.html">
- <code>PrintMeImplicitAction</code></a>, is added to the
- <code>RuleStore</code>. This is done by simply adding a new instance
- of the action to the <code>Joran interpreter</code></p>
-
- <p class="source">ji.addImplicitAction(new
- PrintMeImplicitAction());</p>
-
- <p>When called, the <code>isApplicable()</code> method of
- <code>PrintMeImplicitAction</code> checks the value of the
- <em>printme</em> attribute. If the value is <code>true</code>, the
- implicit action is applicable: its <code>begin()</code> method will
- be called.</p>
-
- <p>The <em>implicit1.xml</em> file contains the following lines:</p>
-
- <em>Example 3.<span class="autoEx"/>: Usage of implicit rules
- (logback-examples/src/main/java/chapter3/implicit/implicit1.xml)</em>
-<div class="source"><pre><foo>
-
- <xyz printme="true">
- <abc printme="true"/>
- </xyz>
-
- <xyz/>
-
- <foo printme="true"/>
-
-</foo></pre></div>
-
- <p>As you can see, the first element will be printed, since it has a
- <em>printme</em> attribute, which bears the value
- <code>true</code>.</p>
-
- <p>The second element will not be printed, because no <em>printme</em> attibute is present.</p>
-
- <p>The last element will not be printed, although the required
- attribute is present. This is because implicit rules are called
- only if no explicit rules are defined. Since we added a
- <code>NOPAction</code> with the <em>*/foo</em> pattern, it will be
- used instead of the <code>PrintMeImplicitAction</code>.</p>
-
- <p>Running the example yields the following output:</p>
-
-<div class="source"><pre>Element <xyz> asked to be printed.
-Element <abc> asked to be printed.
-ERROR in ch.qos.logback.core.joran.spi.ExecutionContext@1c5c1 - no applicable action \
-for <xyz>, current pattern is [/foo/xyz]</pre></div>
-
- <p>The last line was printed because of a call to
- <code>StatusPrinter</code> at the end of the main class.</p>
-
- <h3>Non goals</h3>
-
- <p>The Joran API is not intended to be used to parse documents with
- thousands of elements.
- </p>
-
-
-
-
1
0