[logback-dev] svn commit: r746 - in logback/trunk: logback-classic/examples/src/chapter5 logback-site/src/site/resources/manual logback-site/src/site/resources/manual/images logback-site/src/site/resources/manual/images/chapter5 logback-site/src/site/xdocTemplates/manual
noreply.seb at qos.ch
noreply.seb at qos.ch
Mon Oct 23 20:06:31 CEST 2006
Author: seb
Date: Mon Oct 23 20:06:31 2006
New Revision: 746
Added:
logback/trunk/logback-classic/examples/src/chapter5/MySampleLayout.java
logback/trunk/logback-classic/examples/src/chapter5/MySampleLayout2.java
logback/trunk/logback-classic/examples/src/chapter5/SampleLogging.java
logback/trunk/logback-classic/examples/src/chapter5/sampleLayoutConfig.xml
logback/trunk/logback-classic/examples/src/chapter5/sampleLayoutConfig2.xml
logback/trunk/logback-site/src/site/resources/manual/
logback/trunk/logback-site/src/site/resources/manual/images/
logback/trunk/logback-site/src/site/resources/manual/images/chapter5/ (props changed)
logback/trunk/logback-site/src/site/resources/manual/images/chapter5/htmlLayout1.gif (contents, props changed)
Modified:
logback/trunk/logback-site/src/site/xdocTemplates/manual/layouts.xml
Log:
Work in progress
Added: logback/trunk/logback-classic/examples/src/chapter5/MySampleLayout.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/examples/src/chapter5/MySampleLayout.java Mon Oct 23 20:06:31 2006
@@ -0,0 +1,27 @@
+package chapter5;
+
+import ch.qos.logback.classic.ClassicLayout;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.LayoutBase;
+
+public class MySampleLayout extends LayoutBase implements ClassicLayout {
+
+ public String doLayout(LoggingEvent event) {
+ StringBuffer sbuf = new StringBuffer(128);
+ sbuf.append(event.getTimeStamp() - LoggingEvent.getStartTime());
+ sbuf.append(" ");
+ sbuf.append(event.getLevel());
+ sbuf.append(" [");
+ sbuf.append(event.getThreadName());
+ sbuf.append("] ");
+ sbuf.append(event.getLoggerRemoteView().getName());
+ sbuf.append(" - ");
+ sbuf.append(event.getFormattedMessage());
+ sbuf.append(LINE_SEP);
+ return sbuf.toString();
+ }
+
+ public String doLayout(Object event) {
+ return doLayout((LoggingEvent)event);
+ }
+}
\ No newline at end of file
Added: logback/trunk/logback-classic/examples/src/chapter5/MySampleLayout2.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/examples/src/chapter5/MySampleLayout2.java Mon Oct 23 20:06:31 2006
@@ -0,0 +1,45 @@
+package chapter5;
+
+import ch.qos.logback.classic.ClassicLayout;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.LayoutBase;
+
+public class MySampleLayout2 extends LayoutBase implements ClassicLayout {
+
+ String prefix = null;
+ boolean printThreadName = true;
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public void setPrintThreadName(String printThreadName) {
+ this.printThreadName = printThreadName.equals("true");
+ }
+
+ public String doLayout(LoggingEvent event) {
+ StringBuffer sbuf = new StringBuffer(128);
+ if (prefix != null) {
+ sbuf.append(prefix + ": ");
+ }
+ sbuf.append(event.getTimeStamp() - LoggingEvent.getStartTime());
+ sbuf.append(" ");
+ sbuf.append(event.getLevel());
+ if (printThreadName) {
+ sbuf.append(" [");
+ sbuf.append(event.getThreadName());
+ sbuf.append("] ");
+ } else {
+ sbuf.append(" ");
+ }
+ sbuf.append(event.getLoggerRemoteView().getName());
+ sbuf.append(" - ");
+ sbuf.append(event.getFormattedMessage());
+ sbuf.append(LINE_SEP);
+ return sbuf.toString();
+ }
+
+ public String doLayout(Object event) {
+ return doLayout((LoggingEvent) event);
+ }
+}
\ No newline at end of file
Added: logback/trunk/logback-classic/examples/src/chapter5/SampleLogging.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/examples/src/chapter5/SampleLogging.java Mon Oct 23 20:06:31 2006
@@ -0,0 +1,31 @@
+package chapter5;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class SampleLogging {
+
+ public static void main(String[] args) {
+ Logger logger = (Logger) LoggerFactory
+ .getLogger(SampleLogging.class);
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ try {
+ JoranConfigurator configurator = new JoranConfigurator();
+ configurator.setContext(lc);
+ configurator.doConfigure(args[0]);
+ } catch (JoranException je) {
+ StatusPrinter.print(lc);
+ }
+
+ logger.debug("Everything's going well");
+
+ logger.error("... not quite");
+ }
+
+}
Added: logback/trunk/logback-classic/examples/src/chapter5/sampleLayoutConfig.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/examples/src/chapter5/sampleLayoutConfig.xml Mon Oct 23 20:06:31 2006
@@ -0,0 +1,12 @@
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="chapter5.MySampleLayout" />
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
\ No newline at end of file
Added: logback/trunk/logback-classic/examples/src/chapter5/sampleLayoutConfig2.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/examples/src/chapter5/sampleLayoutConfig2.xml Mon Oct 23 20:06:31 2006
@@ -0,0 +1,15 @@
+<configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="chapter5.MySampleLayout2">
+ <prefix>MyContext</prefix>
+ <printThreadName>false</printThreadName>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
\ No newline at end of file
Added: logback/trunk/logback-site/src/site/resources/manual/images/chapter5/htmlLayout1.gif
==============================================================================
Binary file. No diff available.
Modified: logback/trunk/logback-site/src/site/xdocTemplates/manual/layouts.xml
==============================================================================
--- logback/trunk/logback-site/src/site/xdocTemplates/manual/layouts.xml (original)
+++ logback/trunk/logback-site/src/site/xdocTemplates/manual/layouts.xml Mon Oct 23 20:06:31 2006
@@ -66,11 +66,12 @@
}</pre></div>
<p>
This interface is rather simple and yet is sufficent for
- many formatting needs.
+ many formatting needs. The Texan developer from Texas,
+ who you might know from Joseph Heller's <em>Catch-22</em>,
+ might exclaim:
+ it just takes two methods to implement a layout!!?
</p>
- <!-- Do we add here something about one's personal implementation of Layout? -->
-
<h2>Logback classic</h2>
<p>
@@ -91,6 +92,125 @@
}</pre></div>
+ <h3>Writing your own Layout</h3>
+ <p>
+ Let us implement a simple and functional layout for the
+ classic module which prints the time elapsed since the start
+ of the application, the level of the logging event, the
+ caller thread between brackets, its logger name, a dash followed
+ by the event message and a new line.
+ </p>
+ <p>Sample output might look like:</p>
+ <div class="source">10489 DEBUG [main] com.marsupial.Pouch - Hello world.</div>
+
+ <p>Here is a possible implementation, authored by the Texan developer:</p>
+ <em>Example 5.0: Sample implementation of a Layout
+ (examples/chapter5/MySampleLayout.java)</em>
+ <div class="source"><pre>package chapter5;
+
+import ch.qos.logback.classic.ClassicLayout;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.LayoutBase;
+
+public class MySampleLayout extends LayoutBase implements ClassicLayout {
+
+ public String doLayout(LoggingEvent event) {
+ StringBuffer sbuf = new StringBuffer(128);
+ sbuf.append(event.getTimeStamp() - LoggingEvent.getStartTime());
+ sbuf.append(" ");
+ sbuf.append(event.getLevel());
+ sbuf.append(" [");
+ sbuf.append(event.getThreadName());
+ sbuf.append("] ");
+ sbuf.append(event.getLoggerRemoteView().getName());
+ sbuf.append(" - ");
+ sbuf.append(event.getFormattedMessage());
+ sbuf.append(LINE_SEP);
+ return sbuf.toString();
+ }
+
+ public String doLayout(Object event) {
+ return doLayout((LoggingEvent)event);
+ }
+}</pre></div>
+
+ <p>
+ Note that
+ <code>MySampleLayout</code>
+ extends <code>LayoutBase</code>.
+ This class manages trivial components of a <code>Layout</code>
+ such as started or stopped status, header, footer and
+ content type access or logging context awareness. It allows
+ the developer to concentrate on the formatting she expects
+ from her <code>Layout</code>.
+ </p>
+
+ <p><code>MySampleLayout</code> implements the <code>ClassicLayout</code>
+ interface, since it is intented to be used with the classic module.
+ Therefore, it offers a trivial implementation of the
+ <code>doLayout(Object event)</code> method, that only casts the event
+ in the right type and passes it to the method where the actual formatting
+ takes place.</p>
+
+ <p>The marginally more interesting <code>doLayout(LoggingEvent event)</code>
+ method begins by instantiating a StringBuffer. It proceeds by adding various
+ fields of the event parameter. The Texan from Texas was careful to print
+ the formatted form of the message and not its object form.
+ This allows for logging requests which are passed object arrays to
+ build the message in its proper form.
+ </p>
+ <p>
+ In the previous listing of the <code>Layout</code> class,
+ we had omitted the class static <code>LINE_SEP</code>
+ field which is simply assigned the value returned by
+ <code>System.getProperty("line.separator")</code>
+ method. After adding system dependent line separator
+ character(s), the format method returns the string buffer as
+ a String.
+ </p>
+ <p>
+ The format method ignores any eventual exceptions contained
+ in the event, leaving the task of handling throwables to the
+ containing appender.
+ </p>
+
+ <p>Custom layouts are configured as any other layout, as shown below:</p>
+
+ <em>Example 5.0: Configuration of MySampleLayout
+ (examples/chapter5/sampleLayoutConfig.xml)</em>
+<div class="source"><pre><configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <b><layout class="chapter5.MySampleLayout" /></b>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration></pre></div>
+
+ <p>The sample application <code>chapter5.SampleLogging</code> configures logback with the
+ configuration script supplied as parameter and then logs a debug message,
+ followed by an error message.
+ See <em>examples/chapter5/SampleLogging.java</em> for precise details.</p>
+
+ <p>Executing the command <em>java chapter5.SampleLogging chapter5/sampleLayoutConfig.xml</em>
+ will produce the following output:</p>
+
+<div class="source"><pre>0 DEBUG [main] chapter5.SampleLogging - Everything's going well
+0 ERROR [main] chapter5.SampleLogging - ... not quite</pre></div>
+
+ <p>That was simple enough.
+ The skeptic Pyrrho of Elea, who insists that nothing is certain except
+ perhaps uncertainty itself, which is by no means certain either,
+ might ask: how about a layout with options?
+ The reader shall find a slightly modified version of our
+ custom layout in <code>MySampleLayout2.java</code>. She will discover that adding an option
+ to a layout is as simple as declaring a setter method for the option.
+ See also <em>chapter5/sampleLayoutConfig2.xml</em> for a configuration example.</p>
+
<h3>PatternLayout</h3>
<p>
@@ -953,11 +1073,19 @@
displayed when <em>the expression passed to the evaluator is <b>false</b>.</em></p>
<h3>HTMLLayout</h3>
- <p>HTMLLayout outputs events in an HTML table. Each row of the table corresponds to an event.</p>
+ <p>HTMLLayout outputs events in an HTML table. Each row of the table corresponds to a
+ logging event.</p>
+
+ <p>Here is a sample of the output that can be obtained using <code>HTMLLayout</code>
+ along with the default CSS stylesheet:</p>
+ <img src="images/chapter5/htmlLayout1.gif" alt="HTML Layout Sample Image"/>
+
<p>
The content of the table columns are specified using a
conversion pattern. See <code>PatternLayout</code> for documentation on
- the available patterns.
+ the available patterns. This ensure that the user has full access to the creation
+ of the html table. One can choose to display any (or all) data that <code>PatternLayout</code>
+ can provide.
</p>
<p>One notable point about the use of <code>PatternLayout</code> with <code>HTMLLayout</code>
is that conversion specifiers should not be separated by a space. Each specifier found in the
@@ -1003,12 +1131,13 @@
</layout></pre></div>
<p>
- The HTMLLayout is often used in conjunction with
- SMTPAppender, to send a nicely formatted html email. Of
+ The <code>HTMLLayout</code> is often used in conjunction with
+ <code>SMTPAppender</code>, to send a nicely formatted html email. Of
course, it can be used with any other Appender.
</p>
<p>
- When one wants to use the HTMLLayout with a SMTPAppender,
+ When one wants to use the <code>HTMLLayout</code> with a
+ <code>SMTPAppender</code>,
the following configuration is typically used.
</p>
<div class="source"><pre><configuration>
@@ -1035,6 +1164,31 @@
IThrowableRenderer. It could be omitted, but is showed for
educationnal purposes.
</p>
+ <p>When <code>HTMLLayout</code> is used with any <code>FileAppender</code>,
+ one can specify the html page's title, simply by adding an element to the configuration,
+ as shown above:</p>
+
+<div class="source"><pre><configuration>
+ <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <ActiveFileName>lastLogEntries.html</ActiveFileName>
+ <FileNamePattern>lastLogEntries.%d{yyyy-MM-dd}.log</FileNamePattern>
+ </rollingPolicy>
+
+ <layout class="ch.qos.logback.classic.html.HTMLLayout">
+ <cssBuilder class="ch.qos.logback.core.helpers.CssBuilder">
+ <param name="url" value="path_to_StyleFile.css" />
+ </cssBuilder>
+ <Pattern>%relative%thread%mdc%level%logger%msg</Pattern>
+ <b><Title>Last Logging Events</Title></b>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration></pre></div>
<h2>Logback access</h2>
<p>Just like <code>ClassicLayout</code> represents the <code>Layout</code> interface
@@ -1051,6 +1205,12 @@
modules classic and access address pretty different needs, but offer the same power
and flexibility to the user.</p>
+ <h3>Writing your own Layout</h3>
+ <p>Writing a custom <code>Layout</code> for logback access works almost exactly the
+ same as writing such a component for the classic module.</p>
+ <p>The only exceptions comes from the fact that layouts in access module imlement
+ the <code>AccessLayout</code> interface instead <code>ClassicLayout</code>.</p>
+
<h3>PatternLayout</h3>
<p>Access' <code>PatternLayout</code> work the exact same way as it's classic counterpart.
</p>
More information about the logback-dev
mailing list