logback-dev
Threads by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- 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
- 9940 discussions
svn commit: r2096 - in logback/trunk: logback-access/src/main/java/ch/qos/logback/access/sift logback-access/src/test/input/jetty logback-classic/src/main/java/ch/qos/logback/classic/sift logback-examples/src/main/java/chapter4/sift logback-site/src/site/pages/manual
by noreply.cekiļ¼ qos.ch 23 Dec '08
by noreply.cekiļ¼ qos.ch 23 Dec '08
23 Dec '08
Author: ceki
Date: Tue Dec 23 19:17:20 2008
New Revision: 2096
Added:
logback/trunk/logback-examples/src/main/java/chapter4/sift/
logback/trunk/logback-examples/src/main/java/chapter4/sift/SiftExample.java
logback/trunk/logback-examples/src/main/java/chapter4/sift/byUserid.xml
Modified:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
logback/trunk/logback-site/src/site/pages/manual/appenders.html
Log:
Documenting SiftingAppender
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java Tue Dec 23 19:17:20 2008
@@ -16,16 +16,27 @@
import ch.qos.logback.core.sift.Discriminator;
import ch.qos.logback.core.spi.ContextAwareBase;
+/**
+ *
+ * AccessEventDiscriminator's job is to return the value of a designated field in
+ * an {@link AccessEvent} instance.
+ *
+ * <p>The field is specified via the {@link FieldName} property.
+
+ * @author Ceki Gülcü
+ *
+ */
public class AccessEventDiscriminator extends ContextAwareBase implements
Discriminator<AccessEvent> {
boolean started = false;
/**
- * Allowed field names are: COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE,
- * REMOTE_ADDRESS, LOCAL_PORT,REQUEST_URI
+ * At present time the followed fields can be designated:
+ * COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS,
+ * LOCAL_PORT,REQUEST_URI
*
- * <p> The first three field names require a key attribute.
+ * <p> The first three fields require an additional key.
*/
public enum FieldName {
COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI
@@ -34,7 +45,7 @@
String defaultValue;
String key;
FieldName fieldName;
- String optionalKey;
+ String additionalKey;
public String getDiscriminatingValue(AccessEvent acccessEvent) {
String rawValue = getRawDiscriminatingValue(acccessEvent);
@@ -48,11 +59,11 @@
public String getRawDiscriminatingValue(AccessEvent acccessEvent) {
switch (fieldName) {
case COOKIE:
- return acccessEvent.getCookie(optionalKey);
+ return acccessEvent.getCookie(additionalKey);
case LOCAL_PORT:
return String.valueOf(acccessEvent.getLocalPort());
case REQUEST_ATTRIBUTE:
- return acccessEvent.getAttribute(optionalKey);
+ return acccessEvent.getAttribute(additionalKey);
case SESSION_ATTRIBUTE:
return getSessionAttribute(acccessEvent);
case REMOTE_ADDRESS:
@@ -78,7 +89,7 @@
if (req != null) {
HttpSession session = req.getSession(false);
if (session != null) {
- Object v = session.getAttribute(optionalKey);
+ Object v = session.getAttribute(additionalKey);
if (v != null) {
return v.toString();
}
@@ -107,7 +118,7 @@
case SESSION_ATTRIBUTE:
case REQUEST_ATTRIBUTE:
case COOKIE:
- if (optionalKey == null) {
+ if (additionalKey == null) {
addError("\"OptionalKey\" property is mandatory for field name "+fieldName.toString());
errorCount++;
}
@@ -130,15 +141,15 @@
return fieldName;
}
- public String getOptionalKey() {
- return optionalKey;
+
+ public String getAdditionalKey() {
+ return additionalKey;
}
- public void setOptionalKey(String optionalKey) {
- this.optionalKey = optionalKey;
+ public void setAdditionalKey(String additionalKey) {
+ this.additionalKey = additionalKey;
}
-
/**
* @see #setDefaultValue(String)
* @return
Modified: logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml
==============================================================================
--- logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml (original)
+++ logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml Tue Dec 23 19:17:20 2008
@@ -3,6 +3,7 @@
<appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
<KeyName>client</KeyName>
<Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+ <Key>client</Key>
<DefaultValue>NA</DefaultValue>
<FieldName>REQUEST_URI</FieldName>
</Discriminator>
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java Tue Dec 23 19:17:20 2008
@@ -16,16 +16,30 @@
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.util.OptionHelper;
-public class MDCBasedDiscriminator extends ContextAwareBase implements Discriminator<LoggingEvent> {
-
- String key;
- String defaultValue;
-
- boolean started = false;
+/**
+ * MDCBasedDiscriminator essentially returns the value mapped to an MDC key. If
+ * the said value is null, then a default value is returned.
+ *
+ * <p>Both Key and the DefaultValue are user specified properties.
+ *
+ * @author Ceki Gülcü
+ *
+ */
+public class MDCBasedDiscriminator extends ContextAwareBase implements
+ Discriminator<LoggingEvent> {
+
+ private String key;
+ private String defaultValue;
+ private boolean started = false;
public MDCBasedDiscriminator() {
}
+ /**
+ * Return the value associated with an MDC entry desginated by the Key
+ * property. If that value is null, then return the value assigned to the
+ * DefaultValue property.
+ */
public String getDiscriminatingValue(LoggingEvent event) {
String mdcValue = MDC.get(key);
if (mdcValue == null) {
@@ -76,18 +90,15 @@
/**
* The default MDC value in case the MDC is not set for
- * {@link #setMdcKey(String) mdcKey}.
+ * {@link #setKey(String) mdcKey}.
*
- * <p> For example, if {@link #setMdcKey(String) mdcKey} is set to the value
+ * <p> For example, if {@link #setKey(String) Key} is set to the value
* "someKey", and the MDC is not set for "someKey", then this appender will
- * use the default value, which you can set with the help of method.
+ * use the default value, which you can set with the help of this method.
*
* @param defaultValue
*/
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
-
-
-
}
Added: logback/trunk/logback-examples/src/main/java/chapter4/sift/SiftExample.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter4/sift/SiftExample.java Tue Dec 23 19:17:20 2008
@@ -0,0 +1,51 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package chapter4.sift;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+
+public class SiftExample {
+
+ public static void main(String[] args) throws JoranException {
+ if (args.length != 1) {
+ usage("Wrong number of arguments.");
+ }
+
+ String configFile = args[0];
+
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+ JoranConfigurator configurator = new JoranConfigurator();
+ lc.reset();
+ configurator.setContext(lc);
+ configurator.doConfigure(configFile);
+
+
+ Logger logger = LoggerFactory.getLogger(SiftExample.class);
+ logger.debug("Application started");
+
+ MDC.put("userid", "Alice");
+ logger.debug("Alice says hello");
+
+ //StatusPrinter.print(lc);
+ }
+
+ static void usage(String msg) {
+ System.err.println(msg);
+ System.err.println("Usage: java " + SiftExample.class.getName()
+ + " configFile\n" + " configFile a logback configuration file");
+ System.exit(1);
+ }
+}
Added: logback/trunk/logback-examples/src/main/java/chapter4/sift/byUserid.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter4/sift/byUserid.xml Tue Dec 23 19:17:20 2008
@@ -0,0 +1,21 @@
+<configuration>
+ <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
+ <discriminator>
+ <Key>userid</Key>
+ <DefaultValue>unknown</DefaultValue>
+ </discriminator>
+ <sift>
+ <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
+ <File>${userid}.log</File>s
+ <Append>false</Append>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</Pattern>
+ </layout>
+ </appender>
+ </sift>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="SIFT" />
+ </root>
+</configuration>
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 Tue Dec 23 19:17:20 2008
@@ -3067,27 +3067,227 @@
deny requests coming via a network connection.
</p>
+
+ <h3><a name="SiftingAppender"
+ href="#SiftingAppender">SiftingAppender</a></h3>
+
+ <p>As its name implies, a <code>SiftingAppender</code> can be used
+ to separate (or sift) logging according to some runtime attribute.
+ For example, <code>SiftingAppender</code> can separate logging
+ events into distinct log files, one file per user.
+ </p>
+
+
+ <p><code>SiftingAppender</code> embeds and manages multiple
+ appenders which it builds dynamically depending on discriminating
+ values. The built appender is specified in a configuration file
+ within the <code>SiftingAppender</code> definition itself. By
+ default, <code>SiftingAppender</code> uses MDC key/value pairs as
+ a discriminator.
+ </p>
+
+ <p>After configuring logback, the <a
+ href="../xref/chapter4/sift/SiftExample.html">SiftExample</a>
+ application logs a message stating that the application has
+ started. It then sets the MDC key "userid" to "Alice" and logs a
+ message. Here is the salient code:</p>
+
+ <p class="source">logger.debug("Application started");
+MDC.put("userid", "Alice");
+logger.debug("Alice says hello"); </p>
+
+ <p>The next configuration file illustrates the use of
+ <code>SiftingAppender</code>.</p>
+
+
+ <em>Example 4.<span class="autoEx"/>: <code>SiftingAppender</code>
+ configuration
+ (logback-examples/src/main/java/chapter4/sift/byUserid.xml)</em>
+
+ <p class="source"><configuration>
+
+ <b><appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender"></b>
+ <!-- in the absence of the class attribute, it is assumed that the
+ desired discriminator type is
+ ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
+ <b><discriminator></b>
+ <b><Key><span class="green">userid</span></Key></b>
+ <b><DefaultValue>unknown</DefaultValue></b>
+ <b></discriminator></b>
+ <b><sift></b>
+ <b><appender name="FILE-<span class="green">${userid}</span>" class="ch.qos.logback.core.FileAppender"></b>
+ <b><File><span class="green">${userid}</span>.log</File></b>
+ <b><Append>false</Append></b>
+ <b><layout class="ch.qos.logback.classic.PatternLayout"></b>
+ <b><Pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</Pattern></b>
+ <b></layout></b>
+ <b></appender></b>
+ <b></sift></b>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="SIFT" />
+ </root>
+</configuration></p>
+
+
+ <p>In the absence of a class attribute, it is assumed that the
+ discriminator type is <a
+ href="xref/ch/qos/logback/classic/sift/MDCBasedDiscriminator.html">MDCBasedDiscriminator</a>. It
+ will use the MDC value associated with the <span
+ class="option">Key</span> property as a districimator. If that
+ value is null, then the value associated with the <span
+ class="option">DefaultValue</span> property will be used.
+ </p>
+
+ <p>The <code>SiftingAppender</code> is unique in its capacity to
+ reference and configure nested appenders. In the above example,
+ within the <code>SiftingAppender</code> there will be nested
+ FileAppender instances, each instance identified by the value
+ associated with the "userid" MDC key. Whenever the "userid" MDC
+ key is assigned a new value, a new <code>FileAppender</code>
+ instance will be built from scratch. The SiftingAppender keeps
+ track of the appenders it creates. Appenders unused for 30 minutes
+ will be automatically closed and discarded.
+ </p>
+
+ <p>It is not enough to have different appender instances, each
+ instance must output to a distinct target resource. To allow such
+ differentiation, within the nested appender (FileAppender above),
+ the key passed to the discriminator, "userid" in the above
+ example, becomes a <a
+ href="joran.html#variableSubstitution">variable</a>. Consequently,
+ this variable can be used to differentiate the actual resource
+ used by a given nested appender.
+ </p>
+
+ <p>Running <code>SiftExample</code> application with the
+ "byUserid.xml" configuration file shown above, will result in two
+ distinct log files, "unknown.log" and "Alice.log".
+ </p>
+
+
+ <h3><a name="WriteYourOwnAppender"
+ href="#WriteYourOwnAppender">Writing your own Appender</a></h3>
+
+
+ <p>You can easily write your appender by sub-classing <code>AppenderBase</code>.
+ It handles support for filters, status among other functionality shared by most appenders.
+ The derived class only needs to implement one method, namely
+ <code>append(Object eventObject)</code>.
+ </p>
+
+ <p>The <code>CountingConsoleAppender</code>, which we list next, appends a limited
+ number of incoming events on the console. It shuts down after the limit is reached.
+ It uses a <code>Layout</code> to format the events and accepts a parameter,
+ thus a few more methods are needed.
+ </p>
+
+ <em>Example 4.<span class="autoExec"/>: <code>CountingConsoleAppender</code> (logback-examples/src/main/java/chapter4/CountingConsoleAppender.java)</em>
+ <p class="source">package chapter4;
+
+import ch.qos.logback.core.AppenderBase;
+import ch.qos.logback.core.Layout;
+
+
+public class CountingConsoleAppender extends AppenderBase<LoggingEvent> {
+ static int DEFAULT_LIMIT = 16;
+ int counter = 0;
+ int limit = DEFAULT_LIMIT;
+
+ private Layout<LoggingEvent> layout;
+
+ public CountingConsoleAppender() {
+ }
+
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+ public int getLimit() {
+ return limit;
+ }
+
+ @Override
+ public void start() {
+ if (this.layout == null) {
+ addError("No layout set for the appender named ["+ name +"].");
+ return;
+ }
+
+ super.start();
+ }
+
+ public void append(LoggingEvent event) {
+
+ if (counter >= limit) {
+ return;
+ }
+
+ // output the events as formatted by our layout
+ System.out.print(this.layout.doLayout(event));
+
+ // prepare for next event
+ counter++;
+ }
+
+ public Layout<LoggingEvent> getLayout() {
+ return layout;
+ }
+
+ public void setLayout(Layout<LoggingEvent> layout) {
+ this.layout = layout;
+ }
+}</p>
+
+ <p>The <code>start()</code> method checks for the presence of a
+ <code>Layout</code>. In case none is found, the appender is not
+ started.
+ </p>
- <a name="Access"></a>
- <h2>Logback Access</h2>
+ <p>This custom appender illustrates a two points:
+ </p>
- <p>Most of the appenders found in logback classic can be used
- within logback access. They function mostly in the same way as
- their logback classic counterpart. In the next section, we will
- cover their use, but will focuse on the differences with the
- classic appenders.
+ <ul>
+ <li>All properties that follow the setter/getter JavaBeans
+ conventions are handled transparently. The <code>start()</code>
+ method, that is called automatically, has the responsability to
+ check that the given properties are coherent.
+ </li>
+ <li>The <code>AppenderBase.doAppend()</code> method invokes the
+ append() method of its derived classes where actual output
+ operations occur. It is in this method that appenders format
+ events by invoking their layouts.
+ </li>
+ </ul>
+
+ <p>The <code>CountingConsoleAppender</code> can be configured like
+ any appender. See sample file
+ <em>logback-examples/src/main/java/chapter4/countingConsole.xml</em>
+ for an example.
+ </p>
+
+
+ <h2><a name="logback_access" href="#logback_access">Logback
+ Access</a></h2>
+
+ <p>Most of the appenders found in logback-classic have their
+ equivalent in logback-access. These work essentialy in the same
+ way as their locback-classic counterparts. In the next section, we
+ will cover their use.
</p>
<a name="AccessSocketAppender"/>
<h3>SocketAppender</h3>
- <p>
- The <a href="../xref/ch/qos/logback/access/net/SocketAppender.html">
- <code>SocketAppender</code></a> is designed to log to a
- remote entity by transmitting serialized <code>AccessEvent</code> objects over the wire.
- Remote logging is non-intrusive as far as the access event is concerned.
- On the receiving end after de-serialization, the event can be logged as
- if it were generated locally.
+ <p>The <a
+ href="../xref/ch/qos/logback/access/net/SocketAppender.html">
+ <code>SocketAppender</code></a> is designed to log to a remote
+ entity by transmitting serialized <code>AccessEvent</code> objects
+ over the wire. Remote logging is non-intrusive as far as the
+ access event is concerned. On the receiving end after
+ de-serialization, the event can be logged as if it were generated
+ locally.
</p>
<p>
The properties of access' <code>SocketAppender</code> are the same as those available
@@ -3280,7 +3480,7 @@
</p>
<em>Example 4.<span class="autoEx"/>: DBAppender configuration (logback-examples/src/main/java/chapter4/conf/access/logback-DB.xml)</em>
-<div class="source"><pre><configuration>
+ <p class="source"><configuration>
<appender name="DB" class="ch.qos.logback.access.db.DBAppender">
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
@@ -3293,110 +3493,32 @@
</appender>
<appender-ref ref="DB" />
-</configuration></pre></div>
-
-
- <a name="WriteYourOwnAppender"></a>
- <h2>Writing your own Appender</h2>
+</configuration></p>
- <p>You can easily write your appender by sub-classing <code>AppenderBase</code>.
- It handles support for filters, status among other functionality shared by most appenders.
- The derived class only needs to implement one method, namely
- <code>append(Object eventObject)</code>.
+ <h3><a name="AccessSiftingAppender"
+ href="#AccessSiftingAppender">SiftingAppender</a></h3>
+
+ <p>The SiftingAppender in logback-access is quite similar to its
+ logbacl-classic counterpart. The main difference is that in
+ logback-access the default discriminator, namely <a
+ href="../xref/ch/qos/logback/access/sift/AccessEventDiscriminator.html">AccessEventDiscriminator</a>,
+ is not MDC based. As its name suggests, AccessEventDiscriminator,
+ uses a designated field in AccessEvent as basis for selecting a
+ nested appender. If the value of the designated field is null,
+ then the value specified in the <span
+ class="option">DefaultValue</span> property is used.
</p>
- <p>The <code>CountingConsoleAppender</code>, which we list next, appends a limited
- number of incoming events on the console. It shuts down after the limit is reached.
- It uses a <code>Layout</code> to format the events and accepts a parameter,
- thus a few more methods are needed.
- </p>
+ <p>The desginated AccessEvent field can be one of COOKIE,
+ REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT,
+ REQUEST_URI. Note that the fiest three fields require that the
+ <span class="option">AdditionalKey</span> property to be
+ specified.</p>
- <em>Example 4.<span class="autoExec"/>: <code>CountingConsoleAppender</code> (logback-examples/src/main/java/chapter4/CountingConsoleAppender.java)</em>
- <p class="source">package chapter4;
-import ch.qos.logback.core.AppenderBase;
-import ch.qos.logback.core.Layout;
-public class CountingConsoleAppender extends AppenderBase<LoggingEvent> {
- static int DEFAULT_LIMIT = 16;
- int counter = 0;
- int limit = DEFAULT_LIMIT;
-
- private Layout<LoggingEvent> layout;
-
- public CountingConsoleAppender() {
- }
-
- public void setLimit(int limit) {
- this.limit = limit;
- }
-
- public int getLimit() {
- return limit;
- }
-
- @Override
- public void start() {
- if (this.layout == null) {
- addError("No layout set for the appender named ["+ name +"].");
- return;
- }
-
- super.start();
- }
-
- public void append(LoggingEvent event) {
-
- if (counter >= limit) {
- return;
- }
-
- // output the events as formatted by our layout
- System.out.print(this.layout.doLayout(event));
-
- // prepare for next event
- counter++;
- }
-
- public Layout<LoggingEvent> getLayout() {
- return layout;
- }
-
- public void setLayout(Layout<LoggingEvent> layout) {
- this.layout = layout;
- }
-}</p>
-
- <p>The <code>start()</code> method checks for the presence of a
- <code>Layout</code>. In case none is found, the appender is not
- started.
- </p>
-
- <p>This custom appender illustrates a two points:
- </p>
-
- <ul>
- <li>All properties that follow the setter/getter JavaBeans
- conventions are handled transparently. The <code>start()</code>
- method, that is called automatically, has the responsability to
- check that the given properties are coherent.
- </li>
- <li>The <code>AppenderBase.doAppend()</code> method invokes the
- append() method of its derived classes where actual output
- operations occur. It is in this method that appenders format
- events by invoking their layouts.
- </li>
- </ul>
-
- <p>The <code>CountingConsoleAppender</code> can be configured like
- any appender. See sample file
- <em>logback-examples/src/main/java/chapter4/countingConsole.xml</em>
- for an example.
- </p>
-
-
<script src="../templates/footer.js" type="text/javascript"></script>
1
0
Author: ceki
Date: Mon Dec 22 23:18:36 2008
New Revision: 2095
Added:
logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java
Modified:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java
logback/trunk/logback-access/src/test/input/jetty/sifting.xml
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml
logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml
logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java
Log:
- It is now possible to declare a default class for a sub-component as an @annotation.
Thus, it is no longer necessary to specify the class name as an xml attribute for sub-components
- refactoring of sibling appender
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java Mon Dec 22 23:18:36 2008
@@ -32,6 +32,7 @@
}
String defaultValue;
+ String key;
FieldName fieldName;
String optionalKey;
@@ -156,5 +157,13 @@
this.defaultValue = defaultValue;
}
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
}
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java Mon Dec 22 23:18:36 2008
@@ -36,7 +36,7 @@
Object o = ec.peekObject();
if (o instanceof SiftingAppender) {
SiftingAppender siftingAppender = (SiftingAppender) o;
- AppenderFactory appenderFactory = new AppenderFactory(context, seList, siftingAppender.getKeyName());
+ AppenderFactory appenderFactory = new AppenderFactory(context, seList, siftingAppender.getDiscriminatorKey());
siftingAppender.setAppenderFactory(appenderFactory);
}
}
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java Mon Dec 22 23:18:36 2008
@@ -10,9 +10,10 @@
package ch.qos.logback.access.sift;
import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.joran.spi.DefaultClass;
import ch.qos.logback.core.sift.AppenderTracker;
+import ch.qos.logback.core.sift.Discriminator;
import ch.qos.logback.core.sift.SiftingAppenderBase;
-import ch.qos.logback.core.util.OptionHelper;
/**
* This appender can contains other appenders which it can build dynamically
@@ -26,18 +27,9 @@
*/
public class SiftingAppender extends SiftingAppenderBase<AccessEvent> {
- String keyName;
-
@Override
public void start() {
- int errors = 0;
- if (OptionHelper.isEmpty(keyName)) {
- errors++;
- addError("The \"keyName\" property must be set");
- }
- if (errors == 0) {
- super.start();
- }
+ super.start();
}
AppenderTracker<AccessEvent> getAppenderTracker() {
@@ -49,12 +41,9 @@
return event.getTimeStamp();
}
- public String getKeyName() {
- return keyName;
- }
-
- public void setKeyName(String keyName) {
- this.keyName = keyName;
+ @Override
+ @DefaultClass(AccessEventDiscriminator.class)
+ public void setDiscriminator(Discriminator<AccessEvent> discriminator) {
+ super.setDiscriminator(discriminator);
}
-
}
Modified: logback/trunk/logback-access/src/test/input/jetty/sifting.xml
==============================================================================
--- logback/trunk/logback-access/src/test/input/jetty/sifting.xml (original)
+++ logback/trunk/logback-access/src/test/input/jetty/sifting.xml Mon Dec 22 23:18:36 2008
@@ -1,13 +1,15 @@
<configuration>
- <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
- <KeyName>uri</KeyName>
- <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+ <appender name="SIFTING"
+ class="ch.qos.logback.access.sift.SiftingAppender">
+
+ <Discriminator>
+ <Key>uri</Key>
<FieldName>REQUEST_URI</FieldName>
<DefaultValue>NA</DefaultValue>
</Discriminator>
<sift>
- <appender name="${uri}" class="ch.qos.logback.core.read.ListAppender"/>
+ <appender name="${uri}" class="ch.qos.logback.core.read.ListAppender" />
</sift>
</appender>
Added: logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml Mon Dec 22 23:18:36 2008
@@ -0,0 +1,16 @@
+<configuration>
+
+ <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
+ <KeyName>client</KeyName>
+ <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+ <DefaultValue>NA</DefaultValue>
+ <FieldName>REQUEST_URI</FieldName>
+ </Discriminator>
+ <sift>
+ <appender name="file-${client}"
+ class="ch.qos.logback.core.read.ListAppender" />
+ </sift>
+ </appender>
+
+ <appender-ref ref="SIFTING" />
+</configuration>
\ No newline at end of file
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java Mon Dec 22 23:18:36 2008
@@ -25,6 +25,7 @@
import ch.qos.logback.access.spi.Util;
import ch.qos.logback.core.read.ListAppender;
import ch.qos.logback.core.testUtil.RandomUtil;
+import ch.qos.logback.core.util.StatusPrinter;
public class SiftingAppenderTest {
static final String PREFIX = "src/test/input/jetty/";
@@ -51,11 +52,14 @@
rli.setFileName(PREFIX + "sifting.xml");
jettyFixture.start();
+
+ StatusPrinter.print(rli);
invokeServer("/");
invokeServer("/x");
invokeServer("/x");
invokeServer("/y");
+
SiftingAppender siftingAppender = (SiftingAppender) rli
.getAppender("SIFTING");
List<String> keyList = siftingAppender.getAppenderTracker().keyList();
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java Mon Dec 22 23:18:36 2008
@@ -13,21 +13,21 @@
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.sift.Discriminator;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import ch.qos.logback.core.util.OptionHelper;
-public class MDCBasedDiscriminator implements Discriminator<LoggingEvent> {
+public class MDCBasedDiscriminator extends ContextAwareBase implements Discriminator<LoggingEvent> {
- final String mdcKey;
- final String defaultValue;
+ String key;
+ String defaultValue;
- boolean started = true;
+ boolean started = false;
- MDCBasedDiscriminator(String mdcKey, String defaultValue) {
- this.mdcKey = mdcKey;
- this.defaultValue = defaultValue;
+ public MDCBasedDiscriminator() {
}
public String getDiscriminatingValue(LoggingEvent event) {
- String mdcValue = MDC.get(mdcKey);
+ String mdcValue = MDC.get(key);
if (mdcValue == null) {
return defaultValue;
} else {
@@ -40,11 +40,54 @@
}
public void start() {
- started = true;
+ int errors = 0;
+ if (OptionHelper.isEmpty(key)) {
+ errors++;
+ addError("The \"Key\" property must be set");
+ }
+ if (OptionHelper.isEmpty(defaultValue)) {
+ errors++;
+ addError("The \"DefaultValue\" property must be set");
+ }
+ if (errors == 0) {
+ started = true;
+ }
}
public void stop() {
started = false;
}
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ /**
+ * @see #setDefaultValue(String)
+ * @return
+ */
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * The default MDC value in case the MDC is not set for
+ * {@link #setMdcKey(String) mdcKey}.
+ *
+ * <p> For example, if {@link #setMdcKey(String) mdcKey} is set to the value
+ * "someKey", and the MDC is not set for "someKey", then this appender will
+ * use the default value, which you can set with the help of method.
+ *
+ * @param defaultValue
+ */
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+
+
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java Mon Dec 22 23:18:36 2008
@@ -11,9 +11,9 @@
import ch.qos.logback.core.joran.spi.ActionException;
import ch.qos.logback.core.joran.spi.InterpretationContext;
-public class SiftAction extends Action implements InPlayListener {
+public class SiftAction extends Action implements InPlayListener {
List<SaxEvent> seList;
-
+
@Override
public void begin(InterpretationContext ec, String name, Attributes attributes)
throws ActionException {
@@ -26,22 +26,19 @@
ec.removeInPlayListener(this);
Object o = ec.peekObject();
if (o instanceof SiftingAppender) {
- SiftingAppender ha = (SiftingAppender) o;
- AppenderFactory appenderFactory = new AppenderFactory(context, seList, ha.getMdcKey());
- ha.setAppenderFactory(appenderFactory);
+ SiftingAppender sa = (SiftingAppender) o;
+ AppenderFactory appenderFactory = new AppenderFactory(context, seList, sa
+ .getDiscriminatorKey());
+ sa.setAppenderFactory(appenderFactory);
}
}
public void inPlay(SaxEvent event) {
seList.add(event);
- System.out.println(event);
}
public List<SaxEvent> getSeList() {
return seList;
}
-
-
-
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java Mon Dec 22 23:18:36 2008
@@ -10,9 +10,10 @@
package ch.qos.logback.classic.sift;
import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.joran.spi.DefaultClass;
import ch.qos.logback.core.sift.AppenderTracker;
+import ch.qos.logback.core.sift.Discriminator;
import ch.qos.logback.core.sift.SiftingAppenderBase;
-import ch.qos.logback.core.util.OptionHelper;
/**
* This appender can contains other appenders which it can build dynamically
@@ -26,71 +27,20 @@
*/
public class SiftingAppender extends SiftingAppenderBase<LoggingEvent> {
-
- String mdcKey;
- String defaultValue;
-
-
- @Override
- public void start() {
- int errors = 0;
- if (OptionHelper.isEmpty(mdcKey)) {
- errors++;
- addError("The \"mdcKey\" property must be set");
- }
- if (OptionHelper.isEmpty(defaultValue)) {
- errors++;
- addError("The \"defaultValue\" property must be set");
- }
- setDiscriminator(new MDCBasedDiscriminator(mdcKey, defaultValue));
- if (errors == 0) {
- super.start();
- }
- }
-
AppenderTracker<LoggingEvent> getAppenderTracker() {
return appenderTracker;
}
-
@Override
protected long getTimestamp(LoggingEvent event) {
return event.getTimeStamp();
}
-
- public String getMdcKey() {
- return mdcKey;
- }
-
- public void setMdcKey(String mdcKey) {
- this.mdcKey = mdcKey;
- }
-
- /**
- * @see #setDefaultValue(String)
- * @return
- */
- public String getDefaultValue() {
- return defaultValue;
- }
- /**
- * The default MDC value in case the MDC is not set for
- * {@link #setMdcKey(String) mdcKey}.
- *
- * <p> For example, if {@link #setMdcKey(String) mdcKey} is set to the value
- * "someKey", and the MDC is not set for "someKey", then this appender will
- * use the default value, which you can set with the help of method.
- *
- * <p>The "defaultValue" property is set to the value "DEFAULT" by default.
- *
- * @param defaultValue
- */
- public void setDefaultValue(String defaultValue) {
- this.defaultValue = defaultValue;
+ @Override
+ @DefaultClass(MDCBasedDiscriminator.class)
+ public void setDiscriminator(Discriminator<LoggingEvent> discriminator) {
+ super.setDiscriminator(discriminator);
}
-
-
}
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml Mon Dec 22 23:18:36 2008
@@ -3,13 +3,15 @@
<configuration debug="true">
- <appender name="SIFT"
- class="ch.qos.logback.classic.sift.SiftingAppender">
+ <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
- <mdcKey>cycle</mdcKey>
- <defaultValue>cycleDefault</defaultValue>
+ <discriminator>
+ <Key>cycle</Key>
+ <defaultValue>cycleDefault</defaultValue>
+ </discriminator>
<sift>
- <appender name="list-${cycle}" class="ch.qos.logback.core.read.ListAppender"/>
+ <appender name="list-${cycle}"
+ class="ch.qos.logback.core.read.ListAppender" />
</sift>
</appender>
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml Mon Dec 22 23:18:36 2008
@@ -3,13 +3,15 @@
<configuration debug="true">
- <appender name="SIFT"
- class="ch.qos.logback.classic.sift.SiftingAppender">
+ <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
- <mdcKey>userid</mdcKey>
- <defaultValue>smoke</defaultValue>
+ <discriminator>
+ <Key>userid</Key>
+ <defaultValue>smoke</defaultValue>
+ </discriminator>
<sift>
- <appender name="list-${userid}" class="ch.qos.logback.core.read.ListAppender"/>
+ <appender name="list-${userid}"
+ class="ch.qos.logback.core.read.ListAppender" />
</sift>
</appender>
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml Mon Dec 22 23:18:36 2008
@@ -3,12 +3,14 @@
<configuration debug="true">
- <appender name="SIFT"
- class="ch.qos.logback.classic.sift.SiftingAppender">
+ <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
- <mdcKey>userid</mdcKey>
+ <discriminator>
+ <Key>userid</Key>
+ </discriminator>
<sift>
- <appender name="list-${userid}" class="ch.qos.logback.core.read.ListAppender"/>
+ <appender name="list-${userid}"
+ class="ch.qos.logback.core.read.ListAppender" />
</sift>
</appender>
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java Mon Dec 22 23:18:36 2008
@@ -47,9 +47,8 @@
public void unsetDefaultValueProperty() throws JoranException {
configure(PREFIX + "unsetDefaultValueProperty.xml");
logger.debug("hello");
- SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT");
- assertFalse(ha.isStarted());
-
+ SiftingAppender sa = (SiftingAppender) root.getAppender("SIFT");
+ assertFalse(sa.isStarted());
}
@Test
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java Mon Dec 22 23:18:36 2008
@@ -74,7 +74,7 @@
return true;
default:
- addError("PropertySetter.canContainComponent returned " + aggregationType);
+ addError("PropertySetter.computeAggregationType returned " + aggregationType);
return false;
}
}
@@ -87,9 +87,13 @@
.peek();
String className = attributes.getValue(CLASS_ATTRIBUTE);
-
// perform variable name substitution
className = ec.subst(className);
+ if (className == null) {
+ PropertySetter parentBean = actionData.parentBean;
+ className = parentBean.getDefaultClassNameByAnnonation(actionData
+ .getComplexPropertyName(), actionData.getAggregationType());
+ }
if (OptionHelper.isEmpty(className)) {
Class clazz = actionData.parentBean
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/DefaultClass.java Mon Dec 22 23:18:36 2008
@@ -0,0 +1,21 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.joran.spi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+(a)Retention(RetentionPolicy.RUNTIME)
+(a)Target(ElementType.METHOD)
+public @interface DefaultClass {
+ Class value();
+}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java Mon Dec 22 23:18:36 2008
@@ -22,6 +22,7 @@
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -37,8 +38,7 @@
* the Object specified in the constructor. This class relies on the JavaBeans
* {@link Introspector} to analyze the given Object Class using reflection.
*
- * <p>
- * Usage:
+ * <p> Usage:
*
* <pre>
* PropertySetter ps = new PropertySetter(anObject);
@@ -97,11 +97,10 @@
* setter argument type and partly from the value specified in the call to
* this method.
*
- * <p>
- * If the setter expects a String no conversion is necessary. If it expects an
- * int, then an attempt is made to convert 'value' to an int using new
- * Integer(value). If the setter expects a boolean, the conversion is by new
- * Boolean(value).
+ * <p> If the setter expects a String no conversion is necessary. If it
+ * expects an int, then an attempt is made to convert 'value' to an int using
+ * new Integer(value). If the setter expects a boolean, the conversion is by
+ * new Boolean(value).
*
* @param name
* name of the property
@@ -530,4 +529,36 @@
public Object getObj() {
return obj;
}
+
+ public <T extends Annotation> T getAnnotation(String name,
+ Class<T> annonationClass, AggregationType aggregationType) {
+ String cName = capitalizeFirstLetter(name);
+ Method relevantMethod;
+ if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY_COLLECTION) {
+ relevantMethod = getMethod("add" + cName);
+ } else if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY) {
+ relevantMethod = findSetterMethod(cName);
+ } else {
+ throw new IllegalStateException(aggregationType + " not allowed here");
+ }
+ if (relevantMethod != null) {
+ return relevantMethod.getAnnotation(annonationClass);
+ } else {
+ return null;
+ }
+ }
+
+ public String getDefaultClassNameByAnnonation(String name,
+ AggregationType aggregationType) {
+
+ DefaultClass defaultClassAnnon = getAnnotation(name, DefaultClass.class,
+ aggregationType);
+ if (defaultClassAnnon != null) {
+ Class defaultClass = defaultClassAnnon.value();
+ if (defaultClass != null) {
+ return defaultClass.getName();
+ }
+ }
+ return null;
+ }
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java Mon Dec 22 23:18:36 2008
@@ -14,4 +14,5 @@
public interface Discriminator<E> extends LifeCycle {
String getDiscriminatingValue(E e);
+ String getKey();
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Mon Dec 22 23:18:36 2008
@@ -14,12 +14,11 @@
import ch.qos.logback.core.joran.spi.JoranException;
/**
- * This appender can contains other appenders which it can build dynamically
- * depending on MDC values. The built appender is specified as part of a
- * configuration file.
- *
- * <p>See the logback manual for further details.
- *
+ * This appender serves as the base class for actual SiftingAppenders
+ * implemented by the logback-classic and logback-access modules. In a nutshell,
+ * a SiftingAppender contains other appenders which it can build dynamically
+ * depending on discriminating values supplied by event currently being
+ * processed. The built appender is specified as part of a configuration file.
*
* @author Ceki Gulcu
*/
@@ -28,23 +27,27 @@
protected AppenderTracker<E> appenderTracker = new AppenderTrackerImpl<E>();
AppenderFactoryBase<E> appenderFactory;
-
+
Discriminator<E> discriminator;
-
+
public void setAppenderFactory(AppenderFactoryBase<E> appenderFactory) {
this.appenderFactory = appenderFactory;
}
@Override
public void start() {
- if(discriminator == null) {
+ int errors = 0;
+ if (discriminator == null) {
addError("Missing discriminator. Aborting");
- return;
+ errors++;
}
- if(!discriminator.isStarted()) {
+ if (!discriminator.isStarted()) {
addError("Discriminator has not started successfully. Aborting");
+ errors++;
+ }
+ if (errors == 0) {
+ super.start();
}
- super.start();
}
@Override
@@ -90,4 +93,12 @@
this.discriminator = discriminator;
}
+
+ public String getDiscriminatorKey() {
+ if(discriminator != null) {
+ return discriminator.getKey();
+ } else {
+ return null;
+ }
+ }
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java Mon Dec 22 23:18:36 2008
@@ -180,6 +180,15 @@
setter.setProperty("houseColor", "BLUE");
assertEquals(HouseColor.BLUE, house.getHouseColor());
}
+
+
+ @Test
+ public void testDefaultClassAnnonation() {
+ House house = new House();
+ PropertySetter setter = new PropertySetter(house);
+ String spClassName = setter.getDefaultClassNameByAnnonation("SwimmingPool", AggregationType.AS_COMPLEX_PROPERTY);
+ assertEquals(SwimmingPool.class.getName(), spClassName);
+ }
}
class House {
@@ -237,6 +246,7 @@
this.open = open;
}
+ @DefaultClass(SwimmingPool.class)
public void setSwimmingPool(SwimmingPool pool) {
this.pool = pool;
}
1
0
Author: ceki
Date: Mon Dec 22 19:54:44 2008
New Revision: 2094
Added:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java
logback/trunk/logback-access/src/test/input/jetty/
logback/trunk/logback-access/src/test/input/jetty/sifting.xml
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java
- copied, changed from r1859, /logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java
Removed:
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/AccessStatsTest.java
Modified:
logback/trunk/logback-access/pom.xml
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java
logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
Log:
- Added support for SiftingAppender in logback-access
- logback-access tests are now all JUnit4
Modified: logback/trunk/logback-access/pom.xml
==============================================================================
--- logback/trunk/logback-access/pom.xml (original)
+++ logback/trunk/logback-access/pom.xml Mon Dec 22 19:54:44 2008
@@ -109,7 +109,7 @@
<reportFormat>plain</reportFormat>
<disableXmlReport>true</disableXmlReport>
<excludes>
- <exclude>**/AllTest.java</exclude>
+ <exclude>**/AllAccessTest.java</exclude>
<exclude>**/PackageTest.java</exclude>
<exclude>**/SerializationPerfTest.java</exclude>
</excludes>
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java Mon Dec 22 19:54:44 2008
@@ -133,12 +133,10 @@
if (getFilterChainDecision(accessEvent) == FilterReply.DENY) {
return;
}
- // TODO better exception handling
aai.appendLoopOnAppenders(accessEvent);
}
public void start() {
-
if (filename == null) {
String jettyHomeProperty = OptionHelper.getSystemProperty("jetty.home");
Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java (original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java Mon Dec 22 19:54:44 2008
@@ -13,9 +13,11 @@
import ch.qos.logback.access.joran.action.ConfigurationAction;
import ch.qos.logback.access.joran.action.EvaluatorAction;
+import ch.qos.logback.access.sift.SiftAction;
import ch.qos.logback.core.joran.JoranConfiguratorBase;
import ch.qos.logback.core.joran.action.AppenderRefAction;
import ch.qos.logback.core.joran.action.MatcherAction;
+import ch.qos.logback.core.joran.action.NOPAction;
import ch.qos.logback.core.joran.spi.Pattern;
import ch.qos.logback.core.joran.spi.RuleStore;
@@ -34,6 +36,9 @@
rs.addRule(new Pattern("configuration"), new ConfigurationAction());
rs.addRule(new Pattern("configuration/appender-ref"), new AppenderRefAction());
+ rs.addRule(new Pattern("configuration/appender/sift"), new SiftAction());
+ rs.addRule(new Pattern("configuration/appender/sift/*"), new NOPAction());
+
rs.addRule(new Pattern("*/evaluator"), new EvaluatorAction());
rs.addRule(new Pattern("*/evaluator/matcher"), new MatcherAction());
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,160 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.sift.Discriminator;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+public class AccessEventDiscriminator extends ContextAwareBase implements
+ Discriminator<AccessEvent> {
+
+ boolean started = false;
+
+ /**
+ * Allowed field names are: COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE,
+ * REMOTE_ADDRESS, LOCAL_PORT,REQUEST_URI
+ *
+ * <p> The first three field names require a key attribute.
+ */
+ public enum FieldName {
+ COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI
+ }
+
+ String defaultValue;
+ FieldName fieldName;
+ String optionalKey;
+
+ public String getDiscriminatingValue(AccessEvent acccessEvent) {
+ String rawValue = getRawDiscriminatingValue(acccessEvent);
+ if (rawValue == null || rawValue.length() == 0) {
+ return defaultValue;
+ } else {
+ return rawValue;
+ }
+ }
+
+ public String getRawDiscriminatingValue(AccessEvent acccessEvent) {
+ switch (fieldName) {
+ case COOKIE:
+ return acccessEvent.getCookie(optionalKey);
+ case LOCAL_PORT:
+ return String.valueOf(acccessEvent.getLocalPort());
+ case REQUEST_ATTRIBUTE:
+ return acccessEvent.getAttribute(optionalKey);
+ case SESSION_ATTRIBUTE:
+ return getSessionAttribute(acccessEvent);
+ case REMOTE_ADDRESS:
+ return acccessEvent.getRemoteAddr();
+ case REQUEST_URI:
+ return getRequestURI(acccessEvent);
+ default:
+ return null;
+ }
+ }
+
+ private String getRequestURI(AccessEvent acccessEvent) {
+ String uri = acccessEvent.getRequestURI();
+ if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') {
+ return uri.substring(1);
+ } else {
+ return uri;
+ }
+ }
+
+ private String getSessionAttribute(AccessEvent acccessEvent) {
+ HttpServletRequest req = acccessEvent.getRequest();
+ if (req != null) {
+ HttpSession session = req.getSession(false);
+ if (session != null) {
+ Object v = session.getAttribute(optionalKey);
+ if (v != null) {
+ return v.toString();
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public void start() {
+
+ int errorCount = 0;
+
+ if (defaultValue == null) {
+ addError("\"DefaultValue\" property must be set.");
+ }
+ if (fieldName == null) {
+ addError("\"FieldName\" property must be set.");
+ errorCount++;
+ }
+
+ switch (fieldName) {
+ case SESSION_ATTRIBUTE:
+ case REQUEST_ATTRIBUTE:
+ case COOKIE:
+ if (optionalKey == null) {
+ addError("\"OptionalKey\" property is mandatory for field name "+fieldName.toString());
+ errorCount++;
+ }
+ }
+
+ if (errorCount == 0) {
+ started = true;
+ }
+ }
+
+ public void stop() {
+ started = false;
+ }
+
+ public void setFieldName(FieldName fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ public FieldName getFieldName() {
+ return fieldName;
+ }
+
+ public String getOptionalKey() {
+ return optionalKey;
+ }
+
+ public void setOptionalKey(String optionalKey) {
+ this.optionalKey = optionalKey;
+ }
+
+
+ /**
+ * @see #setDefaultValue(String)
+ * @return
+ */
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * The default value returned by this discriminator in case it cannot compute
+ * the discriminating value from the access event.
+ *
+ * @param defaultValue
+ */
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+
+}
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,34 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import java.util.List;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.joran.event.SaxEvent;
+import ch.qos.logback.core.sift.AppenderFactoryBase;
+import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
+
+public class AppenderFactory extends AppenderFactoryBase<AccessEvent> {
+
+ String keyName;
+
+ AppenderFactory(Context context, List<SaxEvent> eventList, String keyName) {
+ super(context, eventList);
+ this.keyName = keyName;
+ }
+
+ public SiftingJoranConfiguratorBase<AccessEvent> getSiftingJoranConfigurator(
+ String keyValue) {
+ return new SiftingJoranConfigurator(keyName, keyValue);
+ }
+
+}
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,55 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+
+import ch.qos.logback.core.joran.action.Action;
+import ch.qos.logback.core.joran.event.InPlayListener;
+import ch.qos.logback.core.joran.event.SaxEvent;
+import ch.qos.logback.core.joran.spi.ActionException;
+import ch.qos.logback.core.joran.spi.InterpretationContext;
+
+public class SiftAction extends Action implements InPlayListener {
+ List<SaxEvent> seList;
+
+ @Override
+ public void begin(InterpretationContext ec, String name, Attributes attributes)
+ throws ActionException {
+ seList = new ArrayList<SaxEvent>();
+ ec.addInPlayListener(this);
+ }
+
+ @Override
+ public void end(InterpretationContext ec, String name) throws ActionException {
+ ec.removeInPlayListener(this);
+ Object o = ec.peekObject();
+ if (o instanceof SiftingAppender) {
+ SiftingAppender siftingAppender = (SiftingAppender) o;
+ AppenderFactory appenderFactory = new AppenderFactory(context, seList, siftingAppender.getKeyName());
+ siftingAppender.setAppenderFactory(appenderFactory);
+ }
+ }
+
+ public void inPlay(SaxEvent event) {
+ seList.add(event);
+ }
+
+ public List<SaxEvent> getSeList() {
+ return seList;
+ }
+
+
+
+
+}
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,60 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.sift.AppenderTracker;
+import ch.qos.logback.core.sift.SiftingAppenderBase;
+import ch.qos.logback.core.util.OptionHelper;
+
+/**
+ * This appender can contains other appenders which it can build dynamically
+ * depending on MDC values. The built appender is specified as part of a
+ * configuration file.
+ *
+ * <p>See the logback manual for further details.
+ *
+ *
+ * @author Ceki Gulcu
+ */
+public class SiftingAppender extends SiftingAppenderBase<AccessEvent> {
+
+ String keyName;
+
+ @Override
+ public void start() {
+ int errors = 0;
+ if (OptionHelper.isEmpty(keyName)) {
+ errors++;
+ addError("The \"keyName\" property must be set");
+ }
+ if (errors == 0) {
+ super.start();
+ }
+ }
+
+ AppenderTracker<AccessEvent> getAppenderTracker() {
+ return appenderTracker;
+ }
+
+ @Override
+ protected long getTimestamp(AccessEvent event) {
+ return event.getTimeStamp();
+ }
+
+ public String getKeyName() {
+ return keyName;
+ }
+
+ public void setKeyName(String keyName) {
+ this.keyName = keyName;
+ }
+
+}
Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,53 @@
+package ch.qos.logback.access.sift;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.joran.action.ActionConst;
+import ch.qos.logback.core.joran.action.AppenderAction;
+import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.joran.spi.RuleStore;
+import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
+
+public class SiftingJoranConfigurator extends SiftingJoranConfiguratorBase<AccessEvent> {
+
+ String key;
+ String value;
+
+ SiftingJoranConfigurator(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ protected Pattern initialPattern() {
+ return new Pattern("configuration");
+ }
+
+ @Override
+ protected void addInstanceRules(RuleStore rs) {
+ rs.addRule(new Pattern("configuration/appender"), new AppenderAction());
+ }
+
+ @Override
+ protected void buildInterpreter() {
+ super.buildInterpreter();
+ Map<String, Object> omap = interpreter.getInterpretationContext().getObjectMap();
+ omap.put(ActionConst.APPENDER_BAG, new HashMap());
+ omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap());
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ propertiesMap.put(key, value);
+ interpreter.setInterpretationContextPropertiesMap(propertiesMap);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Appender<AccessEvent> getAppender() {
+ Map<String, Object> omap = interpreter.getInterpretationContext().getObjectMap();
+ HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG);
+ Collection values = map.values();
+ return (Appender<AccessEvent>) values.iterator().next();
+ }
+}
Added: logback/trunk/logback-access/src/test/input/jetty/sifting.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/input/jetty/sifting.xml Mon Dec 22 19:54:44 2008
@@ -0,0 +1,15 @@
+<configuration>
+
+ <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
+ <KeyName>uri</KeyName>
+ <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+ <FieldName>REQUEST_URI</FieldName>
+ <DefaultValue>NA</DefaultValue>
+ </Discriminator>
+ <sift>
+ <appender name="${uri}" class="ch.qos.logback.core.read.ListAppender"/>
+ </sift>
+ </appender>
+
+ <appender-ref ref="SIFTING" />
+</configuration>
\ No newline at end of file
Copied: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java (from r1859, /logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java)
==============================================================================
--- /logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java Mon Dec 22 19:54:44 2008
@@ -9,19 +9,17 @@
*/
package ch.qos.logback.access;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
-public class AllTest extends TestCase {
+(a)RunWith(Suite.class)
+@SuiteClasses( { ch.qos.logback.access.spi.PackageTest.class,
+ ch.qos.logback.access.net.PackageTest.class,
+ ch.qos.logback.access.pattern.PackageTest.class,
+ ch.qos.logback.access.jetty.PackageTest.class,
+ ch.qos.logback.access.filter.PackageTest.class,
+ ch.qos.logback.access.sift.PackageTest.class })
+public class AllAccessTest {
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTest(ch.qos.logback.access.spi.PackageTest.suite());
- suite.addTest(ch.qos.logback.access.net.PackageTest.suite());
- suite.addTest(ch.qos.logback.access.pattern.PackageTest.suite());
- suite.addTest(ch.qos.logback.access.jetty.PackageTest.suite());
- suite.addTest(ch.qos.logback.access.filter.PackageTest.suite());
- return suite;
- }
}
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java Mon Dec 22 19:54:44 2008
@@ -10,14 +10,13 @@
package ch.qos.logback.access.filter;
-import junit.framework.*;
+import junit.framework.TestCase;
-public class PackageTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTestSuite(StatsByDayTest.class);
- suite.addTestSuite(AccessStatsTest.class);
- return suite;
- }
+(a)RunWith(Suite.class)
+(a)SuiteClasses({StatsByDayTest.class})
+public class PackageTest extends TestCase {
}
\ No newline at end of file
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java Mon Dec 22 19:54:44 2008
@@ -1,34 +1,25 @@
package ch.qos.logback.access.filter;
-import ch.qos.logback.core.util.TimeUtil;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
-public class StatsByDayTest extends TestCase {
+import org.junit.Test;
- public StatsByDayTest(String name) {
- super(name);
- }
+import ch.qos.logback.core.util.TimeUtil;
- protected void setUp() throws Exception {
- super.setUp();
- }
+public class StatsByDayTest {
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- public void testBasic() {
- // Tue Nov 21 18:05:36 CET 2006
+ @Test
+ public void testBasic() {
+ // Tue Nov 21 18:05:36 CET 2006
long now = 1164128736369L;
StatsByDay statsByDay = new StatsByDay(now);
-
+
int total = 0;
// test fresh start
statsByDay.update(now, 0);
assertEquals(0, statsByDay.getLastCount());
assertEquals(0, statsByDay.getAverage(), 0.01);
-
total++;
statsByDay.update(now, total);
assertEquals(0, statsByDay.getLastCount());
@@ -36,14 +27,14 @@
long nextDay0 = TimeUtil.computeStartOfNextDay(now);
nextDay0 += 99;
-
+
// there should be one event the next day, avg should also be 1
statsByDay.update(nextDay0, total);
assertEquals(1.0, statsByDay.getLastCount(), 0.01);
assertEquals(1.0, statsByDay.getAverage(), 0.01);
total += 2;
-
+
statsByDay.update(nextDay0, total);
assertEquals(1, statsByDay.getLastCount());
assertEquals(1.0, statsByDay.getAverage(), 0.01);
@@ -55,19 +46,18 @@
nextDay1 += 4444;
total += 4;
-
+
statsByDay.update(nextDay1, total);
// values should remain unchanged
assertEquals(2, statsByDay.getLastCount());
assertEquals(1.5, statsByDay.getAverage(), 0.01);
-
long nextDay2 = TimeUtil.computeStartOfNextDay(nextDay1) + 11177;
statsByDay.update(nextDay2, total);
// values should remain unchanged
assertEquals(4, statsByDay.getLastCount());
- assertEquals(7.0/3, statsByDay.getAverage(), 0.01);
+ assertEquals(7.0 / 3, statsByDay.getAverage(), 0.01);
}
}
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java Mon Dec 22 19:54:44 2008
@@ -1,3 +1,12 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
package ch.qos.logback.access.jetty;
import java.io.IOException;
@@ -7,15 +16,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.HttpConnection;
import org.mortbay.jetty.Request;
-import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.AbstractHandler;
-import org.mortbay.jetty.handler.ContextHandler;
-import org.mortbay.jetty.handler.RequestLogHandler;
-import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.util.ByteArrayISO8859Writer;
import ch.qos.logback.access.PatternLayout;
@@ -23,62 +27,26 @@
import ch.qos.logback.access.testUtil.NotifyingListAppender;
import ch.qos.logback.core.ConsoleAppender;
-public class JettyFixture {
- RequestLogImpl requestLogImpl;
-
- private final int port;
- Server server;
- String url;
+public class JettyFixture extends JettyFixtureBase {
+
+ Handler handler = new BasicHandler();
public JettyFixture(RequestLogImpl impl, int port) {
- requestLogImpl = impl;
- this.port = port;
+ super(impl, port);
url = "http://localhost:" + port + "/";
}
- public String getName() {
- return "Jetty Test Setup";
- }
-
- public String getUrl() {
- return url;
- }
-
public void start() throws Exception {
- server = new Server();
- Connector connector = new SelectChannelConnector();
- connector.setPort(port);
- server.setConnectors(new Connector[] { connector });
-
- ContextHandler context = new ContextHandler();
- context.setContextPath("/");
- context.setResourceBase(".");
- context.setClassLoader(Thread.currentThread().getContextClassLoader());
- server.addHandler(context);
-
- RequestLogHandler requestLogHandler = new RequestLogHandler();
- buildContext();
- requestLogHandler.setRequestLog(requestLogImpl);
- server.addHandler(requestLogHandler);
-
- Handler handler = new BasicHandler();
- context.addHandler(handler);
-
- server.start();
-
+ super.start();
Thread.yield();
}
public void stop() throws Exception {
- // System.out.println("into tearDown");
- server.stop();
- Thread.sleep(1000);
- server = null;
- requestLogImpl = null;
+ super.stop();
+ Thread.sleep(500);
}
- private void buildContext() {
-
+ protected void buildContext() {
NotifyingListAppender appender = new NotifyingListAppender();
appender.setContext(requestLogImpl);
appender.setName("list");
@@ -98,6 +66,11 @@
requestLogImpl.addAppender(console);
}
+ @Override
+ protected Handler getHandler() {
+ return handler;
+ }
+
}
class BasicHandler extends AbstractHandler {
Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,72 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.jetty;
+
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.ContextHandler;
+import org.mortbay.jetty.handler.RequestLogHandler;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+
+abstract public class JettyFixtureBase {
+ protected RequestLogImpl requestLogImpl;
+
+ private final int port;
+ Server server;
+ String url;
+
+ public JettyFixtureBase(RequestLogImpl impl, int port) {
+ requestLogImpl = impl;
+ this.port = port;
+ url = "http://localhost:" + port + "/";
+ }
+
+ public String getName() {
+ return "Jetty Test Setup";
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void start() throws Exception {
+ server = new Server();
+ Connector connector = new SelectChannelConnector();
+ connector.setPort(port);
+ server.setConnectors(new Connector[] { connector });
+
+ ContextHandler context = new ContextHandler();
+ context.setContextPath("/");
+ context.setResourceBase(".");
+ context.setClassLoader(Thread.currentThread().getContextClassLoader());
+ server.addHandler(context);
+
+ RequestLogHandler requestLogHandler = new RequestLogHandler();
+ buildContext();
+ requestLogHandler.setRequestLog(requestLogImpl);
+ server.addHandler(requestLogHandler);
+
+ Handler handler = getHandler();
+ context.addHandler(handler);
+
+ server.start();
+ }
+
+ public void stop() throws Exception {
+ // System.out.println("into tearDown");
+ server.stop();
+ server = null;
+ requestLogImpl = null;
+ }
+
+ abstract protected void buildContext();
+ abstract protected Handler getHandler();
+}
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java Mon Dec 22 19:54:44 2008
@@ -10,13 +10,12 @@
package ch.qos.logback.access.jetty;
-import junit.framework.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
-public class PackageTest extends TestCase {
+(a)RunWith(Suite.class)
+(a)SuiteClasses({JettyBasicTest.class})
+public class PackageTest {
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTest(new JUnit4TestAdapter(JettyBasicTest.class));
- return suite;
- }
}
\ No newline at end of file
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java Mon Dec 22 19:54:44 2008
@@ -9,14 +9,13 @@
*/
package ch.qos.logback.access.net;
-import junit.framework.*;
+import junit.framework.TestCase;
-public class PackageTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTestSuite(URLEvaluatorTest.class);
- suite.addTestSuite(SocketAppenderTest.class);
- return suite;
- }
+(a)RunWith(Suite.class)
+(a)SuiteClasses({URLEvaluatorTest.class, SocketAppenderTest.class})
+public class PackageTest extends TestCase {
}
\ No newline at end of file
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java Mon Dec 22 19:54:44 2008
@@ -9,19 +9,24 @@
*/
package ch.qos.logback.access.net;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
import ch.qos.logback.access.dummy.DummyRequest;
import ch.qos.logback.access.dummy.DummyResponse;
import ch.qos.logback.access.dummy.DummyServerAdapter;
-import ch.qos.logback.access.spi.AccessEvent;
import ch.qos.logback.access.spi.AccessContext;
+import ch.qos.logback.access.spi.AccessEvent;
-public class SocketAppenderTest extends TestCase {
+public class SocketAppenderTest {
private AccessContext context;
private MockSocketServer mockSocketServer;
+ @Test
public void testStartFailNoRemoteHost() {
context = new AccessContext();
SocketAppender appender = new SocketAppender();
@@ -31,6 +36,7 @@
assertEquals(1, context.getStatusManager().getCount());
}
+ @Test
public void testRecieveMessage() throws InterruptedException {
startServer(1);
configureClient();
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java Mon Dec 22 19:54:44 2008
@@ -1,6 +1,11 @@
package ch.qos.logback.access.net;
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
import ch.qos.logback.access.dummy.DummyRequest;
import ch.qos.logback.access.dummy.DummyResponse;
import ch.qos.logback.access.dummy.DummyServerAdapter;
@@ -9,7 +14,7 @@
import ch.qos.logback.core.ContextBase;
import ch.qos.logback.core.boolex.EvaluationException;
-public class URLEvaluatorTest extends TestCase {
+public class URLEvaluatorTest {
final String expectedURL1 = "testUrl1";
final String expectedURL2 = "testUrl2";
@@ -19,6 +24,7 @@
DummyResponse response;
DummyServerAdapter serverAdapter;
+ @Before
public void setUp() throws Exception {
evaluator = new URLEvaluator();
evaluator.setContext(context);
@@ -27,9 +33,9 @@
request = new DummyRequest();
response = new DummyResponse();
serverAdapter = new DummyServerAdapter(request, response);
- super.setUp();
}
+ @After
public void tearDown() throws Exception {
evaluator.stop();
evaluator = null;
@@ -39,18 +45,21 @@
context = null;
}
+ @Test
public void testExpectFalse() throws EvaluationException {
request.setRequestUri("test");
AccessEvent ae = new AccessEvent(request, response, serverAdapter);
assertFalse(evaluator.evaluate(ae));
}
+ @Test
public void testExpectTrue() throws EvaluationException {
request.setRequestUri(expectedURL1);
AccessEvent ae = new AccessEvent(request, response, serverAdapter);
assertTrue(evaluator.evaluate(ae));
}
+ @Test
public void testExpectTrueMultiple() throws EvaluationException {
evaluator.addURL(expectedURL2);
request.setRequestUri(expectedURL2);
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java Mon Dec 22 19:54:44 2008
@@ -1,36 +1,42 @@
package ch.qos.logback.access.pattern;
+import static org.junit.Assert.assertEquals;
+
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.Cookie;
-import junit.framework.TestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
import ch.qos.logback.access.dummy.DummyRequest;
import ch.qos.logback.access.dummy.DummyResponse;
import ch.qos.logback.access.dummy.DummyServerAdapter;
import ch.qos.logback.access.spi.AccessEvent;
-public class ConverterTest extends TestCase {
+public class ConverterTest {
AccessEvent event;
DummyRequest request;
DummyResponse response;
+ @Before
public void setUp() throws Exception {
- super.setUp();
request = new DummyRequest();
response = new DummyResponse();
event = createEvent();
}
+ @After
public void tearDown() throws Exception {
- super.tearDown();
event = null;
request = null;
response = null;
}
+ @Test
public void testContentLengthConverter() {
ContentLengthConverter converter = new ContentLengthConverter();
converter.start();
@@ -38,6 +44,7 @@
assertEquals(Long.toString(event.getServerAdapter().getContentLength()), result);
}
+ @Test
public void testDateConverter() {
DateConverter converter = new DateConverter();
converter.start();
@@ -52,6 +59,7 @@
assertEquals(Integer.toString(request.getLocalPort()), result);
}
+ @Test
public void testRemoteHostConverter() {
RemoteHostConverter converter = new RemoteHostConverter();
converter.start();
@@ -59,6 +67,7 @@
assertEquals(request.getRemoteHost(), result);
}
+ @Test
public void testRemoteIPAddressConverter() {
RemoteIPAddressConverter converter = new RemoteIPAddressConverter();
converter.start();
@@ -66,6 +75,7 @@
assertEquals(request.getRemoteAddr(), result);
}
+ @Test
public void testRemoteUserConverter() {
RemoteUserConverter converter = new RemoteUserConverter();
converter.start();
@@ -73,6 +83,7 @@
assertEquals(request.getRemoteUser(), result);
}
+ @Test
public void testRequestAttributeConverter() {
RequestAttributeConverter converter = new RequestAttributeConverter();
List<String> optionList = new ArrayList<String>();
@@ -83,6 +94,7 @@
assertEquals(request.getAttribute("testKey"), result);
}
+ @Test
public void testRequestCookieConverter() {
RequestCookieConverter converter = new RequestCookieConverter();
List<String> optionList = new ArrayList<String>();
@@ -94,6 +106,7 @@
assertEquals(cookie.getValue(), result);
}
+ @Test
public void testRequestHeaderConverter() {
RequestHeaderConverter converter = new RequestHeaderConverter();
List<String> optionList = new ArrayList<String>();
@@ -104,6 +117,7 @@
assertEquals(request.getHeader("headerName1"), result);
}
+ @Test
public void testRequestMethodConverter() {
RequestMethodConverter converter = new RequestMethodConverter();
converter.start();
@@ -111,6 +125,7 @@
assertEquals(request.getMethod(), result);
}
+ @Test
public void testRequestProtocolConverter() {
RequestProtocolConverter converter = new RequestProtocolConverter();
converter.start();
@@ -118,6 +133,7 @@
assertEquals(request.getProtocol(), result);
}
+ @Test
public void testRequestURIConverter() {
RequestURIConverter converter = new RequestURIConverter();
converter.start();
@@ -125,6 +141,7 @@
assertEquals(request.getRequestURI(), result);
}
+ @Test
public void testRequestURLConverter() {
RequestURLConverter converter = new RequestURLConverter();
converter.start();
@@ -134,6 +151,7 @@
assertEquals(expected, result);
}
+ @Test
public void testResponseHeaderConverter() {
ResponseHeaderConverter converter = new ResponseHeaderConverter();
List<String> optionList = new ArrayList<String>();
@@ -144,6 +162,7 @@
assertEquals(request.getHeader("headerName1"), result);
}
+ @Test
public void testServerNameConverter() {
ServerNameConverter converter = new ServerNameConverter();
converter.start();
@@ -151,6 +170,7 @@
assertEquals(request.getServerName(), result);
}
+ @Test
public void testStatusCodeConverter() {
StatusCodeConverter converter = new StatusCodeConverter();
converter.start();
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java Mon Dec 22 19:54:44 2008
@@ -9,13 +9,13 @@
*/
package ch.qos.logback.access.pattern;
-import junit.framework.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+(a)RunWith(Suite.class)
+(a)SuiteClasses({ConverterTest.class})
+public class PackageTest {
-public class PackageTest extends TestCase {
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTestSuite(ConverterTest.class);
- return suite;
- }
}
\ No newline at end of file
Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,59 @@
+package ch.qos.logback.access.sift;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.HttpConnection;
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.handler.AbstractHandler;
+import org.mortbay.util.ByteArrayISO8859Writer;
+
+import ch.qos.logback.access.jetty.JettyFixtureBase;
+import ch.qos.logback.access.jetty.RequestLogImpl;
+
+public class JettyFixture extends JettyFixtureBase {
+
+ Handler handler = new BasicHandler();
+
+ public JettyFixture(RequestLogImpl impl, int port) {
+ super(impl, port);
+ }
+
+ @Override
+ protected void buildContext() {
+ requestLogImpl.start();
+ }
+
+ @Override
+ protected Handler getHandler() {
+ return handler;
+ }
+
+ class BasicHandler extends AbstractHandler {
+ public void handle(String target, HttpServletRequest request,
+ HttpServletResponse response, int dispatch) throws IOException,
+ ServletException {
+
+ // String requestContent = Util.readToString(request.getInputStream());
+ // System.out.println("request content: " + requestContent);
+
+ OutputStream out = response.getOutputStream();
+ ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer();
+ writer.write("hello world");
+ writer.flush();
+ response.setContentLength(writer.size());
+ writer.writeTo(out);
+ out.flush();
+
+ Request base_request = (request instanceof Request) ? (Request) request
+ : HttpConnection.getCurrentConnection().getRequest();
+ base_request.setHandled(true);
+
+ }
+ }
+}
Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,20 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework for Java.
+ *
+ * Copyright (C) 2000-2006, 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+(a)RunWith(Suite.class)
+(a)SuiteClasses({SiftingAppenderTest.class})
+public class PackageTest {
+
+}
\ No newline at end of file
Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,96 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.access.jetty.RequestLogImpl;
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.access.spi.Util;
+import ch.qos.logback.core.read.ListAppender;
+import ch.qos.logback.core.testUtil.RandomUtil;
+
+public class SiftingAppenderTest {
+ static final String PREFIX = "src/test/input/jetty/";
+ static int RANDOM_SERVER_PORT = RandomUtil.getRandomServerPort();
+
+ JettyFixture jettyFixture;
+ RequestLogImpl rli = new RequestLogImpl();
+
+ @Before
+ public void startServer() throws Exception {
+ jettyFixture = new JettyFixture(rli, RANDOM_SERVER_PORT);
+
+ }
+
+ @After
+ public void stopServer() throws Exception {
+ if (jettyFixture != null) {
+ jettyFixture.stop();
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ rli.setFileName(PREFIX + "sifting.xml");
+ jettyFixture.start();
+
+ invokeServer("/");
+ invokeServer("/x");
+ invokeServer("/x");
+ invokeServer("/y");
+
+ SiftingAppender siftingAppender = (SiftingAppender) rli
+ .getAppender("SIFTING");
+ List<String> keyList = siftingAppender.getAppenderTracker().keyList();
+ assertEquals(3, keyList.size());
+
+ List<String> witnessList = new ArrayList<String>();
+ witnessList.add("NA");
+ witnessList.add("x");
+ witnessList.add("y");
+ assertEquals(witnessList, keyList);
+
+ long now = System.currentTimeMillis();
+ {
+ ListAppender<AccessEvent> listAppender = (ListAppender<AccessEvent>) siftingAppender
+ .getAppenderTracker().get("NA", now);
+ assertEquals(1, listAppender.list.size());
+ }
+
+ {
+ ListAppender<AccessEvent> listAppender = (ListAppender<AccessEvent>) siftingAppender
+ .getAppenderTracker().get("x", now);
+ assertEquals(2, listAppender.list.size());
+ }
+ {
+ ListAppender<AccessEvent> listAppender = (ListAppender<AccessEvent>) siftingAppender
+ .getAppenderTracker().get("y", now);
+ assertEquals(1, listAppender.list.size());
+ }
+ }
+
+ void invokeServer(String uri) throws Exception {
+ URL url = new URL("http://localhost:" + RANDOM_SERVER_PORT + uri);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setDoInput(true);
+ Util.readToString(connection.getInputStream());
+ Thread.sleep(30);
+ }
+}
Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java (original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java Mon Dec 22 19:54:44 2008
@@ -9,13 +9,13 @@
*/
package ch.qos.logback.access.spi;
-import junit.framework.*;
+import junit.framework.TestCase;
-public class PackageTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTest(new JUnit4TestAdapter(AccessEventSerializationTest.class));
- return suite;
- }
+(a)RunWith(Suite.class)
+(a)SuiteClasses({AccessEventSerializationTest.class})
+public class PackageTest extends TestCase {
}
\ No newline at end of file
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,50 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.sift;
+
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.sift.Discriminator;
+
+public class MDCBasedDiscriminator implements Discriminator<LoggingEvent> {
+
+ final String mdcKey;
+ final String defaultValue;
+
+ boolean started = true;
+
+ MDCBasedDiscriminator(String mdcKey, String defaultValue) {
+ this.mdcKey = mdcKey;
+ this.defaultValue = defaultValue;
+ }
+
+ public String getDiscriminatingValue(LoggingEvent event) {
+ String mdcValue = MDC.get(mdcKey);
+ if (mdcValue == null) {
+ return defaultValue;
+ } else {
+ return mdcValue;
+ }
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public void start() {
+ started = true;
+ }
+
+ public void stop() {
+ started = false;
+ }
+
+}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java Mon Dec 22 19:54:44 2008
@@ -9,8 +9,6 @@
*/
package ch.qos.logback.classic.sift;
-import org.slf4j.MDC;
-
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.sift.AppenderTracker;
import ch.qos.logback.core.sift.SiftingAppenderBase;
@@ -44,21 +42,12 @@
errors++;
addError("The \"defaultValue\" property must be set");
}
+ setDiscriminator(new MDCBasedDiscriminator(mdcKey, defaultValue));
if (errors == 0) {
super.start();
}
}
- @Override
- protected String getDiscriminatingValue(LoggingEvent event) {
- String mdcValue = MDC.get(mdcKey);
- if (mdcValue == null) {
- return defaultValue;
- } else {
- return mdcValue;
- }
- }
-
AppenderTracker<LoggingEvent> getAppenderTracker() {
return appenderTracker;
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java Mon Dec 22 19:54:44 2008
@@ -32,7 +32,6 @@
void removeHoardElement() {
eventList.remove(0);
eventList.remove(eventList.size() - 1);
- System.out.println(eventList);
}
public abstract SiftingJoranConfiguratorBase<E> getSiftingJoranConfigurator(String k);
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java Mon Dec 22 19:54:44 2008
@@ -0,0 +1,17 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import ch.qos.logback.core.spi.LifeCycle;
+
+
+public interface Discriminator<E> extends LifeCycle {
+ String getDiscriminatingValue(E e);
+}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Mon Dec 22 19:54:44 2008
@@ -28,13 +28,22 @@
protected AppenderTracker<E> appenderTracker = new AppenderTrackerImpl<E>();
AppenderFactoryBase<E> appenderFactory;
-
+
+ Discriminator<E> discriminator;
+
public void setAppenderFactory(AppenderFactoryBase<E> appenderFactory) {
this.appenderFactory = appenderFactory;
}
@Override
public void start() {
+ if(discriminator == null) {
+ addError("Missing discriminator. Aborting");
+ return;
+ }
+ if(!discriminator.isStarted()) {
+ addError("Discriminator has not started successfully. Aborting");
+ }
super.start();
}
@@ -45,7 +54,6 @@
}
}
- abstract protected String getDiscriminatingValue(E event);
abstract protected long getTimestamp(E event);
@Override
@@ -54,7 +62,7 @@
return;
}
- String value = getDiscriminatingValue(event);
+ String value = discriminator.getDiscriminatingValue(event);
long timestamp = getTimestamp(event);
Appender<E> appender = appenderTracker.get(value, timestamp);
@@ -74,4 +82,12 @@
appender.doAppend(event);
}
+ public Discriminator<E> getDiscriminator() {
+ return discriminator;
+ }
+
+ public void setDiscriminator(Discriminator<E> discriminator) {
+ this.discriminator = discriminator;
+ }
+
}
1
0
svn commit: r2093 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic/sift logback-core/src/main/java/ch/qos/logback/core/sift logback-core/src/test/java/ch/qos/logback/core/sift logback-core/src/test/java/ch/qos/logback/core/sift/tracker
by noreply.cekiļ¼ qos.ch 19 Dec '08
by noreply.cekiļ¼ qos.ch 19 Dec '08
19 Dec '08
Author: ceki
Date: Fri Dec 19 19:24:52 2008
New Revision: 2093
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java
Log:
- The key parameter used as a sifting discriminator is now of type String
instead of a generic K. This simplifies the code without real loss
of generality. :-)
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java Fri Dec 19 19:24:52 2008
@@ -17,7 +17,7 @@
import ch.qos.logback.core.sift.AppenderFactoryBase;
import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
-public class AppenderFactory extends AppenderFactoryBase<LoggingEvent, String>{
+public class AppenderFactory extends AppenderFactoryBase<LoggingEvent>{
String mdcKey;
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java Fri Dec 19 19:24:52 2008
@@ -26,7 +26,7 @@
*
* @author Ceki Gulcu
*/
-public class SiftingAppender extends SiftingAppenderBase<LoggingEvent, String> {
+public class SiftingAppender extends SiftingAppenderBase<LoggingEvent> {
String mdcKey;
@@ -59,7 +59,7 @@
}
}
- AppenderTracker<LoggingEvent, String> getAppenderTracker() {
+ AppenderTracker<LoggingEvent> getAppenderTracker() {
return appenderTracker;
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java Fri Dec 19 19:24:52 2008
@@ -17,7 +17,7 @@
import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.spi.JoranException;
-public abstract class AppenderFactoryBase<E, K> {
+public abstract class AppenderFactoryBase<E> {
final List<SaxEvent> eventList;
Context context;
@@ -35,9 +35,9 @@
System.out.println(eventList);
}
- public abstract SiftingJoranConfiguratorBase<E> getSiftingJoranConfigurator(K k);
+ public abstract SiftingJoranConfiguratorBase<E> getSiftingJoranConfigurator(String k);
- Appender<E> buildAppender(Context context, K k) throws JoranException {
+ Appender<E> buildAppender(Context context, String k) throws JoranException {
SiftingJoranConfiguratorBase<E> sjc = getSiftingJoranConfigurator(k);
sjc.setContext(context);
sjc.doConfigure(eventList);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java Fri Dec 19 19:24:52 2008
@@ -13,15 +13,15 @@
import ch.qos.logback.core.Appender;
-public interface AppenderTracker<E, K> {
+public interface AppenderTracker<E> {
static int MILLIS_IN_ONE_SECOND = 1000;
static int THRESHOLD = 30 * 60 * MILLIS_IN_ONE_SECOND; // 30 minutes
- void put(K key, Appender<E> value, long timestamp);
- Appender<E> get(K key, long timestamp);
+ void put(String key, Appender<E> value, long timestamp);
+ Appender<E> get(String key, long timestamp);
void stopStaleAppenders(long timestamp);
- List<K> keyList();
+ List<String> keyList();
List<Appender<E>> valueList();
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java Fri Dec 19 19:24:52 2008
@@ -21,9 +21,9 @@
* longer than THRESHOLD, stop it.
* @author Ceki Gulcu
*/
-public class AppenderTrackerImpl<E, K> implements AppenderTracker<E, K> {
+public class AppenderTrackerImpl<E> implements AppenderTracker<E> {
- Map<K, Entry> map = new HashMap<K, Entry>();
+ Map<String, Entry> map = new HashMap<String, Entry>();
Entry head; // least recently used entries are towards the head
Entry tail; // most recently used entries are towards the tail
@@ -36,7 +36,7 @@
}
- public synchronized void put(K key, Appender<E> value, long timestamp) {
+ public synchronized void put(String key, Appender<E> value, long timestamp) {
Entry entry = map.get(key);
if (entry == null) {
entry = new Entry(key, value, timestamp);
@@ -45,7 +45,7 @@
moveToTail(entry);
}
- public synchronized Appender<E> get(K key, long timestamp) {
+ public synchronized Appender<E> get(String key, long timestamp) {
Entry existing = map.get(key);
if (existing == null) {
return null;
@@ -70,8 +70,8 @@
}
}
- public List<K> keyList() {
- List<K> result = new LinkedList<K>();
+ public List<String> keyList() {
+ List<String> result = new LinkedList<String>();
Entry e = head;
while (e != tail) {
result.add(e.key);
@@ -151,11 +151,11 @@
Entry next;
Entry prev;
- K key;
+ String key;
Appender<E> value;
long timestamp;
- Entry(K k, Appender<E> v, long timestamp) {
+ Entry(String k, Appender<E> v, long timestamp) {
this.key = k;
this.value = v;
this.timestamp = timestamp;
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Fri Dec 19 19:24:52 2008
@@ -12,7 +12,6 @@
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.util.OptionHelper;
/**
* This appender can contains other appenders which it can build dynamically
@@ -24,13 +23,13 @@
*
* @author Ceki Gulcu
*/
-public abstract class SiftingAppenderBase<E, K> extends
+public abstract class SiftingAppenderBase<E> extends
UnsynchronizedAppenderBase<E> {
- protected AppenderTracker<E, K> appenderTracker = new AppenderTrackerImpl<E, K>();
- AppenderFactoryBase<E, K> appenderFactory;
+ protected AppenderTracker<E> appenderTracker = new AppenderTrackerImpl<E>();
+ AppenderFactoryBase<E> appenderFactory;
- public void setAppenderFactory(AppenderFactoryBase<E, K> appenderFactory) {
+ public void setAppenderFactory(AppenderFactoryBase<E> appenderFactory) {
this.appenderFactory = appenderFactory;
}
@@ -46,7 +45,7 @@
}
}
- abstract protected K getDiscriminatingValue(E event);
+ abstract protected String getDiscriminatingValue(E event);
abstract protected long getTimestamp(E event);
@Override
@@ -55,7 +54,7 @@
return;
}
- K value = getDiscriminatingValue(event);
+ String value = getDiscriminatingValue(event);
long timestamp = getTimestamp(event);
Appender<E> appender = appenderTracker.get(value, timestamp);
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java Fri Dec 19 19:24:52 2008
@@ -16,7 +16,7 @@
Context context = new ContextBase();
- AppenderTracker<Object, String> appenderTracker = new AppenderTrackerImpl<Object, String>();
+ AppenderTracker<Object> appenderTracker = new AppenderTrackerImpl<Object>();
ListAppender<Object> la = new ListAppender<Object>();
@Before
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java Fri Dec 19 19:24:52 2008
@@ -28,7 +28,7 @@
*/
public class Simulator {
- AppenderTrackerImpl<Object, String> appenderTracker = new AppenderTrackerImpl<Object, String>();
+ AppenderTrackerImpl<Object> appenderTracker = new AppenderTrackerImpl<Object>();
AppenderTrackerTImpl t_appenderTracker = new AppenderTrackerTImpl();
List<String> keySpace = new ArrayList<String>();
@@ -79,7 +79,7 @@
}
void play(SimulationEvent simulationEvent,
- AppenderTracker<Object, String> appenderTracker) {
+ AppenderTracker<Object> appenderTracker) {
String mdcValue = simulationEvent.key;
long timestamp = simulationEvent.timestamp;
Appender<Object> appender = appenderTracker.get(mdcValue, timestamp);
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java Fri Dec 19 19:24:52 2008
@@ -23,7 +23,7 @@
*
* @author Ceki Gulcu
*/
-public class AppenderTrackerTImpl implements AppenderTracker<Object, String> {
+public class AppenderTrackerTImpl implements AppenderTracker<Object> {
List<TEntry> entryList = new LinkedList<TEntry>();
long lastCheck = 0;
1
0
Author: ceki
Date: Fri Dec 19 17:10:55 2008
New Revision: 2092
Added:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java
- copied, changed from r2091, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java
- copied, changed from r2087, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java
logback/trunk/logback-examples/src/main/java/chapter6/duplicateMessage.xml
Removed:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java
logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml
logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml
logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
logback/trunk/logback-examples/src/main/java/chapter6/FilterEvents.java
logback/trunk/logback-examples/src/main/java/chapter6/basicConfiguration.xml
logback/trunk/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml
logback/trunk/logback-examples/src/main/java/chapter6/levelFilterConfig.xml
logback/trunk/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml
logback/trunk/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml
logback/trunk/logback-examples/src/main/java/chapter6/turboFilters.xml
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/news.html
logback/trunk/logback-site/src/site/pages/support.html
Log:
- Documentation on DuplicateMessageFilter
- Finished renaming HoardingAppender as SiftingAppender (as well as associated classes)
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java Fri Dec 19 17:10:55 2008
@@ -20,7 +20,7 @@
import ch.qos.logback.classic.joran.action.LevelAction;
import ch.qos.logback.classic.joran.action.LoggerAction;
import ch.qos.logback.classic.joran.action.RootLoggerAction;
-import ch.qos.logback.classic.sift.HoardAction;
+import ch.qos.logback.classic.sift.SiftAction;
import ch.qos.logback.classic.spi.PlatformInfo;
import ch.qos.logback.core.joran.JoranConfiguratorBase;
import ch.qos.logback.core.joran.action.AppenderRefAction;
@@ -53,8 +53,8 @@
rs.addRule(new Pattern("*/evaluator/matcher"),
new MatcherAction());
- rs.addRule(new Pattern("configuration/appender/hoard"), new HoardAction());
- rs.addRule(new Pattern("configuration/appender/hoard/*"), new NOPAction());
+ rs.addRule(new Pattern("configuration/appender/sift"), new SiftAction());
+ rs.addRule(new Pattern("configuration/appender/sift/*"), new NOPAction());
rs.addRule(new Pattern("configuration/logger"), new LoggerAction());
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java Fri Dec 19 17:10:55 2008
@@ -27,7 +27,7 @@
}
public SiftingJoranConfiguratorBase<LoggingEvent> getSiftingJoranConfigurator(String k) {
- return new HoardingJoranConfigurator(mdcKey, k);
+ return new SiftingJoranConfigurator(mdcKey, k);
}
}
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java (from r2091, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftAction.java Fri Dec 19 17:10:55 2008
@@ -11,7 +11,7 @@
import ch.qos.logback.core.joran.spi.ActionException;
import ch.qos.logback.core.joran.spi.InterpretationContext;
-public class HoardAction extends Action implements InPlayListener {
+public class SiftAction extends Action implements InPlayListener {
List<SaxEvent> seList;
@Override
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java (from r2087, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java Fri Dec 19 17:10:55 2008
@@ -12,12 +12,12 @@
import ch.qos.logback.core.joran.spi.RuleStore;
import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
-public class HoardingJoranConfigurator extends SiftingJoranConfiguratorBase<LoggingEvent> {
+public class SiftingJoranConfigurator extends SiftingJoranConfiguratorBase<LoggingEvent> {
String key;
String value;
- HoardingJoranConfigurator(String key, String value) {
+ SiftingJoranConfigurator(String key, String value) {
this.key = key;
this.value = value;
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java Fri Dec 19 17:10:55 2008
@@ -15,22 +15,36 @@
import ch.qos.logback.classic.Logger;
import ch.qos.logback.core.spi.FilterReply;
+/**
+ *
+ * See {@link http://logback.qos.ch/manual/filters.html#DuplicateMessageFilter}
+ * for details.
+ *
+ * @author Ceki Gulcu
+ *
+ */
public class DuplicateMessageFilter extends TurboFilter {
- static final int DEFAULT_CACHE_SIZE = 100;
- static final int DEFAULT_ALLOWED_REPETITIONS = 5;
-
+ /**
+ * The default cache size.
+ */
+ public static final int DEFAULT_CACHE_SIZE = 100;
+ /**
+ * The default number of allows repetitions.
+ */
+ public static final int DEFAULT_ALLOWED_REPETITIONS = 5;
+
public int allowedRepetitions = DEFAULT_ALLOWED_REPETITIONS;
public int cacheSize = DEFAULT_CACHE_SIZE;
-
+
private LRUMessageCache msgCache;
-
+
@Override
public void start() {
msgCache = new LRUMessageCache(cacheSize);
super.start();
}
-
+
@Override
public void stop() {
msgCache.clear();
@@ -42,7 +56,7 @@
public FilterReply decide(Marker marker, Logger logger, Level level,
String format, Object[] params, Throwable t) {
int count = msgCache.getMessageCount(format);
- if(count <= allowedRepetitions) {
+ if (count <= allowedRepetitions) {
return FilterReply.NEUTRAL;
} else {
return FilterReply.DENY;
@@ -53,6 +67,11 @@
return allowedRepetitions;
}
+ /**
+ * The allowed number of repetitions before
+ *
+ * @param allowedRepetitions
+ */
public void setAllowedRepetitions(int allowedRepetitions) {
this.allowedRepetitions = allowedRepetitions;
}
@@ -64,5 +83,5 @@
public void setCacheSize(int cacheSize) {
this.cacheSize = cacheSize;
}
-
+
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java Fri Dec 19 17:10:55 2008
@@ -29,7 +29,7 @@
int getMessageCount(String msg) {
Integer i = super.get(msg);
if(i == null) {
- i = 1;
+ i = 0;
} else {
i = new Integer(i.intValue()+1);
}
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml Fri Dec 19 17:10:55 2008
@@ -8,9 +8,9 @@
<mdcKey>cycle</mdcKey>
<defaultValue>cycleDefault</defaultValue>
- <hoard>
+ <sift>
<appender name="list-${cycle}" class="ch.qos.logback.core.read.ListAppender"/>
- </hoard>
+ </sift>
</appender>
<root level="DEBUG">
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml Fri Dec 19 17:10:55 2008
@@ -4,11 +4,11 @@
<configuration debug="true">
<appender name="SIFT"
- class="ch.qos.logback.classic.hoard.HoardingAppender">
+ class="ch.qos.logback.classic.sift.SiftingAppender">
<mdcKey>userid</mdcKey>
<default>asdad</default>
- <hoard>
+ <sift>
<appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
<File>${userid}.log</File>
<Append>true</Append>
@@ -16,7 +16,7 @@
<Pattern>%d [%thread] %level %logger{35} - %msg%n</Pattern>
</layout>
</appender>
- </hoard>
+ </sift>
</appender>
<root level="DEBUG">
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml Fri Dec 19 17:10:55 2008
@@ -8,9 +8,9 @@
<mdcKey>userid</mdcKey>
<defaultValue>smoke</defaultValue>
- <hoard>
+ <sift>
<appender name="list-${userid}" class="ch.qos.logback.core.read.ListAppender"/>
- </hoard>
+ </sift>
</appender>
<root level="DEBUG">
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java Fri Dec 19 17:10:55 2008
@@ -1,3 +1,12 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
package ch.qos.logback.classic.turbo;
import static org.junit.Assert.*;
@@ -13,7 +22,7 @@
@Test
public void smoke() {
DuplicateMessageFilter dmf = new DuplicateMessageFilter();
- dmf.setAllowedRepetitions(1);
+ dmf.setAllowedRepetitions(0);
dmf.start();
assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "x", null, null));
assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "y", null, null));
@@ -36,7 +45,7 @@
@Test
public void many() {
DuplicateMessageFilter dmf = new DuplicateMessageFilter();
- dmf.setAllowedRepetitions(1);
+ dmf.setAllowedRepetitions(0);
int cacheSize = 10;
int margin = 2;
dmf.setCacheSize(cacheSize);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Fri Dec 19 17:10:55 2008
@@ -28,12 +28,6 @@
UnsynchronizedAppenderBase<E> {
protected AppenderTracker<E, K> appenderTracker = new AppenderTrackerImpl<E, K>();
- // Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String,
- // Appender<LoggingEvent>>();
-
- String mdcKey;
- String defaultValue;
-
AppenderFactoryBase<E, K> appenderFactory;
public void setAppenderFactory(AppenderFactoryBase<E, K> appenderFactory) {
@@ -53,7 +47,6 @@
}
abstract protected K getDiscriminatingValue(E event);
-
abstract protected long getTimestamp(E event);
@Override
@@ -82,20 +75,4 @@
appender.doAppend(event);
}
- public String getMdcKey() {
- return mdcKey;
- }
-
- public void setMdcKey(String mdcKey) {
- this.mdcKey = mdcKey;
- }
-
- /**
- * @see #setDefaultValue(String)
- * @return
- */
- public String getDefaultValue() {
- return defaultValue;
- }
-
}
Modified: logback/trunk/logback-examples/src/main/java/chapter6/FilterEvents.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/FilterEvents.java (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/FilterEvents.java Fri Dec 19 17:10:55 2008
@@ -33,13 +33,13 @@
for (int i = 0; i < 10; i++) {
if (i == 3) {
MDC.put("username", "sebastien");
- logger.debug("logging statement " + i);
+ logger.debug("logging statement {}", i);
MDC.remove("username");
} else if (i == 6) {
Marker billing = MarkerFactory.getMarker("billing");
- logger.error(billing, "billing statement " + i);
+ logger.error(billing, "billing statement {}", i);
} else {
- logger.info("logging statement " + i);
+ logger.info("logging statement {}", i);
}
}
}
Modified: logback/trunk/logback-examples/src/main/java/chapter6/basicConfiguration.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/basicConfiguration.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/basicConfiguration.xml Fri Dec 19 17:10:55 2008
@@ -1,16 +1,12 @@
<configuration>
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>
- %-4relative [%thread] %-5level %logger - %msg%n
- </pattern>
- </layout>
- </appender>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
+ </layout>
+ </appender>
- <root>
- <level value="DEBUG" />
- <appender-ref ref="STDOUT" />
- </root>
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ </root>
</configuration>
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/basicEventEvaluator.xml Fri Dec 19 17:10:55 2008
@@ -1,23 +1,19 @@
<configuration debug="true">
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
- <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
- <evaluator name="myEval">
- <expression>message.contains("billing")</expression>
- </evaluator>
- <OnMismatch>NEUTRAL</OnMismatch>
- <OnMatch>DENY</OnMatch>
- </filter>
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>
- %-4relative [%thread] %-5level %logger - %msg%n
- </pattern>
- </layout>
- </appender>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator name="myEval">
+ <expression>message.contains("billing")</expression>
+ </evaluator>
+ <OnMismatch>NEUTRAL</OnMismatch>
+ <OnMatch>DENY</OnMatch>
+ </filter>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
+ </layout>
+ </appender>
- <root>
- <level value="DEBUG" />
- <appender-ref ref="STDOUT" />
- </root>
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ </root>
</configuration>
\ No newline at end of file
Added: logback/trunk/logback-examples/src/main/java/chapter6/duplicateMessage.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter6/duplicateMessage.xml Fri Dec 19 17:10:55 2008
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+ <turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter" />
+
+ <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
+ </layout>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="console" />
+ </root>
+</configuration>
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter6/levelFilterConfig.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/levelFilterConfig.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/levelFilterConfig.xml Fri Dec 19 17:10:55 2008
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
- <appender name="CONSOLE"
- class="ch.qos.logback.core.ConsoleAppender">
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>INFO</level>
- <onMatch>ACCEPT</onMatch>
- <onMismatch>DENY</onMismatch>
- </filter>
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>
- %-4relative [%thread] %-5level %logger{30} - %msg%n
- </pattern>
- </layout>
- </appender>
- <root>
- <level value="DEBUG" />
- <appender-ref ref="CONSOLE" />
- </root>
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
+ </layout>
+ </appender>
+ <root level="DEBUG">
+ <appender-ref ref="CONSOLE" />
+ </root>
</configuration>
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml Fri Dec 19 17:10:55 2008
@@ -1,19 +1,16 @@
<configuration>
- <turboFilter class="chapter6.SampleTurboFilter">
- <Marker>sample</Marker>
- </turboFilter>
+ <turboFilter class="chapter6.SampleTurboFilter">
+ <Marker>sample</Marker>
+ </turboFilter>
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>
- %-4relative [%thread] %-5level %logger - %msg%n
- </pattern>
- </layout>
- </appender>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
+ </layout>
+ </appender>
- <root>
- <appender-ref ref="STDOUT" />
- </root>
+ <root>
+ <appender-ref ref="STDOUT" />
+ </root>
</configuration>
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml Fri Dec 19 17:10:55 2008
@@ -1,19 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
- <appender name="CONSOLE"
- class="ch.qos.logback.core.ConsoleAppender">
- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
- <level>INFO</level>
- </filter>
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>
- %-4relative [%thread] %-5level %logger{30} - %msg%n
- </pattern>
- </layout>
- </appender>
- <root>
- <level value="DEBUG" />
- <appender-ref ref="CONSOLE" />
- </root>
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
+ </layout>
+ </appender>
+ <root level="DEBUG">
+ <appender-ref ref="CONSOLE" />
+ </root>
</configuration>
\ No newline at end of file
Modified: logback/trunk/logback-examples/src/main/java/chapter6/turboFilters.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter6/turboFilters.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter6/turboFilters.xml Fri Dec 19 17:10:55 2008
@@ -2,16 +2,16 @@
<configuration>
- <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
- <MDCKey>username</MDCKey>
- <Value>sebastien</Value>
- <OnMatch>ACCEPT</OnMatch>
- </turboFilter>
-
- <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
- <Marker>billing</Marker>
- <OnMatch>DENY</OnMatch>
- </turboFilter>
+ <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
+ <MDCKey>username</MDCKey>
+ <Value>sebastien</Value>
+ <OnMatch>ACCEPT</OnMatch>
+ </turboFilter>
+
+ <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
+ <Marker>billing</Marker>
+ <OnMatch>DENY</OnMatch>
+ </turboFilter>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
@@ -19,8 +19,7 @@
</layout>
</appender>
- <root>
- <level value="info"/>
+ <root level="info">
<appender-ref ref="console" />
- </root>
+ </root>
</configuration>
\ No newline at end of file
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 Fri Dec 19 17:10:55 2008
@@ -390,7 +390,7 @@
<p>The <a
href="../xref/chapter6/FilterEvents.html"><code>FilterEvents</code></a>
- class issues ten logging requests, numbered from 0 to 9. Let us
+ application issues ten logging requests, numbered 0 to 9. Let us
rist run <code>FilterEvents</code> class without any filters:
</p>
@@ -422,7 +422,7 @@
<p>we obtain:
</p>
-<div class="source"><pre>0 [main] INFO chapter6.FilterEvents - logging statement 0
+ <p class="source">0 [main] INFO chapter6.FilterEvents - logging statement 0
0 [main] INFO chapter6.FilterEvents - logging statement 1
0 [main] INFO chapter6.FilterEvents - logging statement 2
0 [main] DEBUG chapter6.FilterEvents - logging statement 3
@@ -430,11 +430,10 @@
0 [main] INFO chapter6.FilterEvents - logging statement 5
0 [main] INFO chapter6.FilterEvents - logging statement 7
0 [main] INFO chapter6.FilterEvents - logging statement 8
-0 [main] INFO chapter6.FilterEvents - logging statement 9</pre></div>
+0 [main] INFO chapter6.FilterEvents - logging statement 9</p>
- <a name="TurboFilter"></a>
- <h3>TurboFilters</h3>
+ <h2><a name="TurboFilter" href="#TurboFilter">TurboFilters</a></h2>
<p><code>TurboFilter</code> objects all extend the
<a href="../xref/ch/qos/logback/classic/turbo/TurboFilter.html">
@@ -601,31 +600,32 @@
</root>
</configuration></pre></div>
- <p>
- You can see this configuration in action by issuing the following command:
+ <p>You can see this configuration in action by issuing the
+ following command:
</p>
-<div class="source"><pre>
-java chapter6.FilterEvents src/main/java/chapter6/turboFilters.xml
-</pre></div>
+ <p class="source">java chapter6.FilterEvents src/main/java/chapter6/turboFilters.xml</p>
- <p>
- As we've seen previously, the <code>FilterEvents</code> class creates 10 logging requests,
- each with its number from 0 to 9. All of the requests are of level <em>INFO</em>,
- just like the configured overall level, except for two requests.
- The 3rd request, is a <em>DEBUG</em> level corresponding to the key <em>username</em>.
- This obviously satisfies the first <code>TurboFilter</code> declared in the previous
- configuration file. The 6th request, a <em>ERROR</em> level request,
- which is issued along with the <em>billing</em> marker, matches
- the second <code>TurboFilter</code>.
+ <p>As we've seen previously, the <a
+ href="../xref/chapter6/FilterEvents.html"><code>FilterEvents</code></a>
+ application issues 10 logging requests, numbered 0 to 9. Except
+ for requests 3 and 6, all of the requests are of level
+ <em>INFO</em>, the same level as the one assigned to the root
+ logger. The 3rd request, is issued at the the <em>DEBUG</em>
+ level, which is below the effective level. However, since the MDC
+ key "username" is set to "sebastien" just before the 3rd request
+ and removed just afterwards, the <code>MDCFilter</code>
+ specifically accepts the request (and only that request). The 6th
+ request, issued at the <em>ERROR</em> level, is marked as
+ "billing". As such, it is denied by the MarkerFilter (the second
+ turbo filter in the configuration).
</p>
- <p>
- Here is the output of the previous command:
+ <p>Thus, the output of <code>FilterEvents</code> application
+ configured with <em>turboFilters.xml</em> file shown above is:
</p>
-<div class="source"><pre>
-2006-12-04 15:17:22,859 [main] INFO chapter6.FilterEvents - logging statement 0
+ <p class="source">2006-12-04 15:17:22,859 [main] INFO chapter6.FilterEvents - logging statement 0
2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 1
2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 2
2006-12-04 15:17:22,875 [main] DEBUG chapter6.FilterEvents - logging statement 3
@@ -633,24 +633,119 @@
2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 5
2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 7
2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 8
-2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 9
-</pre></div>
+2006-12-04 15:17:22,875 [main] INFO chapter6.FilterEvents - logging statement 9</p>
- <p>
- One can see that the 3rd request, who should not be displayed if we
- only followed the overall <em>INFO</em> level, appears anyway, because
- it matched the first <code>TurboFilter</code> requirements and was accepted.
+ <p>One can see that the 3rd request, which should not be displayed
+ if we only followed the overall <em>INFO</em> level, appears
+ anyway, because it matched the first <code>TurboFilter</code>
+ requirements and was accepted.
</p>
- <p>
- On the other hand, the 6th request, that is a <em>ERROR</em> level request
- should have been displayed. But it satisfied the second <code>TurboFilter</code>
- whose <span class="option">OnMatch</span> option is set to <em>DENY</em>.
- Thus, the 6th request was not displayed.
+ <p>On the other hand, the 6th request, that is a <em>ERROR</em>
+ level request should have been displayed. But it satisfied the
+ second <code>TurboFilter</code> whose <span
+ class="option">OnMatch</span> option is set to <em>DENY</em>.
+ Thus, the 6th request was not displayed.
</p>
+
+
+ <h3><a name="DuplicateMessageFilter"
+ href="#DuplicateMessageFilter">DuplicateMessageFilter</a></h3>
+
+ <p>The <code>DuplicateMessageFilter</code> merits a separate
+ presentation. This filter detects duplicate messages, and beyond
+ a certain number of repetitions, drops repeated messages.
+ </p>
+
+ <p>To detect repetition, this filter uses simple String equality
+ between messages. It does not detect messages which are very
+ similar, varying only by few characters. For example, if you
+ write:
+ </p>
+
+ <p class="source">logger.debug("Hello "+name0);
+logger.debug("Hello "+name1);</p>
+
+ <p>Assuming <code>name0</code> and <code>name1</code> have
+ different values, the two "Hello" messages will be considered as
+ unrelated. Depending on user demand, future releases may check for
+ string similarity, eliminating repetitions of similar but not
+ identical messages.
+ </p>
+
+ <p>Note that in case of parameterized logging, only the raw
+ message is taken into consideration. For example, in the next two
+ requests, the raw messages, i.e. "Hello {}.", are identical, and
+ thus considered as repetitions.
+ </p>
+
+ <p class="source">logger.debug("Hello {}.", name0);
+logger.debug("Hello {}.", name1);</p>
+
+ <p>The number of allowed repetitions can be specified by the <span
+ class="option">AllowedRepetitions</span> property. For example, if
+ the said property is set to 1, then the 2nd and subsequent
+ occurrences of the same message will be dropped. Similarly, if the
+ said property is set to 2, then the 3rd and subsequent occurrences
+ of the same message will be dropped. By default, the <span
+ class="option">AllowedRepetitions</span> property is set to 5.
+ </p>
+
+ <p>In order to detect repetitions, this filter needs to keep
+ references to old messages in an internal cache. The size of this
+ cache is determined by the <span class="option">CacheSize</span>
+ property. By the default, this is set to 100.
+ </p>
+
+
+<em>Example: <code>DuplicateMessageFilter</code>
+configuration (logback-examples/src/main/java/chapter6/duplicateMessage.xml)</em>
+<div class="source"><pre><configuration>
+
+ <b><turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter"/></b>
+
+ <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
+ </layout>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="console" />
+ </root>
+</configuration></pre></div>
+
+ <p>Thus, the output for <code>FilterEvents</code> application
+ configured with <em>duplicateMessage.xml</em> is:
+ </p>
+
+ <p class="source">2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 0
+2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 1
+2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 2
+2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 4
+2008-12-19 15:04:26,156 [main] INFO chapter6.FilterEvents - logging statement 5
+2008-12-19 15:04:26,171 [main] ERROR chapter6.FilterEvents - billing statement 6</p>
+
+ <p>"logging statement 0" is the first <em>occurrence</em> of the
+ message "logging statement {}". "logging statement 1" is the first
+ <em>repetition</em>, "logging statement 2" is the second
+ repetition. Interestingly enough, "logging statement 3" of level
+ DEBUG, is the <em>third</em> repetition, even though it is later
+ dropped by virtue of the <a
+ href="architecture.html#basic_selection">basic selection
+ rule</a>. This can be explained by the fact that turbo filters are
+ invoked before other types of filters, including the basic
+ selection rule. Thus, <code>DuplicateMessageFilter</code>
+ considers "logging statement 3" as a repetition, oblivious to the
+ fact that it will be dropped further down in the processing
+ chain. "logging statement 4" is the fourth repetition and "logging
+ statement 5" the fifth. Statements 6 and beyond are dropped
+ because only 5 repetitions are allowed by default.
+ </p>
+
<h2>Logback-access</h2>
<p>Logback-access offers most of the features available with
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 Fri Dec 19 17:10:55 2008
@@ -414,12 +414,21 @@
</p>
<p>Given a <code>StatusManager</code> you an access all the status
- data associated with a logback context. You may also attach a
- <code>StatusListener</code> to a <code>StatusManager</code> so that
- you can take immediate action in response to status messages,
- especially to messages occuring after logback
- configuration. Registering a status listener is a convenient way to
- supervise logback's internal state without human intervention.
+ data associated with a logback context. To keep memory usage at
+ reasonable levels, the default <code>StatusManager</code>
+ implementation stores the status messages in two separate parts,
+ the header part and the tail part. The header part stores the fist
+ <em>H</em> status messages whereas the tail part stores the last
+ <em>T</em> messages. At present time <em>H</em>=<em>T</em>=150,
+ although these values may change in future releases.</p>
+
+
+ <p>You may also attach a <code>StatusListener</code> to a
+ <code>StatusManager</code> so that you can take immediate action in
+ response to status messages, especially to messages occurring after
+ logback configuration. Registering a status listener is a
+ convenient way to supervise logback's internal state without human
+ intervention.
</p>
<p>Logback ships with a <code>StatusListener</code> implementation
Modified: logback/trunk/logback-site/src/site/pages/news.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/news.html (original)
+++ logback/trunk/logback-site/src/site/pages/news.html Fri Dec 19 17:10:55 2008
@@ -29,6 +29,37 @@
<hr width="80%" align="center" />
+ <h3>xx of December 2008 - Release of version 0.9.14</h3>
+
+ <p>Corrected a serious dead-lock problem occuring during
+ configuration. It was reported in <a
+ href="http://jira.qos.ch/browse/LBCLASSIC-81">LBCLASSIC-81</a> by
+ Holger Mense.</p>
+
+ <p>Corrected thread leakage observed with
+ <code>TimeBasedRollingPolicy</code>'s
+ <code>AsynchronousCompressor</code>. This bug was reported in <a
+ href="http://jira.qos.ch/browse/LBCORE-78">LBCORE-78</a> by Szel
+ Zoltan.</p>
+
+ <p>Added <a
+ href="manual/filters.html#DuplicateMessageFilter">DuplicateMessageFilter</a>,
+ a turbo filter which detects duplicate messages, and beyond a
+ certain number of repetitions, drops repeated messages.</p>
+
+
+ <p><code>BasicStatusManager</code>'s internal buffer is now split
+ into two parts, the header part and the tail part. The header part
+ stores the fist H status messages whereas the tail part stores the
+ last T messages. At present time H=T=150, although these values may
+ change in future releases.</p>
+
+ <p>Fixed <code>NullPointerException</code> thrown when calling
+ <code>setContextMap</code> on a fresh MDC. <a
+ href="http://jira.qos.ch/browse/LBCLASSIC-98">Issue was</a>
+ reported by Francois Terrier.
+ </p>
+
<h3>5th of December 2008 - Release of version 0.9.13</h3>
<p>A <code>NullPointerException</code> was being thrown when a the
Modified: logback/trunk/logback-site/src/site/pages/support.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/support.html (original)
+++ logback/trunk/logback-site/src/site/pages/support.html Fri Dec 19 17:10:55 2008
@@ -30,15 +30,17 @@
<p>As the founders and current maintainers of the logback project,
we can offer you highest quality of support. Opting for our
- professional logback support service is a great way to leverage the
- expertise of developers who have in depth knowledge of the logback
- framework.
+ professional logback support service is a great way to leverage
+ the expertise of logback developers.
</p>
+ <p>If your project requires custom appenders or logback
+ extensions, we can also help you.
+ </p>
- <p>To obtain a quote for "Professional Support Contract" please do
- not hesitate to contact us. We will happy to discuss or help you
- with logging-related issues.</p>
+ <p>For a quote for "Professional Support Contract" please do not
+ hesitate to contact us. We will happy to discuss or help you with
+ logging-related issues.</p>
<table>
<tr>
1
0
18 Dec '08
Author: ceki
Date: Thu Dec 18 22:33:27 2008
New Revision: 2091
Added:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
- copied, changed from r2087, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java
logback/trunk/logback-classic/src/test/input/joran/sift/
- copied from r2086, /logback/trunk/logback-classic/src/test/input/joran/hoard/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java
Removed:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java
logback/trunk/logback-classic/src/test/input/joran/hoard/
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml
logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml
logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml
logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
Log:
SiftingAppender has been largely made generic by virtue of its migration to lb-core
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java Thu Dec 18 22:33:27 2008
@@ -25,8 +25,8 @@
public void end(InterpretationContext ec, String name) throws ActionException {
ec.removeInPlayListener(this);
Object o = ec.peekObject();
- if (o instanceof HoardingAppender) {
- HoardingAppender ha = (HoardingAppender) o;
+ if (o instanceof SiftingAppender) {
+ SiftingAppender ha = (SiftingAppender) o;
AppenderFactory appenderFactory = new AppenderFactory(context, seList, ha.getMdcKey());
ha.setAppenderFactory(appenderFactory);
}
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java (from r2087, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java Thu Dec 18 22:33:27 2008
@@ -12,6 +12,7 @@
import org.slf4j.MDC;
import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.sift.AppenderTracker;
import ch.qos.logback.core.sift.SiftingAppenderBase;
import ch.qos.logback.core.util.OptionHelper;
@@ -25,7 +26,7 @@
*
* @author Ceki Gulcu
*/
-public class HoardingAppender extends SiftingAppenderBase<LoggingEvent, String> {
+public class SiftingAppender extends SiftingAppenderBase<LoggingEvent, String> {
String mdcKey;
@@ -57,6 +58,10 @@
return mdcValue;
}
}
+
+ AppenderTracker<LoggingEvent, String> getAppenderTracker() {
+ return appenderTracker;
+ }
@Override
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml
==============================================================================
--- /logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/completeCycle.xml Thu Dec 18 22:33:27 2008
@@ -3,8 +3,8 @@
<configuration debug="true">
- <appender name="HOARD"
- class="ch.qos.logback.classic.hoard.HoardingAppender">
+ <appender name="SIFT"
+ class="ch.qos.logback.classic.sift.SiftingAppender">
<mdcKey>cycle</mdcKey>
<defaultValue>cycleDefault</defaultValue>
@@ -14,7 +14,7 @@
</appender>
<root level="DEBUG">
- <appender-ref ref="HOARD" />
+ <appender-ref ref="SIFT" />
</root>
</configuration>
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml
==============================================================================
--- /logback/trunk/logback-classic/src/test/input/joran/hoard/hoard0.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/hoard0.xml Thu Dec 18 22:33:27 2008
@@ -3,7 +3,7 @@
<configuration debug="true">
- <appender name="HOARD"
+ <appender name="SIFT"
class="ch.qos.logback.classic.hoard.HoardingAppender">
<mdcKey>userid</mdcKey>
@@ -20,7 +20,7 @@
</appender>
<root level="DEBUG">
- <appender-ref ref="HOARD" />
+ <appender-ref ref="SIFT" />
</root>
</configuration>
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml
==============================================================================
--- /logback/trunk/logback-classic/src/test/input/joran/hoard/smoke.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/smoke.xml Thu Dec 18 22:33:27 2008
@@ -3,8 +3,8 @@
<configuration debug="true">
- <appender name="HOARD"
- class="ch.qos.logback.classic.hoard.HoardingAppender">
+ <appender name="SIFT"
+ class="ch.qos.logback.classic.sift.SiftingAppender">
<mdcKey>userid</mdcKey>
<defaultValue>smoke</defaultValue>
@@ -14,7 +14,7 @@
</appender>
<root level="DEBUG">
- <appender-ref ref="HOARD" />
+ <appender-ref ref="SIFT" />
</root>
</configuration>
Modified: logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml
==============================================================================
--- /logback/trunk/logback-classic/src/test/input/joran/hoard/unsetDefaultValueProperty.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/sift/unsetDefaultValueProperty.xml Thu Dec 18 22:33:27 2008
@@ -3,17 +3,17 @@
<configuration debug="true">
- <appender name="HOARD"
- class="ch.qos.logback.classic.hoard.HoardingAppender">
+ <appender name="SIFT"
+ class="ch.qos.logback.classic.sift.SiftingAppender">
<mdcKey>userid</mdcKey>
- <hoard>
+ <sift>
<appender name="list-${userid}" class="ch.qos.logback.core.read.ListAppender"/>
- </hoard>
+ </sift>
</appender>
<root level="DEBUG">
- <appender-ref ref="HOARD" />
+ <appender-ref ref="SIFT" />
</root>
</configuration>
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java Thu Dec 18 22:33:27 2008
@@ -36,7 +36,6 @@
suite.addTest(new JUnit4TestAdapter(ch.qos.logback.classic.turbo.PackageTest.class));
suite.addTest(new JUnit4TestAdapter(
ch.qos.logback.classic.sift.PackageTest.class));
-
return suite;
}
}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java Thu Dec 18 22:33:27 2008
@@ -0,0 +1,19 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.sift;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+(a)RunWith(Suite.class)
+(a)SuiteClasses({SiftingAppenderTest.class})
+public class PackageTest {
+}
\ No newline at end of file
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java Thu Dec 18 22:33:27 2008
@@ -0,0 +1,95 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.sift;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.util.TeztConstants;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.read.ListAppender;
+import ch.qos.logback.core.sift.AppenderTracker;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class SiftingAppenderTest {
+
+ static String PREFIX = TeztConstants.TEST_DIR_PREFIX + "input/joran/sift/";
+
+ LoggerContext loggerContext = new LoggerContext();
+ Logger logger = loggerContext.getLogger(this.getClass().getName());
+ Logger root = loggerContext.getLogger(LoggerContext.ROOT_NAME);
+
+ void configure(String file) throws JoranException {
+ JoranConfigurator jc = new JoranConfigurator();
+ jc.setContext(loggerContext);
+ jc.doConfigure(file);
+ }
+
+ @Test
+ public void unsetDefaultValueProperty() throws JoranException {
+ configure(PREFIX + "unsetDefaultValueProperty.xml");
+ logger.debug("hello");
+ SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT");
+ assertFalse(ha.isStarted());
+
+ }
+
+ @Test
+ public void smoke() throws JoranException {
+ configure(PREFIX + "smoke.xml");
+ logger.debug("smoke");
+ long timestamp = 0;
+ SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.getAppenderTracker().get("smoke", timestamp);
+
+ StatusPrinter.print(loggerContext);
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+ }
+
+ @Test
+ public void testWholeCycle() throws JoranException {
+ String mdcKey = "cycle";
+ configure(PREFIX + "completeCycle.xml");
+ MDC.put(mdcKey, "a");
+ logger.debug("smoke");
+ long timestamp = System.currentTimeMillis();
+ SiftingAppender ha = (SiftingAppender) root.getAppender("SIFT");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.getAppenderTracker().get("a", timestamp);
+ StatusPrinter.print(loggerContext);
+
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+
+ MDC.remove(mdcKey);
+ LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, null);
+ le.setTimeStamp(timestamp+AppenderTracker.THRESHOLD*2);
+ ha.doAppend(le);
+ assertFalse(listAppender.isStarted());
+ assertEquals(1, ha.getAppenderTracker().keyList().size());
+ assertEquals("cycleDefault", ha.getAppenderTracker().keyList().get(0));
+
+ }
+}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Thu Dec 18 22:33:27 2008
@@ -9,7 +9,6 @@
*/
package ch.qos.logback.core.sift;
-
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.joran.spi.JoranException;
@@ -25,10 +24,12 @@
*
* @author Ceki Gulcu
*/
-public abstract class SiftingAppenderBase<E, K> extends UnsynchronizedAppenderBase<E> {
+public abstract class SiftingAppenderBase<E, K> extends
+ UnsynchronizedAppenderBase<E> {
protected AppenderTracker<E, K> appenderTracker = new AppenderTrackerImpl<E, K>();
- //Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String, Appender<LoggingEvent>>();
+ // Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String,
+ // Appender<LoggingEvent>>();
String mdcKey;
String defaultValue;
@@ -41,18 +42,7 @@
@Override
public void start() {
- int errors = 0;
- if (OptionHelper.isEmpty(mdcKey)) {
- errors++;
- addError("The \"mdcKey\" property must be set");
- }
- if (OptionHelper.isEmpty(defaultValue)) {
- errors++;
- addError("The \"defaultValue\" property must be set");
- }
- if (errors == 0) {
- super.start();
- }
+ super.start();
}
@Override
@@ -63,18 +53,18 @@
}
abstract protected K getDiscriminatingValue(E event);
+
abstract protected long getTimestamp(E event);
-
+
@Override
protected void append(E event) {
if (!isStarted()) {
return;
}
-
K value = getDiscriminatingValue(event);
long timestamp = getTimestamp(event);
-
+
Appender<E> appender = appenderTracker.get(value, timestamp);
if (appender == null) {
@@ -108,5 +98,4 @@
return defaultValue;
}
-
}
1
0
svn commit: r2090 - in logback/trunk/logback-core/src: main/java/ch/qos/logback/core/sift test/java/ch/qos/logback/core test/java/ch/qos/logback/core/sift
by noreply.cekiļ¼ qos.ch 18 Dec '08
by noreply.cekiļ¼ qos.ch 18 Dec '08
18 Dec '08
Author: ceki
Date: Thu Dec 18 22:22:44 2008
New Revision: 2090
Removed:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/SiftingAppenderTest.java
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java
Log:
SiftingAppender has been largely made generic by virtue of its migration to lb-core
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Thu Dec 18 22:22:44 2008
@@ -27,7 +27,7 @@
*/
public abstract class SiftingAppenderBase<E, K> extends UnsynchronizedAppenderBase<E> {
- AppenderTracker<E, K> appenderTracker = new AppenderTrackerImpl<E, K>();
+ protected AppenderTracker<E, K> appenderTracker = new AppenderTrackerImpl<E, K>();
//Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String, Appender<LoggingEvent>>();
String mdcKey;
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java Thu Dec 18 22:22:44 2008
@@ -22,7 +22,8 @@
ch.qos.logback.core.joran.PackageTest.class,
ch.qos.logback.core.appender.PackageTest.class,
ch.qos.logback.core.spi.PackageTest.class,
- ch.qos.logback.core.rolling.PackageTest.class})
+ ch.qos.logback.core.rolling.PackageTest.class,
+ ch.qos.logback.core.sift.PackageTest.class})
public class AllCoreTest {
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java Thu Dec 18 22:22:44 2008
@@ -8,8 +8,6 @@
import org.junit.Before;
import org.junit.Test;
-import ch.qos.logback.classic.sift.AppenderTracker;
-import ch.qos.logback.classic.sift.AppenderTrackerImpl;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.ContextBase;
import ch.qos.logback.core.read.ListAppender;
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java Thu Dec 18 22:22:44 2008
@@ -14,6 +14,6 @@
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
-(a)SuiteClasses({SiftingAppenderTest.class})
+(a)SuiteClasses({ScenarioBasedAppenderTrackerTest.class})
public class PackageTest {
}
\ No newline at end of file
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java Thu Dec 18 22:22:44 2008
@@ -14,8 +14,6 @@
import org.junit.Ignore;
import org.junit.Test;
-import ch.qos.logback.classic.sift.AppenderTracker;
-
public class ScenarioBasedAppenderTrackerTest {
Simulator simulator;
1
0
svn commit: r2089 - logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift
by noreply.cekiļ¼ qos.ch 18 Dec '08
by noreply.cekiļ¼ qos.ch 18 Dec '08
18 Dec '08
Author: ceki
Date: Thu Dec 18 22:13:35 2008
New Revision: 2089
Added:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/SiftingAppenderTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java
Log:
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/AppenderTrackerTest.java Thu Dec 18 22:13:35 2008
@@ -0,0 +1,63 @@
+package ch.qos.logback.core.sift;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.classic.sift.AppenderTracker;
+import ch.qos.logback.classic.sift.AppenderTrackerImpl;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.read.ListAppender;
+
+public class AppenderTrackerTest {
+
+
+ Context context = new ContextBase();
+ AppenderTracker<Object, String> appenderTracker = new AppenderTrackerImpl<Object, String>();
+ ListAppender<Object> la = new ListAppender<Object>();
+
+ @Before
+ public void setUp() {
+ la.setContext(context);
+ la.start();
+ }
+
+
+ @Test
+ public void empty0() {
+ long now = 3000;
+ appenderTracker.stopStaleAppenders(now);
+ assertEquals(0, appenderTracker.keyList().size());
+ }
+
+ @Test
+ public void empty1() {
+ long now = 3000;
+ assertNull(appenderTracker.get("a", now++));
+ now += AppenderTrackerImpl.THRESHOLD+1000;
+ appenderTracker.stopStaleAppenders(now);
+ assertNull(appenderTracker.get("a", now++));
+ }
+
+ @Test
+ public void smoke() {
+ assertTrue(la.isStarted());
+ long now = 3000;
+ appenderTracker.put("a", la, now);
+ assertEquals(la, appenderTracker.get("a", now++));
+ now += AppenderTrackerImpl.THRESHOLD+1000;
+ appenderTracker.stopStaleAppenders(now);
+ assertFalse(la.isStarted());
+ assertNull(appenderTracker.get("a", now++));
+ }
+
+ @Test
+ public void scenarioBased() {
+
+ }
+}
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/PackageTest.java Thu Dec 18 22:13:35 2008
@@ -0,0 +1,19 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+(a)RunWith(Suite.class)
+(a)SuiteClasses({SiftingAppenderTest.class})
+public class PackageTest {
+}
\ No newline at end of file
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/ScenarioBasedAppenderTrackerTest.java Thu Dec 18 22:13:35 2008
@@ -0,0 +1,55 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import ch.qos.logback.classic.sift.AppenderTracker;
+
+public class ScenarioBasedAppenderTrackerTest {
+
+ Simulator simulator;
+
+ void verify() {
+ AppenderTracker at = simulator.appenderTracker;
+ AppenderTracker t_at = simulator.t_appenderTracker;
+ //List<String> resultKeys = at.keyList();
+ //List<String> witnessKeys = t_at.keyList();
+ assertEquals(t_at.keyList(), at.keyList());
+ }
+
+ @Test
+ public void shortTest() {
+ simulator = new Simulator(20, AppenderTracker.THRESHOLD / 2);
+ simulator.buildScenario(200);
+ simulator.simulate();
+ verify();
+ }
+
+ @Test
+ public void mediumTest() {
+ simulator = new Simulator(100, AppenderTracker.THRESHOLD / 2);
+ simulator.buildScenario(20000);
+ simulator.simulate();
+ verify();
+ }
+
+ @Test
+ @Ignore
+ public void longetTest() {
+ simulator = new Simulator(100, AppenderTracker.THRESHOLD / 200);
+ simulator.buildScenario(2000000);
+ simulator.simulate();
+ verify();
+ }
+}
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/SiftingAppenderTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/SiftingAppenderTest.java Thu Dec 18 22:13:35 2008
@@ -0,0 +1,96 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.sift.AppenderTracker;
+import ch.qos.logback.classic.sift.HoardingAppender;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.util.TeztConstants;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.read.ListAppender;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class SiftingAppenderTest {
+
+ static String PREFIX = TeztConstants.TEST_DIR_PREFIX + "input/joran/hoard/";
+
+ LoggerContext loggerContext = new LoggerContext();
+ Logger logger = loggerContext.getLogger(this.getClass().getName());
+ Logger root = loggerContext.getLogger(LoggerContext.ROOT_NAME);
+
+ void configure(String file) throws JoranException {
+ JoranConfigurator jc = new JoranConfigurator();
+ jc.setContext(loggerContext);
+ jc.doConfigure(file);
+ }
+
+ @Test
+ public void unsetDefaultValueProperty() throws JoranException {
+ configure(PREFIX + "unsetDefaultValueProperty.xml");
+ logger.debug("hello");
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ assertFalse(ha.isStarted());
+
+ }
+
+ @Test
+ public void smoke() throws JoranException {
+ configure(PREFIX + "smoke.xml");
+ logger.debug("smoke");
+ long timestamp = 0;
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("smoke", timestamp);
+
+ StatusPrinter.print(loggerContext);
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+ }
+
+ @Test
+ public void testWholeCycle() throws JoranException {
+ String mdcKey = "cycle";
+ configure(PREFIX + "completeCycle.xml");
+ MDC.put(mdcKey, "a");
+ logger.debug("smoke");
+ long timestamp = System.currentTimeMillis();
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("a", timestamp);
+ StatusPrinter.print(loggerContext);
+
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+
+ MDC.remove(mdcKey);
+ LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, null);
+ le.setTimeStamp(timestamp+AppenderTracker.THRESHOLD*2);
+ ha.doAppend(le);
+ assertFalse(listAppender.isStarted());
+ assertEquals(1, ha.appenderTracker.keyList().size());
+ assertEquals("cycleDefault", ha.appenderTracker.keyList().get(0));
+
+ }
+}
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/Simulator.java Thu Dec 18 22:13:35 2008
@@ -0,0 +1,92 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.appender.NOPAppender;
+import ch.qos.logback.core.sift.tracker.AppenderTrackerTImpl;
+import ch.qos.logback.core.sift.tracker.SimulationEvent;
+
+/**
+ * Simulate use of AppenderTracker by HoardAppender.
+ *
+ * @author ceki
+ *
+ */
+public class Simulator {
+
+ AppenderTrackerImpl<Object, String> appenderTracker = new AppenderTrackerImpl<Object, String>();
+ AppenderTrackerTImpl t_appenderTracker = new AppenderTrackerTImpl();
+
+ List<String> keySpace = new ArrayList<String>();
+ List<SimulationEvent> scenario = new ArrayList<SimulationEvent>();
+ Random randomKeyGen = new Random(100);
+
+ Random random = new Random(11234);
+
+ final int maxTimestampInc;
+ long timestamp = 30000;
+
+ Simulator(int keySpaceLen, int maxTimestampInc) {
+ this.maxTimestampInc = maxTimestampInc;
+ Map<String, String> checkMap = new HashMap<String, String>();
+ for (int i = 0; i < keySpaceLen; i++) {
+ String k = getRandomKeyStr();
+ if (checkMap.containsKey(k)) {
+ System.out.println("random key collision occured");
+ k += "" + i;
+ }
+ keySpace.add(k);
+ checkMap.put(k, k);
+ }
+
+ }
+
+ private String getRandomKeyStr() {
+ int ri = randomKeyGen.nextInt();
+ String s = String.format("%X", ri);
+ return s;
+ }
+
+ void buildScenario(int simLen) {
+ int keySpaceLen = keySpace.size();
+ for (int i = 0; i < simLen; i++) {
+ int index = random.nextInt(keySpaceLen);
+ timestamp += random.nextInt(maxTimestampInc);
+ String key = keySpace.get(index);
+ scenario.add(new SimulationEvent(key, timestamp));
+ }
+ }
+
+ public void simulate() {
+ for (SimulationEvent simeEvent : scenario) {
+ play(simeEvent, appenderTracker);
+ play(simeEvent, t_appenderTracker);
+ }
+ }
+
+ void play(SimulationEvent simulationEvent,
+ AppenderTracker<Object, String> appenderTracker) {
+ String mdcValue = simulationEvent.key;
+ long timestamp = simulationEvent.timestamp;
+ Appender<Object> appender = appenderTracker.get(mdcValue, timestamp);
+ if (appender == null) {
+ appender = new NOPAppender<Object>();
+ appenderTracker.put(mdcValue, appender, timestamp);
+ }
+ appenderTracker.stopStaleAppenders(timestamp);
+ }
+}
1
0
svn commit: r2088 - logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker
by noreply.cekiļ¼ qos.ch 18 Dec '08
by noreply.cekiļ¼ qos.ch 18 Dec '08
18 Dec '08
Author: ceki
Date: Thu Dec 18 22:12:54 2008
New Revision: 2088
Added:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java
Log:
heavy refactorization
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/AppenderTrackerTImpl.java Thu Dec 18 22:12:54 2008
@@ -0,0 +1,98 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift.tracker;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.sift.AppenderTracker;
+
+/**
+ * This is an alternative (slower) implementation of AppenderTracker for testing
+ * purposes.
+ *
+ * @author Ceki Gulcu
+ */
+public class AppenderTrackerTImpl implements AppenderTracker<Object, String> {
+
+ List<TEntry> entryList = new LinkedList<TEntry>();
+ long lastCheck = 0;
+
+ public AppenderTrackerTImpl() {
+ }
+
+ @SuppressWarnings("unchecked")
+ synchronized public void put(String k, Appender<Object> appender,
+ long timestamp) {
+ TEntry te = getEntry(k);
+ if (te != null) {
+ te.timestamp = timestamp;
+ } else {
+ te = new TEntry(k, appender, timestamp);
+ entryList.add(te);
+ }
+ Collections.sort(entryList);
+ }
+
+ @SuppressWarnings("unchecked")
+ synchronized public Appender<Object> get(String k, long timestamp) {
+ TEntry te = getEntry(k);
+ if (te == null) {
+ return null;
+ } else {
+ te.timestamp = timestamp;
+ Collections.sort(entryList);
+ return te.appender;
+ }
+ }
+
+ synchronized public void stopStaleAppenders(long timestamp) {
+ if (lastCheck + MILLIS_IN_ONE_SECOND > timestamp) {
+ return;
+ }
+ lastCheck = timestamp;
+ while (entryList.size() != 0 && isEntryStale(entryList.get(0), timestamp)) {
+ entryList.remove(0);
+ }
+ }
+
+ final private boolean isEntryStale(TEntry entry, long now) {
+ return ((entry.timestamp + THRESHOLD) < now);
+ }
+
+ synchronized public List<String> keyList() {
+ List<String> keyList = new ArrayList<String>();
+ for (TEntry e : entryList) {
+ keyList.add(e.key);
+ }
+ return keyList;
+ }
+
+ synchronized public List<Appender<Object>> valueList() {
+ List<Appender<Object>> appenderList = new ArrayList<Appender<Object>>();
+ for (TEntry e : entryList) {
+ appenderList.add(e.appender);
+ }
+ return appenderList;
+ }
+
+ private TEntry getEntry(String k) {
+ for (int i = 0; i < entryList.size(); i++) {
+ TEntry te = entryList.get(i);
+ if (te.key.equals(k)) {
+ return te;
+ }
+ }
+ return null;
+ }
+}
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/SimulationEvent.java Thu Dec 18 22:12:54 2008
@@ -0,0 +1,17 @@
+package ch.qos.logback.core.sift.tracker;
+
+
+public class SimulationEvent {
+
+ public String key;
+ public long timestamp;
+
+ public SimulationEvent(String key, long timestamp) {
+ this.key = key;
+ this.timestamp = timestamp;
+ }
+
+ public String toString() {
+ return "Event: k=" + key +", timestamp=" + timestamp;
+ }
+}
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/tracker/TEntry.java Thu Dec 18 22:12:54 2008
@@ -0,0 +1,45 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift.tracker;
+
+import ch.qos.logback.core.Appender;
+
+public class TEntry implements Comparable {
+
+ String key;
+ long timestamp;
+ Appender<Object> appender;
+
+ TEntry(String key, Appender<Object> appender, long timestamp) {
+ this.key = key;
+ this.appender = appender;
+ this.timestamp = timestamp;
+ }
+
+ public int compareTo(Object o) {
+ if(!(o instanceof TEntry)) {
+ throw new IllegalArgumentException("arguments must be of type "+TEntry.class);
+ }
+
+ TEntry other = (TEntry) o;
+ if(timestamp > other.timestamp) {
+ return 1;
+ }
+ if(timestamp == other.timestamp) {
+ return 0;
+ }
+ return -1;
+ }
+
+ @Override
+ public String toString() {
+ return "("+key+","+timestamp+")";
+ }
+}
1
0
svn commit: r2087 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic/sift logback-classic/src/test/java/ch/qos/logback/classic/hoard logback-classic/src/test/java/ch/qos/logback/classic/sift logback-core/src/main/java/ch/qos/logback/core/sift logback-core/src/test/java/ch/qos/logback/core/sift
by noreply.cekiļ¼ qos.ch 18 Dec '08
by noreply.cekiļ¼ qos.ch 18 Dec '08
18 Dec '08
Author: ceki
Date: Thu Dec 18 22:11:36 2008
New Revision: 2087
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
- copied, changed from r2086, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java
- copied, changed from r2086, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/sift/
Removed:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTracker.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTrackerImpl.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
Log:
- heavy refactorization of SiftingAppender
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java Thu Dec 18 22:11:36 2008
@@ -1,49 +1,33 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
package ch.qos.logback.classic.sift;
-import java.util.ArrayList;
import java.util.List;
import ch.qos.logback.classic.spi.LoggingEvent;
-import ch.qos.logback.core.Appender;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.joran.event.SaxEvent;
-import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.util.StatusPrinter;
+import ch.qos.logback.core.sift.AppenderFactoryBase;
+import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
-public class AppenderFactory {
+public class AppenderFactory extends AppenderFactoryBase<LoggingEvent, String>{
- final List<SaxEvent> eventList;
- Context context;
+ String mdcKey;
- AppenderFactory(Context context, List<SaxEvent> eventList) {
- this.context = context;
- this.eventList = new ArrayList<SaxEvent>(eventList);
- removeHoardElement();
-
- }
-
- void removeHoardElement() {
- eventList.remove(0);
- eventList.remove(eventList.size() - 1);
- System.out.println(eventList);
- }
-
- Appender<LoggingEvent> buildAppender(Context context, String mdcKey,
- String mdcValue) throws JoranException {
- //HoardingContext hoardingContext = new HoardingContext(context, mdcKey,
- // mdcValue);
- HoardingJoranConfigurator hjc = new HoardingJoranConfigurator(mdcKey, mdcValue);
- hjc.setContext(context);
-
- hjc.doConfigure(eventList);
-
- StatusPrinter.print(context);
-
- return hjc.getAppender();
+ AppenderFactory(Context context, List<SaxEvent> eventList, String mdcKey) {
+ super(context, eventList);
+ this.mdcKey = mdcKey;
}
- public List<SaxEvent> getEventList() {
- return eventList;
+ public SiftingJoranConfiguratorBase<LoggingEvent> getSiftingJoranConfigurator(String k) {
+ return new HoardingJoranConfigurator(mdcKey, k);
}
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java Thu Dec 18 22:11:36 2008
@@ -27,7 +27,7 @@
Object o = ec.peekObject();
if (o instanceof HoardingAppender) {
HoardingAppender ha = (HoardingAppender) o;
- AppenderFactory appenderFactory = new AppenderFactory(context, seList);
+ AppenderFactory appenderFactory = new AppenderFactory(context, seList, ha.getMdcKey());
ha.setAppenderFactory(appenderFactory);
}
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java Thu Dec 18 22:11:36 2008
@@ -12,9 +12,7 @@
import org.slf4j.MDC;
import ch.qos.logback.classic.spi.LoggingEvent;
-import ch.qos.logback.core.Appender;
-import ch.qos.logback.core.UnsynchronizedAppenderBase;
-import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.sift.SiftingAppenderBase;
import ch.qos.logback.core.util.OptionHelper;
/**
@@ -27,19 +25,12 @@
*
* @author Ceki Gulcu
*/
-public class HoardingAppender extends UnsynchronizedAppenderBase<LoggingEvent> {
+public class HoardingAppender extends SiftingAppenderBase<LoggingEvent, String> {
- AppenderTracker<LoggingEvent> appenderTracker = new AppenderTrackerImpl<LoggingEvent>();
- //Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String, Appender<LoggingEvent>>();
String mdcKey;
String defaultValue;
- AppenderFactory appenderFactory;
-
- void setAppenderFactory(AppenderFactory appenderFactory) {
- this.appenderFactory = appenderFactory;
- }
@Override
public void start() {
@@ -58,43 +49,22 @@
}
@Override
- public void stop() {
- for (Appender<LoggingEvent> appender : appenderTracker.valueList()) {
- appender.stop();
- }
- }
-
- @Override
- protected void append(LoggingEvent loggingEvent) {
- if (!isStarted()) {
- return;
- }
-
+ protected String getDiscriminatingValue(LoggingEvent event) {
String mdcValue = MDC.get(mdcKey);
-
if (mdcValue == null) {
- mdcValue = defaultValue;
+ return defaultValue;
+ } else {
+ return mdcValue;
}
+ }
- long timestamp = loggingEvent.getTimeStamp();
-
- Appender<LoggingEvent> appender = appenderTracker.get(mdcValue, timestamp);
-
- if (appender == null) {
- try {
- appender = appenderFactory.buildAppender(context, mdcKey, mdcValue);
- if (appender != null) {
- appenderTracker.put(mdcValue, appender, timestamp);
- }
- } catch (JoranException e) {
- addError("Failed to build appender for " + mdcKey + "=" + mdcValue, e);
- return;
- }
- }
- appenderTracker.stopStaleAppenders(timestamp);
- appender.doAppend(loggingEvent);
+
+ @Override
+ protected long getTimestamp(LoggingEvent event) {
+ return event.getTimeStamp();
}
+
public String getMdcKey() {
return mdcKey;
}
@@ -127,4 +97,6 @@
this.defaultValue = defaultValue;
}
+
+
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java Thu Dec 18 22:11:36 2008
@@ -6,16 +6,13 @@
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
-import ch.qos.logback.core.joran.GenericConfigurator;
import ch.qos.logback.core.joran.action.ActionConst;
import ch.qos.logback.core.joran.action.AppenderAction;
-import ch.qos.logback.core.joran.action.NestedBasicPropertyIA;
-import ch.qos.logback.core.joran.action.NestedComplexPropertyIA;
-import ch.qos.logback.core.joran.spi.Interpreter;
import ch.qos.logback.core.joran.spi.Pattern;
import ch.qos.logback.core.joran.spi.RuleStore;
+import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
-public class HoardingJoranConfigurator extends GenericConfigurator {
+public class HoardingJoranConfigurator extends SiftingJoranConfiguratorBase<LoggingEvent> {
String key;
String value;
@@ -24,23 +21,13 @@
this.key = key;
this.value = value;
}
+
@Override
protected Pattern initialPattern() {
return new Pattern("configuration");
}
@Override
- protected void addImplicitRules(Interpreter interpreter) {
- NestedComplexPropertyIA nestedComplexIA = new NestedComplexPropertyIA();
- nestedComplexIA.setContext(context);
- interpreter.addImplicitAction(nestedComplexIA);
-
- NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA();
- nestedSimpleIA.setContext(context);
- interpreter.addImplicitAction(nestedSimpleIA);
- }
-
- @Override
protected void addInstanceRules(RuleStore rs) {
rs.addRule(new Pattern("configuration/appender"), new AppenderAction());
}
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java (from r2086, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java Thu Dec 18 22:11:36 2008
@@ -1,3 +1,12 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * 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
+ * Software Foundation.
+ */
package ch.qos.logback.core.sift;
import java.util.ArrayList;
@@ -8,12 +17,12 @@
import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.spi.JoranException;
-public abstract class AppenderFactory<E, K> {
+public abstract class AppenderFactoryBase<E, K> {
final List<SaxEvent> eventList;
Context context;
- AppenderFactory(Context context, List<SaxEvent> eventList) {
+ protected AppenderFactoryBase(Context context, List<SaxEvent> eventList) {
this.context = context;
this.eventList = new ArrayList<SaxEvent>(eventList);
removeHoardElement();
@@ -26,11 +35,10 @@
System.out.println(eventList);
}
-
- abstract SiftingJoranConfigurator<E> getSiftingJoranConfigurator(K k);
+ public abstract SiftingJoranConfiguratorBase<E> getSiftingJoranConfigurator(K k);
Appender<E> buildAppender(Context context, K k) throws JoranException {
- SiftingJoranConfigurator<E> sjc = getSiftingJoranConfigurator(k);
+ SiftingJoranConfiguratorBase<E> sjc = getSiftingJoranConfigurator(k);
sjc.setContext(context);
sjc.doConfigure(eventList);
return sjc.getAppender();
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java Thu Dec 18 22:11:36 2008
@@ -19,7 +19,7 @@
static int THRESHOLD = 30 * 60 * MILLIS_IN_ONE_SECOND; // 30 minutes
void put(K key, Appender<E> value, long timestamp);
- Appender<E> get(String key, long timestamp);
+ Appender<E> get(K key, long timestamp);
void stopStaleAppenders(long timestamp);
List<K> keyList();
List<Appender<E>> valueList();
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java Thu Dec 18 22:11:36 2008
@@ -45,7 +45,7 @@
moveToTail(entry);
}
- public synchronized Appender<E> get(String key, long timestamp) {
+ public synchronized Appender<E> get(K key, long timestamp) {
Entry existing = map.get(key);
if (existing == null) {
return null;
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Thu Dec 18 22:11:36 2008
@@ -33,9 +33,9 @@
String mdcKey;
String defaultValue;
- AppenderFactory<E, K> appenderFactory;
+ AppenderFactoryBase<E, K> appenderFactory;
- void setAppenderFactory(AppenderFactory<E, K> appenderFactory) {
+ public void setAppenderFactory(AppenderFactoryBase<E, K> appenderFactory) {
this.appenderFactory = appenderFactory;
}
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java (from r2086, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java Thu Dec 18 22:11:36 2008
@@ -2,22 +2,22 @@
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.joran.GenericConfigurator;
+import ch.qos.logback.core.joran.action.NestedBasicPropertyIA;
+import ch.qos.logback.core.joran.action.NestedComplexPropertyIA;
import ch.qos.logback.core.joran.spi.Interpreter;
-import ch.qos.logback.core.joran.spi.RuleStore;
-public abstract class SiftingJoranConfigurator<E> extends GenericConfigurator {
+public abstract class SiftingJoranConfiguratorBase<E> extends GenericConfigurator {
@Override
protected void addImplicitRules(Interpreter interpreter) {
- // TODO Auto-generated method stub
+ NestedComplexPropertyIA nestedComplexIA = new NestedComplexPropertyIA();
+ nestedComplexIA.setContext(context);
+ interpreter.addImplicitAction(nestedComplexIA);
+ NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA();
+ nestedSimpleIA.setContext(context);
+ interpreter.addImplicitAction(nestedSimpleIA);
}
-
- @Override
- protected void addInstanceRules(RuleStore rs) {
- // TODO Auto-generated method stub
-
- }
-
- abstract Appender<E> getAppender();
+
+ abstract public Appender<E> getAppender();
}
1
0