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

[JIRA] Created: (LBCLASSIC-96) verify the newly built appender depends on the mdc value
by Ceki Gulcu (JIRA) 23 Dec '08
by Ceki Gulcu (JIRA) 23 Dec '08
23 Dec '08
verify the newly built appender depends on the mdc value
--------------------------------------------------------
Key: LBCLASSIC-96
URL: http://jira.qos.ch/browse/LBCLASSIC-96
Project: logback-classic
Issue Type: Sub-task
Reporter: Ceki Gulcu
Assignee: Logback dev list
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
3
HoardingAppender
----------------
Key: LBCLASSIC-92
URL: http://jira.qos.ch/browse/LBCLASSIC-92
Project: logback-classic
Issue Type: Task
Components: appender
Affects Versions: 0.9.14
Reporter: Ceki Gulcu
Assignee: Ceki Gulcu
HoardingAppender related tasks
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
2
clean up appenders
-------------------
Key: LBCLASSIC-94
URL: http://jira.qos.ch/browse/LBCLASSIC-94
Project: logback-classic
Issue Type: Sub-task
Reporter: Ceki Gulcu
Assignee: Logback dev list
Fix For: 0.9.14
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
3

svn commit: r2100 - in logback/trunk: logback-access/src/main/java/ch/qos/logback/access/sift logback-access/src/test/input/jetty logback-core/src/main/java/ch/qos/logback/core/joran/action 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 22:22:24 2008
New Revision: 2100
Added:
logback/trunk/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml
Removed:
logback/trunk/logback-access/src/test/input/jetty/siftingFile.xml
Modified:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java
logback/trunk/logback-site/src/site/pages/manual/appenders.html
Log:
- improved docs
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 22:22:24 2008
@@ -38,7 +38,9 @@
* REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS,
* LOCAL_PORT,REQUEST_URI
*
- * <p> The first three fields require an additional key.
+ * <p> The first three fields require an additional key. For the
+ * SESSION_ATTRIBUTE field, the additional key named "id" has special meaning
+ * as it is mapped to the session id of the current http request.
*/
public enum FieldName {
COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI
@@ -61,16 +63,19 @@
public String getRawDiscriminatingValue(AccessEvent acccessEvent) {
switch (fieldName) {
case COOKIE:
+ // tested
return acccessEvent.getCookie(additionalKey);
case LOCAL_PORT:
return String.valueOf(acccessEvent.getLocalPort());
case REQUEST_ATTRIBUTE:
+ // tested
return getRequestAttribute(acccessEvent);
case SESSION_ATTRIBUTE:
return getSessionAttribute(acccessEvent);
case REMOTE_ADDRESS:
return acccessEvent.getRemoteAddr();
case REQUEST_URI:
+ // tested
return getRequestURI(acccessEvent);
default:
return null;
@@ -79,13 +84,13 @@
private String getRequestAttribute(AccessEvent acccessEvent) {
String attr = acccessEvent.getAttribute(additionalKey);
- if(AccessEvent.NA.equals(attr)) {
+ if (AccessEvent.NA.equals(attr)) {
return null;
} else {
return attr;
}
}
-
+
private String getRequestURI(AccessEvent acccessEvent) {
String uri = acccessEvent.getRequestURI();
if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') {
@@ -97,18 +102,9 @@
private String getSessionAttribute(AccessEvent acccessEvent) {
HttpServletRequest req = acccessEvent.getRequest();
- System.out.println("req=" + req);
if (req != null) {
HttpSession session = req.getSession(false);
- System.out.println("session=" + session);
if (session != null) {
- Enumeration ee = session.getAttributeNames();
- while(ee.hasMoreElements()) {
- String k = (String) ee.nextElement();
- Object v = session.getAttribute(k);
- System.out.println("Session "+k+"="+v);
- }
-
if ("id".equalsIgnoreCase(additionalKey)) {
return session.getId();
} else {
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderRefAction.java Tue Dec 23 22:22:24 2008
@@ -1,7 +1,7 @@
/**
- * LOGBack: the generic, reliable, fast and flexible logging framework.
+ * Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 1999-2006, QOS.ch
+ * Copyright (C) 2000-2008, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
Added: logback/trunk/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter4/sift/access-siftingFile.xml Tue Dec 23 22:22:24 2008
@@ -0,0 +1,22 @@
+<configuration>
+
+ <appender name="SIFTING"
+ class="ch.qos.logback.access.sift.SiftingAppender">
+ <Discriminator>
+ <Key>id</Key>
+ <FieldName>SESSION_ATTRIBUTE</FieldName>
+ <AdditionalKey>username</AdditionalKey>
+ <DefaultValue>NA</DefaultValue>
+ </Discriminator>
+ <sift>
+ <appender name="${id}" class="ch.qos.logback.core.FileAppender">
+ <File>byUser/${id}.log</File>
+ <layout class="ch.qos.logback.access.PatternLayout">
+ <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
+ </layout>
+ </appender>
+ </sift>
+ </appender>
+
+ <appender-ref ref="SIFTING" />
+</configuration>
\ No newline at end of file
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 22:22:24 2008
@@ -3512,11 +3512,47 @@
<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
+ REQUEST_URI. Note that the first three fields require that the
+ <span class="option">AdditionalKey</span> property also to be
specified.</p>
+ <p>Below is an example configuration file.</p>
+ <em>Example 4.<span class="autoEx"/>: SiftingAppender configuration (logback-examples/src/main/java/chapter4/conf/sift/access-siftingFile.xml)</em>
+
+ <p class="source"><configuration>
+ <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
+ <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+ <Key>id</Key>
+ <FieldName>SESSION_ATTRIBUTE</FieldName>
+ <AdditionalKey>username</AdditionalKey>
+ <DefaultValue>NA</DefaultValue>
+ </Discriminator>
+ <sift>
+ <appender name="${id}" class="ch.qos.logback.core.FileAppender">
+ <File>byUser/${id}.log</File>
+ <layout class="ch.qos.logback.access.PatternLayout">
+ <Pattern>%h %l %u %t \"%r\" %s %b</Pattern>
+ </layout>
+ </appender>
+ </sift>
+ </appender>
+ <appender-ref ref="SIFTING" />
+</configuration></p>
+
+
+ <p>In the above configuration file, a <code>SiftingAppender</code>
+ nests <code>FileAppender</code> instances. The key "id" is
+ designated as a variable which will be availabe to the nested
+ <code>FileAppender</code> instances. The default discriminator,
+ namely <code>AccessEventDiscriminator</code>, will search for
+ "username" session attribute in each <code>AccessEvent</code>. If
+ no such attribute is available, then the default value "NA" will
+ be used. Thus, assuming the session attribute named "username"
+ contains the username of each logged on user, there will be a log
+ file under the <em>byUser/</em> folder (of the current folder)
+ named after each user containing the access logs for that user.
+ </p>
<script src="../templates/footer.js" type="text/javascript"></script>
1
0

svn commit: r2099 - logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift
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 21:33:14 2008
New Revision: 2099
Modified:
logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
Log:
- minor changes
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 21:33:14 2008
@@ -9,6 +9,8 @@
*/
package ch.qos.logback.access.sift;
+import java.util.Enumeration;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@@ -18,11 +20,11 @@
/**
*
- * AccessEventDiscriminator's job is to return the value of a designated field in
- * an {@link AccessEvent} instance.
+ * 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.
*
- * <p>The field is specified via the {@link FieldName} property.
-
* @author Ceki Gülcü
*
*/
@@ -32,8 +34,8 @@
boolean started = false;
/**
- * At present time the followed fields can be designated:
- * COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS,
+ * At present time the followed fields can be designated: COOKIE,
+ * REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS,
* LOCAL_PORT,REQUEST_URI
*
* <p> The first three fields require an additional key.
@@ -63,7 +65,7 @@
case LOCAL_PORT:
return String.valueOf(acccessEvent.getLocalPort());
case REQUEST_ATTRIBUTE:
- return acccessEvent.getAttribute(additionalKey);
+ return getRequestAttribute(acccessEvent);
case SESSION_ATTRIBUTE:
return getSessionAttribute(acccessEvent);
case REMOTE_ADDRESS:
@@ -75,6 +77,15 @@
}
}
+ private String getRequestAttribute(AccessEvent acccessEvent) {
+ String attr = acccessEvent.getAttribute(additionalKey);
+ if(AccessEvent.NA.equals(attr)) {
+ return null;
+ } else {
+ return attr;
+ }
+ }
+
private String getRequestURI(AccessEvent acccessEvent) {
String uri = acccessEvent.getRequestURI();
if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') {
@@ -86,12 +97,25 @@
private String getSessionAttribute(AccessEvent acccessEvent) {
HttpServletRequest req = acccessEvent.getRequest();
+ System.out.println("req=" + req);
if (req != null) {
HttpSession session = req.getSession(false);
+ System.out.println("session=" + session);
if (session != null) {
- Object v = session.getAttribute(additionalKey);
- if (v != null) {
- return v.toString();
+ Enumeration ee = session.getAttributeNames();
+ while(ee.hasMoreElements()) {
+ String k = (String) ee.nextElement();
+ Object v = session.getAttribute(k);
+ System.out.println("Session "+k+"="+v);
+ }
+
+ if ("id".equalsIgnoreCase(additionalKey)) {
+ return session.getId();
+ } else {
+ Object v = session.getAttribute(additionalKey);
+ if (v != null) {
+ return v.toString();
+ }
}
}
}
@@ -119,7 +143,8 @@
case REQUEST_ATTRIBUTE:
case COOKIE:
if (additionalKey == null) {
- addError("\"OptionalKey\" property is mandatory for field name "+fieldName.toString());
+ addError("\"OptionalKey\" property is mandatory for field name "
+ + fieldName.toString());
errorCount++;
}
}
@@ -141,7 +166,6 @@
return fieldName;
}
-
public String getAdditionalKey() {
return additionalKey;
}
@@ -176,5 +200,4 @@
this.key = key;
}
-
}
1
0

svn commit: r2098 - logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util
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 21:06:37 2008
New Revision: 2098
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java
Log:
It is possible for ContextInitializer (part of logback-classic) to
be loaded by a different class loader than the class loaded that loaded
c.q.l.core.Loader (part of logback-core).
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java Tue Dec 23 21:06:37 2008
@@ -80,7 +80,7 @@
return url;
}
- url = Loader.getResourceBySelfClassLoader(TEST_AUTOCONFIG_FILE);
+ url = Loader.getResource(TEST_AUTOCONFIG_FILE, this.getClass().getClassLoader());
if (updateStatus) {
statusOnResourceSearch(TEST_AUTOCONFIG_FILE, url);
}
@@ -88,7 +88,7 @@
return url;
}
- url = Loader.getResourceBySelfClassLoader(AUTOCONFIG_FILE);
+ url = Loader.getResource(AUTOCONFIG_FILE, this.getClass().getClassLoader());
if (updateStatus) {
statusOnResourceSearch(AUTOCONFIG_FILE, url);
}
1
0
Author: ceki
Date: Tue Dec 23 20:04:00 2008
New Revision: 2097
Modified:
logback-demo/trunk/pom.xml
Log:
test with logback 0.9.14-SNAPSHOT
Modified: logback-demo/trunk/pom.xml
==============================================================================
--- logback-demo/trunk/pom.xml (original)
+++ logback-demo/trunk/pom.xml Tue Dec 23 20:04:00 2008
@@ -9,7 +9,7 @@
<version>1.0</version>
<properties>
- <lb.version>0.9.13</lb.version>
+ <lb.version>0.9.14-SNAPSHOT</lb.version>
</properties>
1
0

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