
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via f8c4d4ca4162fc0bdd311db2508ba58be7c0d3ba (commit) from c1ef0faaefee2012e6248bc871f1c237cbfbbd7d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=f8c4d4ca4162fc0bdd311db25... http://github.com/ceki/logback/commit/f8c4d4ca4162fc0bdd311db2508ba58be7c0d3... commit f8c4d4ca4162fc0bdd311db2508ba58be7c0d3ba Author: Ceki Gulcu <ceki@qos.ch> Date: Tue Jun 29 15:28:40 2010 +0200 - Fixed LBCLASSIC-213 ( Groovy runtime dependency problem with ReconfigureOnChangeFilter) - Fixed LBCLASSIC-214 - Preparing release 0.9.23 diff --git a/logback-access/pom.xml b/logback-access/pom.xml index 56782bf..12427fc 100644 --- a/logback-access/pom.xml +++ b/logback-access/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ch.qos.logback</groupId> <artifactId>logback-parent</artifactId> - <version>0.9.23-SNAPSHOT</version> + <version>0.9.23</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index ad232b3..26472d2 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ch.qos.logback</groupId> <artifactId>logback-parent</artifactId> - <version>0.9.23-SNAPSHOT</version> + <version>0.9.23</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy b/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy index 08d3c73..c1dfacb 100644 --- a/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy +++ b/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy @@ -28,7 +28,8 @@ import ch.qos.logback.core.Appender import ch.qos.logback.core.status.StatusListener import java.text.SimpleDateFormat import ch.qos.logback.classic.turbo.TurboFilter -import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.CoreConstants +import ch.qos.logback.core.util.ContextUtil; /** * @author Ceki Gücü @@ -38,7 +39,6 @@ public class ConfigurationDelegate extends ContextAwareBase { List<Appender> appenderList = []; - Object getDeclaredOrigin() { return this; } @@ -130,11 +130,6 @@ public class ConfigurationDelegate extends ContextAwareBase { appender.start(); } - - public void toto(String m) { - println "xxxxxxxxxxxxxxxxxxxx "+m; - } - private void copyContributions(AppenderDelegate appenderDelegate, Appender appender) { if(appender instanceof ConfigurationContributor) { ConfigurationContributor cc = (ConfigurationContributor) appender; diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java b/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java index 8958016..193a31d 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java @@ -39,5 +39,6 @@ public class ClassicConstants { public final static String REQUEST_QUERY_STRING = "req.queryString"; public final static String REQUEST_REQUEST_URL = "req.requestURL"; public final static String REQUEST_X_FORWARDED_FOR = "req.xForwardedFor"; - + + public final static String GAFFER_CONFIGURATOR_FQCN = "ch.qos.logback.classic.gaffer.GafferConfigurator"; } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/gaffer/GafferUtil.java b/logback-classic/src/main/java/ch/qos/logback/classic/gaffer/GafferUtil.java new file mode 100644 index 0000000..3ac1a81 --- /dev/null +++ b/logback-classic/src/main/java/ch/qos/logback/classic/gaffer/GafferUtil.java @@ -0,0 +1,82 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2010, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ +package ch.qos.logback.classic.gaffer; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; + +/** + * @author Ceki Gücü + */ +public class GafferUtil { + + private static String ERROR_MSG = "Failed to instantiate " + ClassicConstants.GAFFER_CONFIGURATOR_FQCN; + + public static void runGafferConfiguratorOn(LoggerContext loggerContext, Object origin, File configFile) { + GafferConfigurator gafferConfigurator = GafferUtil.newGafferConfiguratorInstance(loggerContext, origin); + if (gafferConfigurator != null) { + gafferConfigurator.run(configFile); + } + } + + public static void runGafferConfiguratorOn(LoggerContext loggerContext, Object origin, URL configFile) { + GafferConfigurator gafferConfigurator = GafferUtil.newGafferConfiguratorInstance(loggerContext, origin); + if (gafferConfigurator != null) { + gafferConfigurator.run(configFile); + } + } + + private static GafferConfigurator newGafferConfiguratorInstance(LoggerContext loggerContext, Object origin) { + + try { + Class gcClass = Class.forName(ClassicConstants.GAFFER_CONFIGURATOR_FQCN); + Constructor c = gcClass.getConstructor(LoggerContext.class); + GafferConfigurator gafferConfigurator = (GafferConfigurator) c.newInstance(loggerContext); + return gafferConfigurator; + } catch (ClassNotFoundException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (NoSuchMethodException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (InvocationTargetException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (InstantiationException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (IllegalAccessException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } + return null; + } + + private static void addError(LoggerContext context, Object origin, String msg) { + addError(context, origin, msg, null); + } + + private static void addError(LoggerContext context, Object origin, String msg, Throwable t) { + StatusManager sm = context.getStatusManager(); + if (sm == null) { + return; + } + sm.add(new ErrorStatus(msg, origin, t)); + } + + +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java b/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java index 3e840b7..7098ac6 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java @@ -45,7 +45,8 @@ public class MDCBasedDiscriminator extends ContextAwareBase implements * DefaultValue property. */ public String getDiscriminatingValue(ILoggingEvent event) { - String mdcValue = MDC.get(key); + // http://jira.qos.ch/browse/LBCLASSIC-213 + String mdcValue = event.getMdc().get(key); if (mdcValue == null) { return defaultValue; } else { diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java index 8aee404..7189586 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java @@ -17,7 +17,7 @@ import java.io.File; import java.net.URL; import java.net.URLDecoder; -import ch.qos.logback.classic.gaffer.GafferConfigurator; +import ch.qos.logback.classic.gaffer.GafferUtil; import ch.qos.logback.classic.util.EnvUtil; import ch.qos.logback.core.status.ErrorStatus; import ch.qos.logback.core.status.StatusManager; @@ -172,14 +172,11 @@ public class ReconfigureOnChangeFilter extends TurboFilter { if (fileToScan.toString().endsWith("groovy")) { if (EnvUtil.isGroovyAvailable()) { lc.reset(); - GafferConfigurator gafferConfigurator = new GafferConfigurator(lc); - gafferConfigurator.run(fileToScan); - lc.getStatusManager().add( - new InfoStatus("done resetting the logging context", this)); + // avoid directly referring to GafferConfigurator so as to avoid + // loading groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214 + GafferUtil.runGafferConfiguratorOn(lc, this, fileToScan); } else { - StatusManager sm = context.getStatusManager(); - sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.", - context)); + addError("Groovy classes are not available on the class path. ABORTING INITIALIZATION."); } } else if (fileToScan.toString().endsWith("xml")) { JoranConfigurator jc = new JoranConfigurator(); diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java b/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java index 0927830..30b3f69 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java @@ -22,6 +22,7 @@ import java.util.List; import ch.qos.logback.classic.BasicConfigurator; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.gaffer.GafferConfigurator; +import ch.qos.logback.classic.gaffer.GafferUtil; import ch.qos.logback.classic.joran.JoranConfigurator; import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.joran.spi.JoranException; @@ -61,8 +62,9 @@ public class ContextInitializer { } if (url.toString().endsWith("groovy")) { if (EnvUtil.isGroovyAvailable()) { - GafferConfigurator gafferConfigurator = new GafferConfigurator(loggerContext); - gafferConfigurator.run(url); + // avoid directly referring to GafferConfigurator so as to avoid + // loading groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214 + GafferUtil.runGafferConfiguratorOn(loggerContext, this, url); } else { StatusManager sm = loggerContext.getStatusManager(); sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.", diff --git a/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/GafferConfiguratorTest.groovy b/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/GafferConfiguratorTest.groovy index aadeaca..c36d936 100644 --- a/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/GafferConfiguratorTest.groovy +++ b/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/GafferConfiguratorTest.groovy @@ -131,9 +131,10 @@ class GafferConfiguratorTest { ConsoleAppender ca = (ConsoleAppender) root.getAppender("STDOUT"); assertTrue ca.isStarted() - + assertEquals("HELLO %m%n", ca.encoder.layout.pattern) } + @Test void propertyCascading1() { File file = new File(ClassicTestConstants.GAFFER_INPUT_PREFIX + "propertyCascading1.groovy") diff --git a/logback-classic/src/test/input/turbo/scan 1.groovy b/logback-classic/src/test/input/turbo/scan 1.groovy new file mode 100644 index 0000000..4384893 --- /dev/null +++ b/logback-classic/src/test/input/turbo/scan 1.groovy @@ -0,0 +1,6 @@ +import static ch.qos.logback.classic.Level.ERROR + +scan("50 millisecond") +root(ERROR) + + \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java index ac2d714..4259f26 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import ch.qos.logback.classic.gaffer.GafferConfigurator; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -50,6 +51,9 @@ public class ReconfigureOnChangeTest { final static String SCAN1_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/scan 1.xml"; + final static String G_SCAN1_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + + "turbo/scan 1.groovy"; + final static String SCAN_LBCLASSIC_154_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/scan_lbclassic154.xml"; @@ -90,6 +94,11 @@ public class ReconfigureOnChangeTest { jc.doConfigure(file); } + void gConfigure(File file) throws JoranException { + GafferConfigurator gc = new GafferConfigurator(loggerContext); + gc.run(file); + } + RunnableWithCounterAndDone[] buildRunnableArray(File configFile) { RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[THREAD_COUNT]; rArray[0] = new Updater(configFile); @@ -112,7 +121,6 @@ public class ReconfigureOnChangeTest { // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter @Test public void scan1() throws JoranException, IOException, InterruptedException { - System.out.println("***SCAN1"); File file = new File(SCAN1_FILE_AS_STR); configure(file); RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(file); @@ -125,6 +133,20 @@ public class ReconfigureOnChangeTest { verify(expectedRreconfigurations); } + @Test + public void gscan1() throws JoranException, IOException, InterruptedException { + File file = new File(G_SCAN1_FILE_AS_STR); + gConfigure(file); + RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(file); + harness.execute(runnableArray); + + loggerContext.getStatusManager().add( + new InfoStatus("end of execution ", this)); + + long expectedRreconfigurations = runnableArray[0].getCounter(); + verify(expectedRreconfigurations); + } + // check for deadlocks @Test(timeout = 20000) public void scan_lbclassic154() throws JoranException, IOException, diff --git a/logback-core/pom.xml b/logback-core/pom.xml index 222437c..b773910 100644 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ch.qos.logback</groupId> <artifactId>logback-parent</artifactId> - <version>0.9.23-SNAPSHOT</version> + <version>0.9.23</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java index fa13a0c..c088c55 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAware.java @@ -17,22 +17,27 @@ import ch.qos.logback.core.Context; import ch.qos.logback.core.status.Status; +/** + * An object which has a context and add methods for updating internal status messages. + */ public interface ContextAware { public void setContext(Context context); + public Context getContext(); - + public void addStatus(Status status); + public void addInfo(String msg); - + public void addInfo(String msg, Throwable ex); - + public void addWarn(String msg); - + public void addWarn(String msg, Throwable ex); - + public void addError(String msg); - - public void addError(String msg, Throwable ex); + + public void addError(String msg, Throwable ex); } diff --git a/logback-examples/pom.xml b/logback-examples/pom.xml index 627bdc6..04ecc5f 100644 --- a/logback-examples/pom.xml +++ b/logback-examples/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ch.qos.logback</groupId> <artifactId>logback-parent</artifactId> - <version>0.9.23-SNAPSHOT</version> + <version>0.9.23</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/logback-site/pom.xml b/logback-site/pom.xml index 6a03767..7fb8f5b 100644 --- a/logback-site/pom.xml +++ b/logback-site/pom.xml @@ -3,7 +3,7 @@ <parent> <groupId>ch.qos.logback</groupId> <artifactId>logback-parent</artifactId> - <version>0.9.23-SNAPSHOT</version> + <version>0.9.23</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/logback-site/src/site/pages/manual/configuration.html b/logback-site/src/site/pages/manual/configuration.html index 3fea8db..533ebef 100644 --- a/logback-site/src/site/pages/manual/configuration.html +++ b/logback-site/src/site/pages/manual/configuration.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter3: Logback configuration</title> + <title>Chapter 3: Configuration</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> diff --git a/logback-site/src/site/pages/manual/encoders.html b/logback-site/src/site/pages/manual/encoders.html index fcb07d4..237bfd9 100644 --- a/logback-site/src/site/pages/manual/encoders.html +++ b/logback-site/src/site/pages/manual/encoders.html @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter 4: Appenders</title> + <title>Chapter 5: Encoders</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/manual/filters.html b/logback-site/src/site/pages/manual/filters.html index 6340456..c3c59aa 100644 --- a/logback-site/src/site/pages/manual/filters.html +++ b/logback-site/src/site/pages/manual/filters.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter 6: Filters</title> + <title>Chapter 7: Filters</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/manual/groovy.html b/logback-site/src/site/pages/manual/groovy.html index 46e7f1d..f234f22 100644 --- a/logback-site/src/site/pages/manual/groovy.html +++ b/logback-site/src/site/pages/manual/groovy.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter3: Logback configuration</title> + <title>Chapter12: Groovy configuration</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> @@ -59,7 +59,7 @@ syntax. To help you migrate to Groovy style configuration, we have developped a <a href="http://logback.qos.ch/translator/asGroovy.html">tool to - automatically migrate your <em>logback.xml</em> files to + automatically migrate your existing<em>logback.xml</em> files to <em>logback.groovy</em></a>. </p> @@ -84,13 +84,17 @@ <p>Given that <em>logback.groovy</em> files are groovy programs with minimal logback-specific extensins, <em>all</em> the usual groovy constructs such as class imports, variable definitions, - if-else statements are avaiable in <em>logback.groovy</em> files.</p> + evaluation of ${..} expressions in a string (GStrings), if-else + statements are all avaiable in <em>logback.groovy</em> files.</p> - <p><em>Logback.groovy</em> syntax consists of half a dozen methods - described next in the reverse order of their customary - appearance. Strictly speaking, the order of invocation of these - methods does NOT matter, with one exception: appenders MUST be - defined before they can be attached to a logger.</p> + <h2>Extensions specific to <em>logback.groovy</em></h2> + + <p><span class="green">Essentially, <em>Logback.groovy</em> syntax + consists of half a dozen methods described next; in the reverse + order of their customary appearance. </span>Strictly speaking, the + order of invocation of these methods does NOT matter, with one + exception: appenders MUST be defined before they can be attached + to a logger.</p> <!-- ========================================================== --> @@ -105,14 +109,14 @@ <p>To set the level of the root logger to WARN, you would write:</p> - <pre class="prettyprint">import static ch.qos.logback.classic.Level.WARN + <pre class="prettyprint source">import static ch.qos.logback.classic.Level.WARN root(WARN)</pre> <p>To set the level of the root logger to DEBUG, and attach appenders named "CONSOLE" and "FILE" to root, you would write:</p> - <pre class="prettyprint">import static ch.qos.logback.classic.Level.INFO + <pre class="prettyprint source">import static ch.qos.logback.classic.Level.INFO root(INFO, ["CONSOLE", "FILE"])</pre> @@ -143,14 +147,14 @@ root(INFO, ["CONSOLE", "FILE"])</pre> <p>For example, the following script set the level of the "com.foo" logger to INFO.</p> - <pre class="prettyprint">import static ch.qos.logback.classic.Level.INFO + <pre class="prettyprint source">import static ch.qos.logback.classic.Level.INFO logger("com.foo", INFO)</pre> <p>The next script sets the level of the "com.foo" logger to DEBUG, and attaches the appender named "CONSOLE" to it.</p> - <pre class="prettyprint">import static ch.qos.logback.classic.Level.DEBUG + <pre class="prettyprint source">import static ch.qos.logback.classic.Level.DEBUG logger("com.foo", DEBUG, ["CONSOLE"])</pre> @@ -158,7 +162,7 @@ logger("com.foo", DEBUG, ["CONSOLE"])</pre> also sets the the additivity flag of the "com.foo" logger to false.</p> - <pre class="prettyprint">import static ch.qos.logback.classic.Level.DEBUG + <pre class="prettyprint source">import static ch.qos.logback.classic.Level.DEBUG logger("com.foo", DEBUG, ["CONSOLE"], false)</pre> @@ -189,7 +193,7 @@ logger("com.foo", DEBUG, ["CONSOLE"], false)</pre> %logger - %msg%n". The appender is then attached to the root logger.</p> - <pre class="prettyprint">import ch.qos.logback.classic.encoder.PatternLayoutEncoder + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder import ch.qos.logback.core.FileAppender import static ch.qos.logback.classic.Level.DEBUG @@ -208,7 +212,38 @@ root(DEBUG, ["FILE"])</pre> </p> - + <!-- ========================================================== --> + <h3>• <span class="code">timestamp(String datePattern)</span></h3> + + <p>The <code>timestamp()</code> method method returns a string + corresponding to the current time formatted according to + <code>datePattern</code> passed as parameter. The datePattern + parameter should follow the conventions defined by <a + href="http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html">SimpleDateFormat</a>. + </p> + + <p>In the next example, the <code>bySecond</code> variable is + assigned the current time in the "yyyyMMdd'T'HHmmss" format. The + bySecond variable is then used to define the value of the <span + class="option">file</span> property. + </p> + +<pre class="prettyprint source">import +ch.qos.logback.classic.encoder.PatternLayoutEncoder import +ch.qos.logback.core.FileAppender + +import static ch.qos.logback.classic.Level.DEBUG + +<b>def bySecond = timestamp("yyyyMMdd'T'HHmmss")</b> + +appender("FILE", FileAppender) { + <b>file = "log-${bySecond}.txt"</b> + encoder(PatternLayoutEncoder) { + pattern = "%logger{35} - %msg%n" + } +} +root(DEBUG, ["FILE"])</pre> + <!-- ========================================================== --> <h3>• <span class="code">conversionRule(String conversionWord, Class converterClass)</span></h3> @@ -220,7 +255,7 @@ root(DEBUG, ["FILE"])</pre> word is encountered. </p> - <pre class="prettyprint"> + <pre class="prettyprint source"> import ch.qos.logback.classic.encoder.PatternLayoutEncoder import ch.qos.logback.core.ConsoleAppender import chapters.layouts.MySampleConverter @@ -242,7 +277,7 @@ root(DEBUG, ["STDOUT"])</pre> scan the logback.groovy file for changes. Whenever a change is detected, the <em>logback.groovy</em> file is reloaded.</p> - <pre class="prettyprint">scan()</pre> + <pre class="prettyprint source">scan()</pre> <p>By default, the configuration file will be scanned for changes once every minute. You can specify a different scanning period by @@ -251,7 +286,7 @@ root(DEBUG, ["STDOUT"])</pre> example: </p> - <pre class="prettyprint">scan("30 seconds")</pre> + <pre class="prettyprint source">scan("30 seconds")</pre> <p>If no unit of time is specified, then the unit of time is assumed to be milliseconds, which is usually inappropriate. If you @@ -269,13 +304,219 @@ root(DEBUG, ["STDOUT"])</pre> <code>statusListener</code> method and passing a listener class as an argument. Here is an example:</p> - <pre class="prettyprint">import ch.qos.logback.core.status.OnConsoleStatusListener + <pre class="prettyprint source">import ch.qos.logback.core.status.OnConsoleStatusListener -statusListener(OnConsoleStatusListener)</pre> +<b>// We highly recommended that you always add a status listener just</b> +<b>// after the last import statement and before all other statements</b> +<b>statusListener(OnConsoleStatusListener)</b></pre> <p><a href="configuration.html#statusListener">Status listeners</a> were described in an earlier chapter.</p> + + + <!-- ========================================================== --> + + <h2>Internal DSL, i.e. it's all groovy baby!</h2> + + <p>The <em>logback.groovy</em> is an internal DSL meaning that its + contents are executed as a groovy script. Thus, all the usual + groovy constructs such as class imports, GString, variable + definitions, evaluation of ${..} expressions in a string + (GStrings), if-else statements are all avaiable in logback.groovy + files. In the following discussion, we will present typical uses + of these groovy constructs in <em>logback.groovy</em> files. + </p> + + + <h3>Variable definitions and GStrings</h3> + + <p>You can define variables anywhere within a + <em>logback.groovy</em> files, then use the variable within a + GString. Here is an example.</p> + + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.core.FileAppender + +import static ch.qos.logback.classic.Level.DEBUG + + +// define the USER_HOME variable setting its value +// to that of the "user.home" system property +<b>def USER_HOME = System.getProperty("user.home")</b> + +appender("FILE", FileAppender) { + // make use of the USER_HOME variable + <b>file = "${USER_HOME}/myApp.log"</b> + encoder(PatternLayoutEncoder) { + pattern = "%msg%n" + } +} +root(DEBUG, ["FILE"])</pre> + + + <h3>Printing on the console</h3> + + <p>You can invoke the println method to print on the console. Here + is an example.</p> + + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.core.FileAppender + +import static ch.qos.logback.classic.Level.DEBUG + +def USER_HOME = System.getProperty("user.home"); +<b>println "USER_HOME=${USER_HOME}"</b> + +appender("FILE", FileAppender) { + <b>println "Setting [file] property to [${USER_HOME}/myApp.log]"</b> + file = "${USER_HOME}/myApp.log" + encoder(PatternLayoutEncoder) { + pattern = "%msg%n" + } +} +root(DEBUG, ["FILE"])</pre> + + + <h3>Automatically exported fields</h3> + + <p>The 'hostname' variable contains the name of the current + host. However, due to scoping rules that the authors cannot fully + explain, the 'hostname' variable is available only at the topmost + scope but not in nested scopes. The next example should get the + point across. + </p> + + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.core.ConsoleAppender + +import static ch.qos.logback.classic.Level.DEBUG + +// will print "hostname is x" where x is the current host's name +println "Hostname is ${hostname}" + +appender("STDOUT", ConsoleAppender) { + <b>// will print "hostname is null"</b> + <b>println "Hostname is ${hostname}" </b> +}</pre> + + <p>If you wish to have the hostname variable be seen in all scopes, + you need to define another variable and assign it the value of + 'hostname' as shown next.</p> + + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.core.ConsoleAppender + +import static ch.qos.logback.classic.Level.DEBUG + +// define HOSTNAME by assigning it hostname +def HOSTNAME=hostname +// will print "hostname is x" where x is the current host's name +println "Hostname is ${HOSTNAME}" + +appender("STDOUT", ConsoleAppender) { + // will print "hostname is x" where x is the current host's name + println "Hostname is ${HOSTNAME}" +}</pre> + + + <h3>Everything is context aware with a reference to the current + context</h3> + + <p>The execution of the logback.grooy script is done within a scope + of a <a + href="../xref/ch/qos/logback/core/spi/ContextAware.html">ContextAware</a> + object. Thus, the current context is always accessible using the + '<code>context</code>' variable and you can add status messages + using <code>addInfo</code>(), <code>addWarn</code> and addError + methods.</p> + + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.core.FileAppender +import ch.qos.logback.core.status.OnConsoleStatusListener + +import static ch.qos.logback.classic.Level.DEBUG + +// always a good idea to add an on console status listener +statusListener(OnConsoleStatusListener) + +// set the context's name to wombat +<b>context.name = "wombat"</b> +// add a status message regarding context's name +<b>addInfo("Context name has been set to ${context.name}")</b> + +def USER_HOME = System.getProperty("user.home"); +// add a status message regarding USER_HOME +<b>addInfo("USER_HOME=${USER_HOME}")</b> + +appender("FILE", FileAppender) { + // add a status message regarding the file property + <b>addInfo("Setting [file] property to [${USER_HOME}/myApp.log]")</b> + file = "${USER_HOME}/myApp.log" + encoder(PatternLayoutEncoder) { + pattern = "%msg%n" + } +} +root(DEBUG, ["FILE"])</pre> + + + <h3>Conditional configuration</h3> + + <p>Given that Groovy is a fully-fledged programming language, + conditional statements allow for a single logback.groovy file to + adapt to various environments such as development, testing or + production.</p> + + <p>In the next script, a console appender is activated on hosts + other than pixie or orion, our production machines. Note that the + output directory of the rolling file appender also depends on the + host.</p> + + <pre class="prettyprint source">import ch.qos.logback.classic.encoder.PatternLayoutEncoder +import ch.qos.logback.core.rolling.RollingFileAppender +import ch.qos.logback.core.rolling.TimeBasedRollingPolicy +import ch.qos.logback.core.ConsoleAppender +import ch.qos.logback.core.status.OnConsoleStatusListener + +import static ch.qos.logback.classic.Level.INFO + +// always a good idea to add an on console status listener +statusListener(OnConsoleStatusListener) + +def appenderList = ["ROLLING"] +def WEBAPP_DIR = "." +def consoleAppender = true; + +// does hostname match pixie or orion? +if (hostname =~ /pixie|orion/) { + WEBAPP_DIR = "/opt/myapp" + consoleAppender = false +} else { + appenderList.add("CONSOLE") +} + +if (consoleAppender) { + appender("CONSOLE", ConsoleAppender) { + encoder(PatternLayoutEncoder) { + pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" + } + } +} + +appender("ROLLING", RollingFileAppender) { + encoder(PatternLayoutEncoder) { + Pattern = "%d %level %thread %mdc %logger - %m%n" + } + rollingPolicy(TimeBasedRollingPolicy) { + FileNamePattern = "${WEBAPP_DIR}/log/translator-%d{yyyy-MM}.zip" + } +} + +root(INFO, appenderList)</pre> + + + + <script src="../templates/footer.js" type="text/javascript"></script> </div> diff --git a/logback-site/src/site/pages/manual/jmxConfig.html b/logback-site/src/site/pages/manual/jmxConfig.html index 13bddfa..67ac974 100644 --- a/logback-site/src/site/pages/manual/jmxConfig.html +++ b/logback-site/src/site/pages/manual/jmxConfig.html @@ -10,7 +10,7 @@ <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> <link rel="stylesheet" type="text/css" href="../css/prettify.css" media="screen" /> - <title>JMX Configuration</title> + <title>Chapter 10: JMX Configuration</title> </head> <body onload="prettyPrint()"> <script type="text/javascript">prefix='../';</script> diff --git a/logback-site/src/site/pages/manual/layouts.html b/logback-site/src/site/pages/manual/layouts.html index 23e5bfc..ccee3c3 100644 --- a/logback-site/src/site/pages/manual/layouts.html +++ b/logback-site/src/site/pages/manual/layouts.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter 5: Layouts</title> + <title>Chapter 6: Layouts</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/manual/loggingSeparation.html b/logback-site/src/site/pages/manual/loggingSeparation.html index 5b84bfa..17f6b54 100644 --- a/logback-site/src/site/pages/manual/loggingSeparation.html +++ b/logback-site/src/site/pages/manual/loggingSeparation.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter 8: Context Selector</title> + <title>Chapter 9: Logging separation</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/manual/mdc.html b/logback-site/src/site/pages/manual/mdc.html index 08ed8ec..9e24ced 100644 --- a/logback-site/src/site/pages/manual/mdc.html +++ b/logback-site/src/site/pages/manual/mdc.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Chapter 7: Diagnostic Context</title> + <title>Chapter 8: Mapped Diagnostic Context</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/manual/migrationFromLog4j.html b/logback-site/src/site/pages/manual/migrationFromLog4j.html index dfc948d..5d5fe00 100644 --- a/logback-site/src/site/pages/manual/migrationFromLog4j.html +++ b/logback-site/src/site/pages/manual/migrationFromLog4j.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Migration from log4j</title> + <title>Chapter 13: Migration from log4j</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/manual/onJoran.html b/logback-site/src/site/pages/manual/onJoran.html index 5eba56f..0060d72 100644 --- a/logback-site/src/site/pages/manual/onJoran.html +++ b/logback-site/src/site/pages/manual/onJoran.html @@ -4,7 +4,7 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> - <title>Joran</title> + <title>Chapter 11: Joran</title> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" /> diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index f2b7071..459abc4 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -26,8 +26,22 @@ the <a href="http://www.qos.ch/mailman/listinfo/announce">QOS.ch announce</a> mailing list.</p> + <hr width="80%" align="center" /> + + <h3>June 29th, 2010 - Release of version 0.9.23</h3> + + <p>Fixed Groovy runtime dependency problem with + ReconfigureOnChangeFilter, i.e. the auto-scan filter, when using + non-groovy configuration files. This problem was reported in <a + href="http://jira.qos.ch/browse/LBCLASSIC-214">LBCLASSIC-214</a> + by Alvin Chee.</p> - <hr width="80%" align="center" /> + <p>Fixed MDCBasedDiscriminator so that it supports deferred + processing. This issue was reported in <a + href="http://jira.qos.ch/browse/LBCLASSIC-213">LBCLASSIC-213</a> + by Torsten Juergeleit.</p> + + <hr width="80%" align="center" /> <h3>June 21st, 2010 - Release of version 0.9.22</h3> diff --git a/logback-site/src/site/pages/templates/creative.js b/logback-site/src/site/pages/templates/creative.js index 68ade79..555b746 100644 --- a/logback-site/src/site/pages/templates/creative.js +++ b/logback-site/src/site/pages/templates/creative.js @@ -5,7 +5,7 @@ document.write(' <td> '); document.write(' <p class="author">'); document.write(' Authors: Ceki Gülcü, Sébastien Pennec'); document.write(' <br/>'); -document.write(' Copyright © 2000-2009, QOS.ch</p>'); +document.write(' Copyright © 2000-2010, QOS.ch</p>'); document.write(' </td>'); document.write(' <td>'); document.write(' <a rel="license"'); diff --git a/pom.xml b/pom.xml index 5915215..508b5f3 100755 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <groupId>ch.qos.logback</groupId> <artifactId>logback-parent</artifactId> - <version>0.9.23-SNAPSHOT</version> + <version>0.9.23</version> <packaging>pom</packaging> <name>Logback-Parent</name> ----------------------------------------------------------------------- Summary of changes: logback-access/pom.xml | 2 +- logback-classic/pom.xml | 2 +- .../classic/gaffer/ConfigurationDelegate.groovy | 9 +- .../ch/qos/logback/classic/ClassicConstants.java | 3 +- .../ch/qos/logback/classic/gaffer/GafferUtil.java | 82 ++++++ .../classic/sift/MDCBasedDiscriminator.java | 3 +- .../classic/turbo/ReconfigureOnChangeFilter.java | 13 +- .../logback/classic/util/ContextInitializer.java | 6 +- .../classic/gaffer/GafferConfiguratorTest.groovy | 3 +- logback-classic/src/test/input/turbo/scan 1.groovy | 6 + .../classic/turbo/ReconfigureOnChangeTest.java | 24 ++- logback-core/pom.xml | 2 +- .../java/ch/qos/logback/core/spi/ContextAware.java | 19 +- logback-examples/pom.xml | 2 +- logback-site/pom.xml | 2 +- .../src/site/pages/manual/configuration.html | 2 +- logback-site/src/site/pages/manual/encoders.html | 2 +- logback-site/src/site/pages/manual/filters.html | 2 +- logback-site/src/site/pages/manual/groovy.html | 281 ++++++++++++++++++-- logback-site/src/site/pages/manual/jmxConfig.html | 2 +- logback-site/src/site/pages/manual/layouts.html | 2 +- .../src/site/pages/manual/loggingSeparation.html | 2 +- logback-site/src/site/pages/manual/mdc.html | 2 +- .../src/site/pages/manual/migrationFromLog4j.html | 2 +- logback-site/src/site/pages/manual/onJoran.html | 2 +- logback-site/src/site/pages/news.html | 16 +- logback-site/src/site/pages/templates/creative.js | 2 +- pom.xml | 2 +- 28 files changed, 432 insertions(+), 65 deletions(-) create mode 100644 logback-classic/src/main/java/ch/qos/logback/classic/gaffer/GafferUtil.java create mode 100644 logback-classic/src/test/input/turbo/scan 1.groovy hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework.