logback-dev
Threads by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 9940 discussions
svn commit: r2086 - logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift
by noreply.ceki@qos.ch 18 Dec '08
by noreply.ceki@qos.ch 18 Dec '08
18 Dec '08
Author: ceki
Date: Thu Dec 18 21:48:23 2008
New Revision: 2086
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java
Log:
- migrating SiftingAppender to logback-core from logback-classic
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactory.java Thu Dec 18 21:48:23 2008
@@ -0,0 +1,43 @@
+package ch.qos.logback.core.sift;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.joran.event.SaxEvent;
+import ch.qos.logback.core.joran.spi.JoranException;
+
+public abstract class AppenderFactory<E, K> {
+
+ final List<SaxEvent> eventList;
+ Context context;
+
+ AppenderFactory(Context context, List<SaxEvent> eventList) {
+ this.context = context;
+ this.eventList = new ArrayList<SaxEvent>(eventList);
+ removeHoardElement();
+
+ }
+
+ void removeHoardElement() {
+ eventList.remove(0);
+ eventList.remove(eventList.size() - 1);
+ System.out.println(eventList);
+ }
+
+
+ abstract SiftingJoranConfigurator<E> getSiftingJoranConfigurator(K k);
+
+ Appender<E> buildAppender(Context context, K k) throws JoranException {
+ SiftingJoranConfigurator<E> sjc = getSiftingJoranConfigurator(k);
+ sjc.setContext(context);
+ sjc.doConfigure(eventList);
+ return sjc.getAppender();
+ }
+
+ public List<SaxEvent> getEventList() {
+ return eventList;
+ }
+
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTracker.java Thu Dec 18 21:48:23 2008
@@ -0,0 +1,28 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import java.util.List;
+
+import ch.qos.logback.core.Appender;
+
+public interface AppenderTracker<E, K> {
+
+ static int MILLIS_IN_ONE_SECOND = 1000;
+ static int THRESHOLD = 30 * 60 * MILLIS_IN_ONE_SECOND; // 30 minutes
+
+ void put(K key, Appender<E> value, long timestamp);
+ Appender<E> get(String key, long timestamp);
+ void stopStaleAppenders(long timestamp);
+ List<K> keyList();
+ List<Appender<E>> valueList();
+
+
+}
\ No newline at end of file
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderTrackerImpl.java Thu Dec 18 21:48:23 2008
@@ -0,0 +1,207 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import ch.qos.logback.core.Appender;
+
+/**
+ * Track appenders by a key. When an appender is not used for
+ * longer than THRESHOLD, stop it.
+ * @author Ceki Gulcu
+ */
+public class AppenderTrackerImpl<E, K> implements AppenderTracker<E, K> {
+
+ Map<K, Entry> map = new HashMap<K, Entry>();
+
+ Entry head; // least recently used entries are towards the head
+ Entry tail; // most recently used entries are towards the tail
+
+ long lastCheck = 0;
+
+ AppenderTrackerImpl() {
+ head = new Entry(null, null, 0);
+ tail = head;
+ }
+
+
+ public synchronized void put(K key, Appender<E> value, long timestamp) {
+ Entry entry = map.get(key);
+ if (entry == null) {
+ entry = new Entry(key, value, timestamp);
+ map.put(key, entry);
+ }
+ moveToTail(entry);
+ }
+
+ public synchronized Appender<E> get(String key, long timestamp) {
+ Entry existing = map.get(key);
+ if (existing == null) {
+ return null;
+ } else {
+ existing.setTimestamp(timestamp);
+ moveToTail(existing);
+ return existing.value;
+ }
+ }
+
+
+ public synchronized void stopStaleAppenders(long now) {
+ if (lastCheck + MILLIS_IN_ONE_SECOND > now) {
+ return;
+ }
+ lastCheck = now;
+ while (head.value != null && isEntryStale(head,now)) {
+ Appender appender = head.value;
+ //System.out.println(" stopping "+appender);
+ appender.stop();
+ removeHead();
+ }
+ }
+
+ public List<K> keyList() {
+ List<K> result = new LinkedList<K>();
+ Entry e = head;
+ while (e != tail) {
+ result.add(e.key);
+ e = e.next;
+ }
+ return result;
+ }
+
+
+ final private boolean isEntryStale(Entry entry, long now) {
+ return ((entry.timestamp + THRESHOLD) < now);
+ }
+
+
+ private void removeHead() {
+ // System.out.println("RemoveHead called");
+ map.remove(head.key);
+ head = head.next;
+ head.prev = null;
+ }
+
+ private void moveToTail(Entry e) {
+ rearrangePreexistingLinks(e);
+ rearrangeTailLinks(e);
+ }
+
+ private void rearrangePreexistingLinks(Entry e) {
+ if (e.prev != null) {
+ e.prev.next = e.next;
+ }
+ if (e.next != null) {
+ e.next.prev = e.prev;
+ }
+ if (head == e) {
+ head = e.next;
+ }
+ }
+
+ private void rearrangeTailLinks(Entry e) {
+ if (head == tail) {
+ head = e;
+ }
+ Entry preTail = tail.prev;
+ if (preTail != null) {
+ preTail.next = e;
+ }
+ e.prev = preTail;
+ e.next = tail;
+ tail.prev = e;
+ }
+
+ public void dump() {
+ Entry e = head;
+ System.out.print("N:");
+ while (e != null) {
+ // System.out.print(e+"->");
+ System.out.print(e.key + ", ");
+ e = e.next;
+ }
+ System.out.println();
+ }
+
+
+
+ public List<Appender<E>> valueList() {
+ List<Appender<E>> result = new LinkedList<Appender<E>>();
+ Entry e = head;
+ while (e != tail) {
+ result.add(e.value);
+ e = e.next;
+ }
+ return result;
+ }
+
+ // ================================================================
+ private class Entry {
+ Entry next;
+ Entry prev;
+
+ K key;
+ Appender<E> value;
+ long timestamp;
+
+ Entry(K k, Appender<E> v, long timestamp) {
+ this.key = k;
+ this.value = v;
+ this.timestamp = timestamp;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((key == null) ? 0 : key.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Entry other = (Entry) obj;
+ if (key == null) {
+ if (other.key != null)
+ return false;
+ } else if (!key.equals(other.key))
+ return false;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + key + ", " + value + ")";
+ }
+ }
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java Thu Dec 18 21:48:23 2008
@@ -0,0 +1,112 @@
+/**
+ * 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.Appender;
+import ch.qos.logback.core.UnsynchronizedAppenderBase;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.OptionHelper;
+
+/**
+ * This appender can contains other appenders which it can build dynamically
+ * 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 abstract class SiftingAppenderBase<E, K> extends UnsynchronizedAppenderBase<E> {
+
+ AppenderTracker<E, K> appenderTracker = new AppenderTrackerImpl<E, K>();
+ //Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String, Appender<LoggingEvent>>();
+
+ String mdcKey;
+ String defaultValue;
+
+ AppenderFactory<E, K> appenderFactory;
+
+ void setAppenderFactory(AppenderFactory<E, K> appenderFactory) {
+ this.appenderFactory = appenderFactory;
+ }
+
+ @Override
+ public void start() {
+ int errors = 0;
+ if (OptionHelper.isEmpty(mdcKey)) {
+ errors++;
+ addError("The \"mdcKey\" property must be set");
+ }
+ if (OptionHelper.isEmpty(defaultValue)) {
+ errors++;
+ addError("The \"defaultValue\" property must be set");
+ }
+ if (errors == 0) {
+ super.start();
+ }
+ }
+
+ @Override
+ public void stop() {
+ for (Appender<E> appender : appenderTracker.valueList()) {
+ appender.stop();
+ }
+ }
+
+ abstract protected K getDiscriminatingValue(E event);
+ abstract protected long getTimestamp(E event);
+
+ @Override
+ protected void append(E event) {
+ if (!isStarted()) {
+ return;
+ }
+
+
+ K value = getDiscriminatingValue(event);
+ long timestamp = getTimestamp(event);
+
+ Appender<E> appender = appenderTracker.get(value, timestamp);
+
+ if (appender == null) {
+ try {
+ appender = appenderFactory.buildAppender(context, value);
+ if (appender != null) {
+ appenderTracker.put(value, appender, timestamp);
+ }
+ } catch (JoranException e) {
+ addError("Failed to build appender for [" + value + "]", e);
+ return;
+ }
+ }
+ appenderTracker.stopStaleAppenders(timestamp);
+ appender.doAppend(event);
+ }
+
+ public String getMdcKey() {
+ return mdcKey;
+ }
+
+ public void setMdcKey(String mdcKey) {
+ this.mdcKey = mdcKey;
+ }
+
+ /**
+ * @see #setDefaultValue(String)
+ * @return
+ */
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingJoranConfigurator.java Thu Dec 18 21:48:23 2008
@@ -0,0 +1,23 @@
+package ch.qos.logback.core.sift;
+
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.joran.GenericConfigurator;
+import ch.qos.logback.core.joran.spi.Interpreter;
+import ch.qos.logback.core.joran.spi.RuleStore;
+
+public abstract class SiftingJoranConfigurator<E> extends GenericConfigurator {
+
+ @Override
+ protected void addImplicitRules(Interpreter interpreter) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void addInstanceRules(RuleStore rs) {
+ // TODO Auto-generated method stub
+
+ }
+
+ abstract Appender<E> getAppender();
+}
1
0
18 Dec '08
Author: ceki
Date: Thu Dec 18 21:15:43 2008
New Revision: 2085
Added:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/
- copied from r2079, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderFactory.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTracker.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTracker.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTrackerImpl.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTrackerImpl.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardAction.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/AppenderTrackerTest.java
- copied, changed from r2084, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java
- copied, changed from r2082, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/ScenarioBasedAppenderTrackerTest.java
- copied, changed from r2082, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java
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/Simulator.java
- copied, changed from r2082, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java
Removed:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java
Log:
Renamed HoardingAppender as SiftingAppender
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java Thu Dec 18 21:15:43 2008
@@ -10,7 +10,6 @@
package ch.qos.logback.classic.joran;
-import ch.qos.logback.classic.hoard.HoardAction;
import ch.qos.logback.classic.joran.action.ConfigurationAction;
import ch.qos.logback.classic.joran.action.ConsolePluginAction;
import ch.qos.logback.classic.joran.action.ContextNameAction;
@@ -21,6 +20,7 @@
import ch.qos.logback.classic.joran.action.LevelAction;
import ch.qos.logback.classic.joran.action.LoggerAction;
import ch.qos.logback.classic.joran.action.RootLoggerAction;
+import ch.qos.logback.classic.sift.HoardAction;
import ch.qos.logback.classic.spi.PlatformInfo;
import ch.qos.logback.core.joran.JoranConfiguratorBase;
import ch.qos.logback.core.joran.action.AppenderRefAction;
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java (from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderFactory.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderFactory.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderFactory.java Thu Dec 18 21:15:43 2008
@@ -1,4 +1,4 @@
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import java.util.ArrayList;
import java.util.List;
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTracker.java (from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTracker.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTracker.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTracker.java Thu Dec 18 21:15:43 2008
@@ -1,4 +1,4 @@
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import java.util.List;
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTrackerImpl.java (from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTrackerImpl.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTrackerImpl.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/AppenderTrackerImpl.java Thu Dec 18 21:15:43 2008
@@ -7,7 +7,7 @@
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import java.util.HashMap;
import java.util.LinkedList;
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java (from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardAction.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardAction.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardAction.java Thu Dec 18 21:15:43 2008
@@ -1,4 +1,4 @@
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import java.util.ArrayList;
import java.util.List;
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java (from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingAppender.java Thu Dec 18 21:15:43 2008
@@ -7,7 +7,7 @@
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import org.slf4j.MDC;
Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java (from r2084, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/HoardingJoranConfigurator.java Thu Dec 18 21:15:43 2008
@@ -1,4 +1,4 @@
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import java.util.Collection;
import java.util.HashMap;
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java Thu Dec 18 21:15:43 2008
@@ -35,7 +35,7 @@
suite.addTest(ch.qos.logback.classic.spi.PackageTest.suite());
suite.addTest(new JUnit4TestAdapter(ch.qos.logback.classic.turbo.PackageTest.class));
suite.addTest(new JUnit4TestAdapter(
- ch.qos.logback.classic.hoard.PackageTest.class));
+ ch.qos.logback.classic.sift.PackageTest.class));
return suite;
}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java Thu Dec 18 21:15:43 2008
@@ -14,7 +14,7 @@
import java.util.LinkedList;
import java.util.List;
-import ch.qos.logback.classic.hoard.AppenderTracker;
+import ch.qos.logback.classic.sift.AppenderTracker;
import ch.qos.logback.core.Appender;
/**
Copied: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/AppenderTrackerTest.java (from r2084, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java)
==============================================================================
--- /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/AppenderTrackerTest.java Thu Dec 18 21:15:43 2008
@@ -1,4 +1,4 @@
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -8,6 +8,8 @@
import org.junit.Before;
import org.junit.Test;
+import ch.qos.logback.classic.sift.AppenderTracker;
+import ch.qos.logback.classic.sift.AppenderTrackerImpl;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.ContextBase;
import ch.qos.logback.core.read.ListAppender;
Copied: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java (from r2082, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java)
==============================================================================
--- /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/PackageTest.java Thu Dec 18 21:15:43 2008
@@ -7,13 +7,13 @@
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
-(a)SuiteClasses({HoardingAppenderTest.class})
+(a)SuiteClasses({SiftingAppenderTest.class})
public class PackageTest {
}
\ No newline at end of file
Copied: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/ScenarioBasedAppenderTrackerTest.java (from r2082, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java)
==============================================================================
--- /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/ScenarioBasedAppenderTrackerTest.java Thu Dec 18 21:15:43 2008
@@ -7,13 +7,15 @@
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import static org.junit.Assert.assertEquals;
import org.junit.Ignore;
import org.junit.Test;
+import ch.qos.logback.classic.sift.AppenderTracker;
+
public class ScenarioBasedAppenderTrackerTest {
Simulator simulator;
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/SiftingAppenderTest.java Thu Dec 18 21:15:43 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.classic.sift;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.sift.AppenderTracker;
+import ch.qos.logback.classic.sift.HoardingAppender;
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.util.TeztConstants;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.read.ListAppender;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class SiftingAppenderTest {
+
+ static String PREFIX = TeztConstants.TEST_DIR_PREFIX + "input/joran/hoard/";
+
+ LoggerContext loggerContext = new LoggerContext();
+ Logger logger = loggerContext.getLogger(this.getClass().getName());
+ Logger root = loggerContext.getLogger(LoggerContext.ROOT_NAME);
+
+ void configure(String file) throws JoranException {
+ JoranConfigurator jc = new JoranConfigurator();
+ jc.setContext(loggerContext);
+ jc.doConfigure(file);
+ }
+
+ @Test
+ public void unsetDefaultValueProperty() throws JoranException {
+ configure(PREFIX + "unsetDefaultValueProperty.xml");
+ logger.debug("hello");
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ assertFalse(ha.isStarted());
+
+ }
+
+ @Test
+ public void smoke() throws JoranException {
+ configure(PREFIX + "smoke.xml");
+ logger.debug("smoke");
+ long timestamp = 0;
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("smoke", timestamp);
+
+ StatusPrinter.print(loggerContext);
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+ }
+
+ @Test
+ public void testWholeCycle() throws JoranException {
+ String mdcKey = "cycle";
+ configure(PREFIX + "completeCycle.xml");
+ MDC.put(mdcKey, "a");
+ logger.debug("smoke");
+ long timestamp = System.currentTimeMillis();
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("a", timestamp);
+ StatusPrinter.print(loggerContext);
+
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+
+ MDC.remove(mdcKey);
+ LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, null);
+ le.setTimeStamp(timestamp+AppenderTracker.THRESHOLD*2);
+ ha.doAppend(le);
+ assertFalse(listAppender.isStarted());
+ assertEquals(1, ha.appenderTracker.keyList().size());
+ assertEquals("cycleDefault", ha.appenderTracker.keyList().get(0));
+
+ }
+}
Copied: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/Simulator.java (from r2082, /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java)
==============================================================================
--- /logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/sift/Simulator.java Thu Dec 18 21:15:43 2008
@@ -7,7 +7,7 @@
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
-package ch.qos.logback.classic.hoard;
+package ch.qos.logback.classic.sift;
import java.util.ArrayList;
import java.util.HashMap;
@@ -17,6 +17,8 @@
import ch.qos.logback.classic.hoard.tracker.SimulationEvent;
import ch.qos.logback.classic.hoard.tracker.AppenderTrackerTImpl;
+import ch.qos.logback.classic.sift.AppenderTracker;
+import ch.qos.logback.classic.sift.AppenderTrackerImpl;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.appender.NOPAppender;
1
0
Author: ceki
Date: Thu Dec 18 21:11:24 2008
New Revision: 2084
Added:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java
logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java
Modified:
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
Log:
- added DuplicateMessageFilter
- BasicStatusMessages's internal buffer now has two parts, the head part and the tail part.
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java Thu Dec 18 21:11:24 2008
@@ -0,0 +1,68 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.turbo;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.core.spi.FilterReply;
+
+public class DuplicateMessageFilter extends TurboFilter {
+
+ static final int DEFAULT_CACHE_SIZE = 100;
+ static final int DEFAULT_ALLOWED_REPETITIONS = 5;
+
+ public int allowedRepetitions = DEFAULT_ALLOWED_REPETITIONS;
+ public int cacheSize = DEFAULT_CACHE_SIZE;
+
+ private LRUMessageCache msgCache;
+
+ @Override
+ public void start() {
+ msgCache = new LRUMessageCache(cacheSize);
+ super.start();
+ }
+
+ @Override
+ public void stop() {
+ msgCache.clear();
+ msgCache = null;
+ super.stop();
+ }
+
+ @Override
+ public FilterReply decide(Marker marker, Logger logger, Level level,
+ String format, Object[] params, Throwable t) {
+ int count = msgCache.getMessageCount(format);
+ if(count <= allowedRepetitions) {
+ return FilterReply.NEUTRAL;
+ } else {
+ return FilterReply.DENY;
+ }
+ }
+
+ public int getAllowedRepetitions() {
+ return allowedRepetitions;
+ }
+
+ public void setAllowedRepetitions(int allowedRepetitions) {
+ this.allowedRepetitions = allowedRepetitions;
+ }
+
+ public int getCacheSize() {
+ return cacheSize;
+ }
+
+ public void setCacheSize(int cacheSize) {
+ this.cacheSize = cacheSize;
+ }
+
+}
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java Thu Dec 18 21:11:24 2008
@@ -0,0 +1,43 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.turbo;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+class LRUMessageCache extends LinkedHashMap<String, Integer> {
+
+ private static final long serialVersionUID = 1L;
+
+ final int cacheSize;
+
+ LRUMessageCache(int cacheSize) {
+ super((int) (cacheSize * (4.0f / 3)), 0.75f, true);
+ if (cacheSize < 1) {
+ throw new IllegalArgumentException("Cache size cannnot be smaller than 1");
+ }
+ this.cacheSize = cacheSize;
+ }
+
+ int getMessageCount(String msg) {
+ Integer i = super.get(msg);
+ if(i == null) {
+ i = 1;
+ } else {
+ i = new Integer(i.intValue()+1);
+ }
+ super.put(msg, i);
+ return i;
+ }
+
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return (size() > cacheSize);
+ }
+}
Added: logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml Thu Dec 18 21:11:24 2008
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration>
+
+<configuration debug="true">
+
+ <appender name="HOARD"
+ class="ch.qos.logback.classic.hoard.HoardingAppender">
+
+ <mdcKey>cycle</mdcKey>
+ <defaultValue>cycleDefault</defaultValue>
+ <hoard>
+ <appender name="list-${cycle}" class="ch.qos.logback.core.read.ListAppender"/>
+ </hoard>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="HOARD" />
+ </root>
+
+</configuration>
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java Thu Dec 18 21:11:24 2008
@@ -33,7 +33,7 @@
suite.addTest(ch.qos.logback.classic.pattern.PackageTest.suite());
suite.addTest(ch.qos.logback.classic.db.PackageTest.suite());
suite.addTest(ch.qos.logback.classic.spi.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.turbo.PackageTest.suite());
+ suite.addTest(new JUnit4TestAdapter(ch.qos.logback.classic.turbo.PackageTest.class));
suite.addTest(new JUnit4TestAdapter(
ch.qos.logback.classic.hoard.PackageTest.class));
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java Thu Dec 18 21:11:24 2008
@@ -24,9 +24,17 @@
la.setContext(context);
la.start();
}
+
@Test
- public void empty() {
+ public void empty0() {
+ long now = 3000;
+ appenderTracker.stopStaleAppenders(now);
+ assertEquals(0, appenderTracker.keyList().size());
+ }
+
+ @Test
+ public void empty1() {
long now = 3000;
assertNull(appenderTracker.get("a", now++));
now += AppenderTrackerImpl.THRESHOLD+1000;
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java Thu Dec 18 21:11:24 2008
@@ -16,7 +16,9 @@
import java.util.List;
import org.junit.Test;
+import org.slf4j.MDC;
+import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
@@ -56,8 +58,8 @@
long timestamp = 0;
HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("smoke", timestamp);
- StatusPrinter.print(loggerContext);
+ StatusPrinter.print(loggerContext);
assertNotNull(listAppender);
List<LoggingEvent> eventList = listAppender.list;
assertEquals(1, listAppender.list.size());
@@ -65,11 +67,28 @@
}
@Test
- public void testLevel() throws JoranException {
- configure(PREFIX + "hoard0.xml");
- logger.debug("ss");
- //StatusPrinter.print(loggerContext);
+ public void testWholeCycle() throws JoranException {
+ String mdcKey = "cycle";
+ configure(PREFIX + "completeCycle.xml");
+ MDC.put(mdcKey, "a");
+ logger.debug("smoke");
+ long timestamp = System.currentTimeMillis();
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("a", timestamp);
+ StatusPrinter.print(loggerContext);
- }
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+ MDC.remove(mdcKey);
+ LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, null);
+ le.setTimeStamp(timestamp+AppenderTracker.THRESHOLD*2);
+ ha.doAppend(le);
+ assertFalse(listAppender.isStarted());
+ assertEquals(1, ha.appenderTracker.keyList().size());
+ assertEquals("cycleDefault", ha.appenderTracker.keyList().get(0));
+
+ }
}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java Thu Dec 18 21:11:24 2008
@@ -0,0 +1,54 @@
+package ch.qos.logback.classic.turbo;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import ch.qos.logback.core.spi.FilterReply;
+
+
+public class DuplicateMessageFilterTest {
+
+
+ @Test
+ public void smoke() {
+ DuplicateMessageFilter dmf = new DuplicateMessageFilter();
+ dmf.setAllowedRepetitions(1);
+ dmf.start();
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "x", null, null));
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "y", null, null));
+ assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "x", null, null));
+ assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "y", null, null));
+ }
+
+ @Test
+ public void memoryLoss() {
+ DuplicateMessageFilter dmf = new DuplicateMessageFilter();
+ dmf.setAllowedRepetitions(1);
+ dmf.setCacheSize(1);
+ dmf.start();
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, null));
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "b", null, null));
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, null));
+ }
+
+
+ @Test
+ public void many() {
+ DuplicateMessageFilter dmf = new DuplicateMessageFilter();
+ dmf.setAllowedRepetitions(1);
+ int cacheSize = 10;
+ int margin = 2;
+ dmf.setCacheSize(cacheSize);
+ dmf.start();
+ for(int i = 0; i < cacheSize+margin; i++) {
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a"+i, null, null));
+ }
+ for(int i = cacheSize-1; i >= margin; i--) {
+ assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "a"+i, null, null));
+ }
+ for(int i = margin-1; i >= 0; i--) {
+ assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a"+i, null, null));
+ }
+ }
+}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java Thu Dec 18 21:11:24 2008
@@ -1,30 +1,23 @@
package ch.qos.logback.classic.turbo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import ch.qos.logback.core.spi.FilterReply;
-import junit.framework.TestCase;
-
-public class MarkerFilterTest extends TestCase {
+public class MarkerFilterTest {
static String MARKER_NAME = "toto";
Marker totoMarker = MarkerFactory.getMarker(MARKER_NAME);
- public MarkerFilterTest(String arg0) {
- super(arg0);
- }
-
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- protected void tearDown() throws Exception {
- super.tearDown();
- }
+ @Test
public void testNoMarker() {
MarkerFilter mkt = new MarkerFilter();
mkt.start();
@@ -33,7 +26,9 @@
assertEquals(FilterReply.NEUTRAL, mkt.decide(null, null, null, null, null, null));
}
-
+
+
+ @Test
public void testBasic() {
MarkerFilter mkt = new MarkerFilter();
mkt.setMarker(MARKER_NAME);
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java Thu Dec 18 21:11:24 2008
@@ -10,15 +10,11 @@
package ch.qos.logback.classic.turbo;
-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 PackageTest extends TestCase {
-
- public static Test suite() {
- TestSuite suite = new TestSuite();
- suite.addTestSuite(MarkerFilterTest.class);
- return suite;
- }
+(a)RunWith(Suite.class)
+@SuiteClasses( { MarkerFilterTest.class, DuplicateMessageFilterTest.class})
+public class PackageTest {
}
\ No newline at end of file
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java Thu Dec 18 21:11:24 2008
@@ -12,18 +12,22 @@
import java.util.ArrayList;
import java.util.List;
+import ch.qos.logback.core.helpers.CyclicBuffer;
import ch.qos.logback.core.status.Status;
import ch.qos.logback.core.status.StatusListener;
import ch.qos.logback.core.status.StatusManager;
public class BasicStatusManager implements StatusManager {
- public static final int MAX_COUNT = 200;
+ public static final int MAX_HEADER_COUNT = 150;
+ public static final int TAIL_SIZE = 150;
int count = 0;
// protected access was requested in http://jira.qos.ch/browse/LBCORE-36
final protected List<Status> statusList = new ArrayList<Status>();
+ final protected CyclicBuffer<Status> tailBuffer = new CyclicBuffer<Status>(
+ TAIL_SIZE);
final protected Object statusListLock = new Object();
int level = Status.INFO;
@@ -34,7 +38,7 @@
// Note on synchronization
// This class contains two separate locks statusListLock and
- // statusListenerListLock guarding respectively the statusList and
+ // statusListenerListLock guarding respectively the statusList+tailBuffer and
// statusListenerList fields. The locks are used internally
// without cycles. They are exposed to derived classes which should be careful
// not to create deadlock cycles.
@@ -49,21 +53,28 @@
// LBCORE-72: fire event before the count check
fireStatusAddEvent(newStatus);
- if (count > MAX_COUNT) {
- return;
- }
count++;
-
if (newStatus.getLevel() > level) {
level = newStatus.getLevel();
}
synchronized (statusListLock) {
- statusList.add(newStatus);
+ if (statusList.size() < MAX_HEADER_COUNT) {
+ statusList.add(newStatus);
+ } else {
+ tailBuffer.add(newStatus);
+ }
}
}
-
+ public List<Status> getCopyOfStatusList() {
+ synchronized (statusListLock) {
+ List<Status> tList = new ArrayList<Status>(statusList);
+ tList.addAll(tailBuffer.asList());
+ return tList;
+ }
+ }
+
private void fireStatusAddEvent(Status status) {
synchronized (statusListenerListLock) {
for (StatusListener sl : statusListenerList) {
@@ -72,12 +83,6 @@
}
}
- public List<Status> getCopyOfStatusList() {
- synchronized (statusListLock) {
- return new ArrayList<Status>(statusList);
- }
- }
-
public int getLevel() {
return level;
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java Thu Dec 18 21:11:24 2008
@@ -10,14 +10,14 @@
package ch.qos.logback.core.helpers;
+import java.util.ArrayList;
+import java.util.List;
/**
+ * CyclicBuffer holds values in a cyclic array.
*
- * CyclicBuffer is used by other appenders to hold
- * objects for immediate or differed display.
- * <p>
- * This buffer gives read access to any element in the buffer not just the first
- * or last element.
+ * <p>It allows read access to any element in the buffer not just the first or
+ * last element.
*
* @author Ceki Gülcü
*/
@@ -35,7 +35,7 @@
* The <code>maxSize</code> argument must a positive integer.
*
* @param maxSize
- * The maximum number of elements in the buffer.
+ * The maximum number of elements in the buffer.
*/
@SuppressWarnings("unchecked")
public CyclicBuffer(int maxSize) throws IllegalArgumentException {
@@ -45,7 +45,7 @@
}
init(maxSize);
}
-
+
@SuppressWarnings("unchecked")
private void init(int maxSize) {
this.maxSize = maxSize;
@@ -54,10 +54,9 @@
last = 0;
numElems = 0;
}
-
+
/**
- * Clears the buffer
- * and resets all attributes.
+ * Clears the buffer and resets all attributes.
*/
public void clear() {
init(this.maxSize);
@@ -94,7 +93,6 @@
return maxSize;
}
-
/**
* Get the oldest (first) element in the buffer. The oldest element is removed
* from the buffer.
@@ -110,6 +108,14 @@
}
return r;
}
+
+ public List<E> asList() {
+ List<E> tList = new ArrayList<E>();
+ for(int i = 0; i < length(); i++) {
+ tList.add(get(i));
+ }
+ return tList;
+ }
/**
* Get the number of elements in the buffer. This number is guaranteed to be
@@ -123,7 +129,7 @@
* Resize the cyclic buffer to <code>newSize</code>.
*
* @throws IllegalArgumentException
- * if <code>newSize</code> is negative.
+ * if <code>newSize</code> is negative.
*/
@SuppressWarnings("unchecked")
public void resize(int newSize) {
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java Thu Dec 18 21:11:24 2008
@@ -52,7 +52,7 @@
appender.setContext(context);
- String appenderName = attributes.getValue(NAME_ATTRIBUTE);
+ String appenderName = ec.subst(attributes.getValue(NAME_ATTRIBUTE));
if (OptionHelper.isEmpty(appenderName)) {
addWarn("No appender name given for appender of type " + className
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java Thu Dec 18 21:11:24 2008
@@ -1,11 +1,11 @@
/**
- * LOGBack: the generic, reliable, fast and flexible logging framework.
- *
- * Copyright (C) 1999-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.
+ * 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.read;
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java Thu Dec 18 21:11:24 2008
@@ -139,4 +139,33 @@
return buf.toString();
}
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + level;
+ result = prime * result + ((message == null) ? 0 : message.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final StatusBase other = (StatusBase) obj;
+ if (level != other.level)
+ return false;
+ if (message == null) {
+ if (other.message != null)
+ return false;
+ } else if (!message.equals(other.message))
+ return false;
+ return true;
+ }
+
+
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java Thu Dec 18 21:11:24 2008
@@ -14,7 +14,8 @@
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
-(a)SuiteClasses({ch.qos.logback.core.util.PackageTest.class,
+(a)SuiteClasses({BasicStatusManagerTest.class,
+ ch.qos.logback.core.util.PackageTest.class,
ch.qos.logback.core.helpers.PackageTest.class,
ch.qos.logback.core.pattern.PackageTest.class,
ch.qos.logback.core.PackageTest.class,
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java Thu Dec 18 21:11:24 2008
@@ -0,0 +1,53 @@
+package ch.qos.logback.core;
+
+import static ch.qos.logback.core.BasicStatusManager.MAX_HEADER_COUNT;
+import static ch.qos.logback.core.BasicStatusManager.TAIL_SIZE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import ch.qos.logback.core.status.ErrorStatus;
+import ch.qos.logback.core.status.Status;
+
+
+public class BasicStatusManagerTest {
+
+
+ BasicStatusManager bsm = new BasicStatusManager();
+
+ @Test
+ public void smoke() {
+ bsm.add(new ErrorStatus("hello", this));
+ assertEquals(Status.ERROR, bsm.getLevel());
+
+ List<Status> statusList = bsm.getCopyOfStatusList();
+ assertNotNull(statusList);
+ assertEquals(1, statusList.size());
+ assertEquals("hello", statusList.get(0).getMessage());
+ }
+
+ @Test
+ public void many() {
+ int margin = 300;
+ int len = MAX_HEADER_COUNT+TAIL_SIZE+margin;
+ for(int i = 0; i < len; i++) {
+ bsm.add(new ErrorStatus(""+i, this));
+ }
+
+ List<Status> statusList = bsm.getCopyOfStatusList();
+ assertNotNull(statusList);
+ assertEquals(MAX_HEADER_COUNT+TAIL_SIZE, statusList.size());
+ List<Status> witness = new ArrayList<Status>();
+ for(int i = 0; i < MAX_HEADER_COUNT; i++) {
+ witness.add(new ErrorStatus(""+i, this));
+ }
+ for(int i = 0; i < TAIL_SIZE; i++) {
+ witness.add(new ErrorStatus(""+(MAX_HEADER_COUNT+margin+i), this));
+ }
+ assertEquals(witness, statusList);
+ }
+}
1
0
[JIRA] Created: (LBCLASSIC-93) start mehtod/ default mdc value property
by Ceki Gulcu (JIRA) 18 Dec '08
by Ceki Gulcu (JIRA) 18 Dec '08
18 Dec '08
start mehtod/ default mdc value property
----------------------------------------
Key: LBCLASSIC-93
URL: http://jira.qos.ch/browse/LBCLASSIC-93
Project: logback-classic
Issue Type: Sub-task
Components: appender
Reporter: Ceki Gulcu
Assignee: Logback dev list
Priority: Blocker
Fix For: 0.9.14
Work on the start method
Add "default" mdc value property
--
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
[JIRA] Created: (LBCLASSIC-98) NPE when calling setContextMap on a fresch MDC.
by Ceki Gulcu (JIRA) 18 Dec '08
by Ceki Gulcu (JIRA) 18 Dec '08
18 Dec '08
NPE when calling setContextMap on a fresch MDC.
-----------------------------------------------
Key: LBCLASSIC-98
URL: http://jira.qos.ch/browse/LBCLASSIC-98
Project: logback-classic
Issue Type: Bug
Affects Versions: 0.9.13
Reporter: Ceki Gulcu
Assignee: Ceki Gulcu
Fix For: 0.9.14
Reported by Francois_Terrier in http://www.qos.ch/pipermail/logback-user/2008-December/000864.html
there is a little NPE when calling setContextMap on a fresch MDC. This
could raises a NPE:
public static void main(String[] args) {
MDC.setContextMap(new HashMap<String, String>());
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
1
svn commit: r2083 - in logback/trunk/logback-classic/src: main/java/org/slf4j/impl test/java/ch/qos/logback/classic
by noreply.ceki@qos.ch 18 Dec '08
by noreply.ceki@qos.ch 18 Dec '08
18 Dec '08
Author: ceki
Date: Thu Dec 18 14:22:04 2008
New Revision: 2083
Modified:
logback/trunk/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java
Log:
Fixed LBCLASSIC-98 (NPE thrown when calling setContextMap on a fresh MDC)
Modified: logback/trunk/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java (original)
+++ logback/trunk/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java Thu Dec 18 14:22:04 2008
@@ -10,12 +10,9 @@
* A <em>Mapped Diagnostic Context</em>, or MDC in short, is an instrument
* for distinguishing interleaved log output from different sources. Log output
* is typically interleaved when a server handles multiple clients
- * near-simultaneously.
- * <p>
- * <b><em>The MDC is managed on a per thread basis</em></b>. A child thread
- * automatically inherits a <em>copy</em> of the mapped diagnostic context of
- * its parent.
- * <p>
+ * near-simultaneously. <p> <b><em>The MDC is managed on a per thread basis</em></b>.
+ * A child thread automatically inherits a <em>copy</em> of the mapped
+ * diagnostic context of its parent. <p>
*
* For more information about MDC, please refer to the online manual at
* http://logback.qos.ch/manual/mdc.html
@@ -24,7 +21,8 @@
*/
public class LogbackMDCAdapter implements MDCAdapter {
- //final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new CopyOnInheritThreadLocal();
+ // final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new
+ // CopyOnInheritThreadLocal();
final CopyOnInheritThreadLocal copyOnInheritThreadLocal = new CopyOnInheritThreadLocal();
@@ -36,13 +34,11 @@
* the <code>key</code> parameter into the current thread's context map.
* Note that contrary to log4j, the <code>val</code> parameter can be null.
*
- * <p>
- * If the current thread does not have a context map it is created as a side
- * effect of this call.
+ * <p> If the current thread does not have a context map it is created as a
+ * side effect of this call.
*
- * <p>
- * Each time a value is added, a new instance of the map is created. This is
- * to be certain that the serialization process will operate on the updated
+ * <p> Each time a value is added, a new instance of the map is created. This
+ * is to be certain that the serialization process will operate on the updated
* map and not send a reference to the old map, thus not allowing the remote
* logback component to see the latest changes.
*
@@ -68,8 +64,7 @@
/**
* Get the context identified by the <code>key</code> parameter.
*
- * <p>
- * This method has no side effects.
+ * <p> This method has no side effects.
*/
public String get(String key) {
HashMap<String, String> hashMap = copyOnInheritThreadLocal.get();
@@ -84,11 +79,10 @@
/**
* Remove the the context identified by the <code>key</code> parameter.
*
- * <p>
- * Each time a value is removed, a new instance of the map is created. This is
- * to be certain that the serialization process will operate on the updated
- * map and not send a reference to the old map, thus not allowing the remote
- * logback component to see the latest changes.
+ * <p> Each time a value is removed, a new instance of the map is created.
+ * This is to be certain that the serialization process will operate on the
+ * updated map and not send a reference to the old map, thus not allowing the
+ * remote logback component to see the latest changes.
*/
public void remove(String key) {
HashMap<String, String> oldMap = copyOnInheritThreadLocal.get();
@@ -160,7 +154,9 @@
copyOnInheritThreadLocal.set(newMap);
// hints for the garbage collector
- oldMap.clear();
- oldMap = null;
+ if (oldMap != null) {
+ oldMap.clear();
+ oldMap = null;
+ }
}
}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/MDCTest.java Thu Dec 18 14:22:04 2008
@@ -12,7 +12,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import java.util.HashMap;
+
import org.junit.Test;
+import org.slf4j.MDC;
public class MDCTest {
@@ -37,4 +40,9 @@
}
+ @Test
+ public void testLBCLASSIC_98() {
+ MDC.setContextMap(new HashMap<String, String>());
+ }
+
}
1
0
svn commit: r2082 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic/hoard test/input/joran/hoard test/java/ch/qos/logback/classic test/java/ch/qos/logback/classic/hoard test/java/ch/qos/logback/classic/hoard/tracker
by noreply.ceki@qos.ch 17 Dec '08
by noreply.ceki@qos.ch 17 Dec '08
17 Dec '08
Author: ceki
Date: Wed Dec 17 18:46:01 2008
New Revision: 2082
Added:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTracker.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTrackerImpl.java
logback/trunk/logback-classic/src/test/input/joran/hoard/smoke.xml
logback/trunk/logback-classic/src/test/input/joran/hoard/unsetDefaultValueProperty.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/SimulationEvent.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/TEntry.java
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java
logback/trunk/logback-classic/src/test/input/joran/hoard/hoard0.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
Log:
Code to track and clean up appenders. Related to LBCLASSIC-94
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTracker.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTracker.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,19 @@
+package ch.qos.logback.classic.hoard;
+
+import java.util.List;
+
+import ch.qos.logback.core.Appender;
+
+public interface AppenderTracker<E> {
+
+ static int MILLIS_IN_ONE_SECOND = 1000;
+ static int THRESHOLD = 30 * 60 * MILLIS_IN_ONE_SECOND; // 30 minutes
+
+ void put(String key, Appender<E> value, long timestamp);
+ Appender<E> get(String key, long timestamp);
+ void stopStaleAppenders(long now);
+ List<String> keyList();
+ List<Appender<E>> valueList();
+
+
+}
\ No newline at end of file
Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTrackerImpl.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/AppenderTrackerImpl.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,216 @@
+/**
+ * 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.hoard;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import ch.qos.logback.core.Appender;
+
+/**
+ * Track appenders by a key. When an appender is not used for
+ * longer than THRESHOLD, stop it.
+ * @author Ceki Gulcu
+ */
+public class AppenderTrackerImpl<E> implements AppenderTracker<E> {
+
+ Map<String, Entry> map = new HashMap<String, Entry>();
+
+ Entry head; // least recently used entries are towards the head
+ Entry tail; // most recently used entries are towards the tail
+
+ long lastCheck = 0;
+
+ AppenderTrackerImpl() {
+ head = new Entry(null, null, 0);
+ tail = head;
+ }
+
+ /* (non-Javadoc)
+ * @see ch.qos.logback.classic.hoard.AppenderTracker#put(java.lang.String, ch.qos.logback.core.Appender, long)
+ */
+ public synchronized void put(String key, Appender<E> value, long timestamp) {
+ Entry entry = map.get(key);
+ if (entry == null) {
+ entry = new Entry(key, value, timestamp);
+ map.put(key, entry);
+ }
+ moveToTail(entry);
+ }
+
+ /* (non-Javadoc)
+ * @see ch.qos.logback.classic.hoard.AppenderTracker#get(java.lang.String, long)
+ */
+ public synchronized Appender<E> get(String key, long timestamp) {
+ Entry existing = map.get(key);
+ if (existing == null) {
+ return null;
+ } else {
+ existing.setTimestamp(timestamp);
+ moveToTail(existing);
+ return existing.value;
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.qos.logback.classic.hoard.AppenderTracker#stopStaleAppenders(long)
+ */
+ public synchronized void stopStaleAppenders(long now) {
+ if (lastCheck + MILLIS_IN_ONE_SECOND > now) {
+ return;
+ }
+ lastCheck = now;
+ while (head.value != null && isEntryStale(head,now)) {
+ Appender appender = head.value;
+ //System.out.println(" stopping "+appender);
+ appender.stop();
+ removeHead();
+ }
+ }
+
+ public List<String> keyList() {
+ List<String> result = new LinkedList<String>();
+ Entry e = head;
+ while (e != tail) {
+ result.add(e.key);
+ e = e.next;
+ }
+ return result;
+ }
+
+
+ final private boolean isEntryStale(Entry entry, long now) {
+ return ((entry.timestamp + THRESHOLD) < now);
+ }
+
+
+ private void removeHead() {
+ // System.out.println("RemoveHead called");
+ map.remove(head.key);
+ head = head.next;
+ head.prev = null;
+ }
+
+ private void moveToTail(Entry e) {
+ rearrangePreexistingLinks(e);
+ rearrangeTailLinks(e);
+ }
+
+ private void rearrangePreexistingLinks(Entry e) {
+ if (e.prev != null) {
+ e.prev.next = e.next;
+ }
+ if (e.next != null) {
+ e.next.prev = e.prev;
+ }
+ if (head == e) {
+ head = e.next;
+ }
+ }
+
+ private void rearrangeTailLinks(Entry e) {
+ if (head == tail) {
+ head = e;
+ }
+ Entry preTail = tail.prev;
+ if (preTail != null) {
+ preTail.next = e;
+ }
+ e.prev = preTail;
+ e.next = tail;
+ tail.prev = e;
+ }
+
+ public void dump() {
+ Entry e = head;
+ System.out.print("N:");
+ while (e != null) {
+ // System.out.print(e+"->");
+ System.out.print(e.key + ", ");
+ e = e.next;
+ }
+ System.out.println();
+ }
+
+
+
+ public List<Appender<E>> valueList() {
+ List<Appender<E>> result = new LinkedList<Appender<E>>();
+ Entry e = head;
+ while (e != tail) {
+ result.add(e.value);
+ e = e.next;
+ }
+ return result;
+ }
+
+ // ================================================================
+ private class Entry {
+ Entry next;
+ Entry prev;
+
+ String key;
+ Appender<E> value;
+ long timestamp;
+
+ Entry(String k, Appender<E> v, long timestamp) {
+ this.key = k;
+ this.value = v;
+ this.timestamp = timestamp;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((key == null) ? 0 : key.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Entry other = (Entry) obj;
+ if (key == null) {
+ if (other.key != null)
+ return false;
+ } else if (!key.equals(other.key))
+ return false;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + key + ", " + value + ")";
+ }
+ }
+
+}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingAppender.java Wed Dec 17 18:46:01 2008
@@ -1,22 +1,39 @@
+/**
+ * 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.hoard;
-import java.util.Hashtable;
-import java.util.Map;
-
import org.slf4j.MDC;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.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 HoardingAppender extends UnsynchronizedAppenderBase<LoggingEvent> {
- static String DEFAULT = "default";
-
- Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String, Appender<LoggingEvent>>();
+ AppenderTracker<LoggingEvent> appenderTracker = new AppenderTrackerImpl<LoggingEvent>();
+ //Map<String, Appender<LoggingEvent>> appenderMap = new Hashtable<String, Appender<LoggingEvent>>();
String mdcKey;
+ String defaultValue;
AppenderFactory appenderFactory;
@@ -24,26 +41,57 @@
this.appenderFactory = appenderFactory;
}
-
-
+ @Override
+ public void start() {
+ int errors = 0;
+ if (OptionHelper.isEmpty(mdcKey)) {
+ errors++;
+ addError("The \"mdcKey\" property must be set");
+ }
+ if (OptionHelper.isEmpty(defaultValue)) {
+ errors++;
+ addError("The \"defaultValue\" property must be set");
+ }
+ if (errors == 0) {
+ super.start();
+ }
+ }
+
+ @Override
+ public void stop() {
+ for (Appender<LoggingEvent> appender : appenderTracker.valueList()) {
+ appender.stop();
+ }
+ }
+
@Override
protected void append(LoggingEvent loggingEvent) {
+ if (!isStarted()) {
+ return;
+ }
+
String mdcValue = MDC.get(mdcKey);
if (mdcValue == null) {
- mdcValue = DEFAULT;
+ mdcValue = defaultValue;
}
- Appender<LoggingEvent> appender = appenderMap.get(mdcValue);
+ long timestamp = loggingEvent.getTimeStamp();
+
+ Appender<LoggingEvent> appender = appenderTracker.get(mdcValue, timestamp);
if (appender == null) {
try {
appender = appenderFactory.buildAppender(context, mdcKey, mdcValue);
+ if (appender != null) {
+ appenderTracker.put(mdcValue, appender, timestamp);
+ }
} catch (JoranException e) {
addError("Failed to build appender for " + mdcKey + "=" + mdcValue, e);
return;
}
}
+ appenderTracker.stopStaleAppenders(timestamp);
appender.doAppend(loggingEvent);
}
@@ -54,6 +102,29 @@
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;
+ }
+
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/hoard/HoardingJoranConfigurator.java Wed Dec 17 18:46:01 2008
@@ -4,6 +4,7 @@
import java.util.HashMap;
import java.util.Map;
+import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.joran.GenericConfigurator;
import ch.qos.logback.core.joran.action.ActionConst;
@@ -55,10 +56,11 @@
interpreter.setInterpretationContextPropertiesMap(propertiesMap);
}
- public Appender getAppender() {
+ @SuppressWarnings("unchecked")
+ public Appender<LoggingEvent> getAppender() {
Map<String, Object> omap = interpreter.getInterpretationContext().getObjectMap();
HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG);
Collection values = map.values();
- return (Appender) values.iterator().next();
+ return (Appender<LoggingEvent>) values.iterator().next();
}
}
Modified: logback/trunk/logback-classic/src/test/input/joran/hoard/hoard0.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/hoard/hoard0.xml (original)
+++ logback/trunk/logback-classic/src/test/input/joran/hoard/hoard0.xml Wed Dec 17 18:46:01 2008
@@ -7,10 +7,9 @@
class="ch.qos.logback.classic.hoard.HoardingAppender">
<mdcKey>userid</mdcKey>
-
-
+ <default>asdad</default>
<hoard>
- <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
<File>${userid}.log</File>
<Append>true</Append>
<layout class="ch.qos.logback.classic.PatternLayout">
@@ -18,7 +17,6 @@
</layout>
</appender>
</hoard>
-
</appender>
<root level="DEBUG">
Added: logback/trunk/logback-classic/src/test/input/joran/hoard/smoke.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/joran/hoard/smoke.xml Wed Dec 17 18:46:01 2008
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration>
+
+<configuration debug="true">
+
+ <appender name="HOARD"
+ class="ch.qos.logback.classic.hoard.HoardingAppender">
+
+ <mdcKey>userid</mdcKey>
+ <defaultValue>smoke</defaultValue>
+ <hoard>
+ <appender name="list-${userid}" class="ch.qos.logback.core.read.ListAppender"/>
+ </hoard>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="HOARD" />
+ </root>
+
+</configuration>
Added: logback/trunk/logback-classic/src/test/input/joran/hoard/unsetDefaultValueProperty.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/joran/hoard/unsetDefaultValueProperty.xml Wed Dec 17 18:46:01 2008
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration>
+
+<configuration debug="true">
+
+ <appender name="HOARD"
+ class="ch.qos.logback.classic.hoard.HoardingAppender">
+
+ <mdcKey>userid</mdcKey>
+ <hoard>
+ <appender name="list-${userid}" class="ch.qos.logback.core.read.ListAppender"/>
+ </hoard>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="HOARD" />
+ </root>
+
+</configuration>
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java Wed Dec 17 18:46:01 2008
@@ -20,20 +20,23 @@
TestSuite suite = new TestSuite();
suite.addTest(org.slf4j.impl.PackageTest.suite());
- suite.addTest(new JUnit4TestAdapter(ch.qos.logback.classic.PackageTest.class));
+ suite.addTest(new JUnit4TestAdapter(
+ ch.qos.logback.classic.PackageTest.class));
suite.addTest(ch.qos.logback.classic.util.PackageTest.suite());
suite.addTest(ch.qos.logback.classic.control.PackageTest.suite());
suite.addTest(ch.qos.logback.classic.joran.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.jmx.PackageTest.suite());
+ suite.addTest(ch.qos.logback.classic.jmx.PackageTest.suite());
suite.addTest(ch.qos.logback.classic.boolex.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.selector.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.html.PackageTest.suite());
+ suite.addTest(ch.qos.logback.classic.selector.PackageTest.suite());
+ suite.addTest(ch.qos.logback.classic.html.PackageTest.suite());
suite.addTest(ch.qos.logback.classic.net.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.pattern.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.db.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.spi.PackageTest.suite());
- suite.addTest(ch.qos.logback.classic.turbo.PackageTest.suite());
-
+ suite.addTest(ch.qos.logback.classic.pattern.PackageTest.suite());
+ suite.addTest(ch.qos.logback.classic.db.PackageTest.suite());
+ suite.addTest(ch.qos.logback.classic.spi.PackageTest.suite());
+ suite.addTest(ch.qos.logback.classic.turbo.PackageTest.suite());
+ suite.addTest(new JUnit4TestAdapter(
+ ch.qos.logback.classic.hoard.PackageTest.class));
+
return suite;
}
}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,53 @@
+package ch.qos.logback.classic.hoard;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.read.ListAppender;
+
+public class AppenderTrackerTest {
+
+
+ Context context = new ContextBase();
+ AppenderTracker<Object> appenderTracker = new AppenderTrackerImpl<Object>();
+ ListAppender<Object> la = new ListAppender<Object>();
+
+ @Before
+ public void setUp() {
+ la.setContext(context);
+ la.start();
+ }
+
+ @Test
+ public void empty() {
+ long now = 3000;
+ assertNull(appenderTracker.get("a", now++));
+ now += AppenderTrackerImpl.THRESHOLD+1000;
+ appenderTracker.stopStaleAppenders(now);
+ assertNull(appenderTracker.get("a", now++));
+ }
+
+ @Test
+ public void smoke() {
+ assertTrue(la.isStarted());
+ long now = 3000;
+ appenderTracker.put("a", la, now);
+ assertEquals(la, appenderTracker.get("a", now++));
+ now += AppenderTrackerImpl.THRESHOLD+1000;
+ appenderTracker.stopStaleAppenders(now);
+ assertFalse(la.isStarted());
+ assertNull(appenderTracker.get("a", now++));
+ }
+
+ @Test
+ public void scenarioBased() {
+
+ }
+}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java Wed Dec 17 18:46:01 2008
@@ -9,13 +9,21 @@
*/
package ch.qos.logback.classic.hoard;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
import org.junit.Test;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.util.TeztConstants;
import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.read.ListAppender;
import ch.qos.logback.core.util.StatusPrinter;
public class HoardingAppenderTest {
@@ -32,6 +40,29 @@
jc.doConfigure(file);
}
+ @Test
+ public void unsetDefaultValueProperty() throws JoranException {
+ configure(PREFIX + "unsetDefaultValueProperty.xml");
+ logger.debug("hello");
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ assertFalse(ha.isStarted());
+
+ }
+
+ @Test
+ public void smoke() throws JoranException {
+ configure(PREFIX + "smoke.xml");
+ logger.debug("smoke");
+ long timestamp = 0;
+ HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+ ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("smoke", timestamp);
+ StatusPrinter.print(loggerContext);
+
+ assertNotNull(listAppender);
+ List<LoggingEvent> eventList = listAppender.list;
+ assertEquals(1, listAppender.list.size());
+ assertEquals("smoke", eventList.get(0).getMessage());
+ }
@Test
public void testLevel() throws JoranException {
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/PackageTest.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,19 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.hoard;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+(a)RunWith(Suite.class)
+(a)SuiteClasses({HoardingAppenderTest.class})
+public class PackageTest {
+}
\ No newline at end of file
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/ScenarioBasedAppenderTrackerTest.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,53 @@
+/**
+ * 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.hoard;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class ScenarioBasedAppenderTrackerTest {
+
+ Simulator simulator;
+
+ void verify() {
+ AppenderTracker at = simulator.appenderTracker;
+ AppenderTracker t_at = simulator.t_appenderTracker;
+ //List<String> resultKeys = at.keyList();
+ //List<String> witnessKeys = t_at.keyList();
+ assertEquals(t_at.keyList(), at.keyList());
+ }
+
+ @Test
+ public void shortTest() {
+ simulator = new Simulator(20, AppenderTracker.THRESHOLD / 2);
+ simulator.buildScenario(200);
+ simulator.simulate();
+ verify();
+ }
+
+ @Test
+ public void mediumTest() {
+ simulator = new Simulator(100, AppenderTracker.THRESHOLD / 2);
+ simulator.buildScenario(20000);
+ simulator.simulate();
+ verify();
+ }
+
+ @Test
+ @Ignore
+ public void longetTest() {
+ simulator = new Simulator(100, AppenderTracker.THRESHOLD / 200);
+ simulator.buildScenario(2000000);
+ simulator.simulate();
+ verify();
+ }
+}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/Simulator.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,92 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.hoard;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import ch.qos.logback.classic.hoard.tracker.SimulationEvent;
+import ch.qos.logback.classic.hoard.tracker.AppenderTrackerTImpl;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.appender.NOPAppender;
+
+/**
+ * Simulate use of AppenderTracker by HoardAppender.
+ *
+ * @author ceki
+ *
+ */
+public class Simulator {
+
+ AppenderTrackerImpl<Object> appenderTracker = new AppenderTrackerImpl<Object>();
+ AppenderTrackerTImpl t_appenderTracker = new AppenderTrackerTImpl();
+
+ List<String> keySpace = new ArrayList<String>();
+ List<SimulationEvent> scenario = new ArrayList<SimulationEvent>();
+ Random randomKeyGen = new Random(100);
+
+ Random random = new Random(11234);
+
+ final int maxTimestampInc;
+ long timestamp = 30000;
+
+ Simulator(int keySpaceLen, int maxTimestampInc) {
+ this.maxTimestampInc = maxTimestampInc;
+ Map<String, String> checkMap = new HashMap<String, String>();
+ for (int i = 0; i < keySpaceLen; i++) {
+ String k = getRandomKeyStr();
+ if (checkMap.containsKey(k)) {
+ System.out.println("random key collision occured");
+ k += "" + i;
+ }
+ keySpace.add(k);
+ checkMap.put(k, k);
+ }
+
+ }
+
+ private String getRandomKeyStr() {
+ int ri = randomKeyGen.nextInt();
+ String s = String.format("%X", ri);
+ return s;
+ }
+
+ void buildScenario(int simLen) {
+ int keySpaceLen = keySpace.size();
+ for (int i = 0; i < simLen; i++) {
+ int index = random.nextInt(keySpaceLen);
+ timestamp += random.nextInt(maxTimestampInc);
+ String key = keySpace.get(index);
+ scenario.add(new SimulationEvent(key, timestamp));
+ }
+ }
+
+ public void simulate() {
+ for (SimulationEvent simeEvent : scenario) {
+ play(simeEvent, appenderTracker);
+ play(simeEvent, t_appenderTracker);
+ }
+ }
+
+ void play(SimulationEvent simulationEvent,
+ AppenderTracker<Object> appenderTracker) {
+ String mdcValue = simulationEvent.key;
+ long timestamp = simulationEvent.timestamp;
+ Appender<Object> appender = appenderTracker.get(mdcValue, timestamp);
+ if (appender == null) {
+ appender = new NOPAppender<Object>();
+ appenderTracker.put(mdcValue, appender, timestamp);
+ }
+ appenderTracker.stopStaleAppenders(timestamp);
+ }
+}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/AppenderTrackerTImpl.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,98 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.hoard.tracker;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import ch.qos.logback.classic.hoard.AppenderTracker;
+import ch.qos.logback.core.Appender;
+
+/**
+ * This is an alternative (slower) implementation of AppenderTracker for testing
+ * purposes.
+ *
+ * @author Ceki Gulcu
+ */
+public class AppenderTrackerTImpl implements AppenderTracker<Object> {
+
+ List<TEntry> entryList = new LinkedList<TEntry>();
+ long lastCheck = 0;
+
+ public AppenderTrackerTImpl() {
+ }
+
+ @SuppressWarnings("unchecked")
+ synchronized public void put(String k, Appender<Object> appender,
+ long timestamp) {
+ TEntry te = getEntry(k);
+ if (te != null) {
+ te.timestamp = timestamp;
+ } else {
+ te = new TEntry(k, appender, timestamp);
+ entryList.add(te);
+ }
+ Collections.sort(entryList);
+ }
+
+ @SuppressWarnings("unchecked")
+ synchronized public Appender<Object> get(String k, long timestamp) {
+ TEntry te = getEntry(k);
+ if (te == null) {
+ return null;
+ } else {
+ te.timestamp = timestamp;
+ Collections.sort(entryList);
+ return te.appender;
+ }
+ }
+
+ synchronized public void stopStaleAppenders(long timestamp) {
+ if (lastCheck + MILLIS_IN_ONE_SECOND > timestamp) {
+ return;
+ }
+ lastCheck = timestamp;
+ while (entryList.size() != 0 && isEntryStale(entryList.get(0), timestamp)) {
+ entryList.remove(0);
+ }
+ }
+
+ final private boolean isEntryStale(TEntry entry, long now) {
+ return ((entry.timestamp + THRESHOLD) < now);
+ }
+
+ synchronized public List<String> keyList() {
+ List<String> keyList = new ArrayList<String>();
+ for (TEntry e : entryList) {
+ keyList.add(e.key);
+ }
+ return keyList;
+ }
+
+ synchronized public List<Appender<Object>> valueList() {
+ List<Appender<Object>> appenderList = new ArrayList<Appender<Object>>();
+ for (TEntry e : entryList) {
+ appenderList.add(e.appender);
+ }
+ return appenderList;
+ }
+
+ private TEntry getEntry(String k) {
+ for (int i = 0; i < entryList.size(); i++) {
+ TEntry te = entryList.get(i);
+ if (te.key.equals(k)) {
+ return te;
+ }
+ }
+ return null;
+ }
+}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/SimulationEvent.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/SimulationEvent.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,17 @@
+package ch.qos.logback.classic.hoard.tracker;
+
+
+public class SimulationEvent {
+
+ public String key;
+ public long timestamp;
+
+ public SimulationEvent(String key, long timestamp) {
+ this.key = key;
+ this.timestamp = timestamp;
+ }
+
+ public String toString() {
+ return "Event: k=" + key +", timestamp=" + timestamp;
+ }
+}
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/TEntry.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/tracker/TEntry.java Wed Dec 17 18:46:01 2008
@@ -0,0 +1,45 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2008, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.hoard.tracker;
+
+import ch.qos.logback.core.Appender;
+
+public class TEntry implements Comparable {
+
+ String key;
+ long timestamp;
+ Appender<Object> appender;
+
+ TEntry(String key, Appender<Object> appender, long timestamp) {
+ this.key = key;
+ this.appender = appender;
+ this.timestamp = timestamp;
+ }
+
+ public int compareTo(Object o) {
+ if(!(o instanceof TEntry)) {
+ throw new IllegalArgumentException("arguments must be of type "+TEntry.class);
+ }
+
+ TEntry other = (TEntry) o;
+ if(timestamp > other.timestamp) {
+ return 1;
+ }
+ if(timestamp == other.timestamp) {
+ return 0;
+ }
+ return -1;
+ }
+
+ @Override
+ public String toString() {
+ return "("+key+","+timestamp+")";
+ }
+}
1
0
[JIRA] Created: (LBCLASSIC-95) clean up appenders as their MDC value is cleared
by Ceki Gulcu (JIRA) 17 Dec '08
by Ceki Gulcu (JIRA) 17 Dec '08
17 Dec '08
clean up appenders as their MDC value is cleared
------------------------------------------------
Key: LBCLASSIC-95
URL: http://jira.qos.ch/browse/LBCLASSIC-95
Project: logback-classic
Issue Type: Sub-task
Reporter: Ceki Gulcu
Assignee: Ceki Gulcu
--
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
Author: ceki
Date: Mon Dec 15 22:41:53 2008
New Revision: 2081
Modified:
logback-demo/trunk/pom.xml
Log:
Modified: logback-demo/trunk/pom.xml
==============================================================================
--- logback-demo/trunk/pom.xml (original)
+++ logback-demo/trunk/pom.xml Mon Dec 15 22:41:53 2008
@@ -9,7 +9,7 @@
<version>1.0</version>
<properties>
- <lb.version>0.9.10-SNAPSHOT</lb.version>
+ <lb.version>0.9.13</lb.version>
</properties>
1
0
svn commit: r2080 - in logback-demo/trunk/src: etc main/java/ch/qos/logback/demo main/java/ch/qos/logback/demo/prime main/java/ch/qos/logback/demo/reload main/java/ch/qos/logback/demo/statii main/java/ch/qos/logback/demo/util main/resources
by noreply.ceki@qos.ch 15 Dec '08
by noreply.ceki@qos.ch 15 Dec '08
15 Dec '08
Author: ceki
Date: Mon Dec 15 22:41:47 2008
New Revision: 2080
Modified:
logback-demo/trunk/src/etc/logback-access.xml
logback-demo/trunk/src/main/java/ch/qos/logback/demo/LoggingTask.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/ViewLastLog.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/NumberCruncherImpl.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/PrimeForm.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/reload/ReloadConfigAction.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseContextAction.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseModuleAction.java
logback-demo/trunk/src/main/java/ch/qos/logback/demo/util/EnhancedStatusPrinter.java
logback-demo/trunk/src/main/resources/logback.xml
Log:
Modified: logback-demo/trunk/src/etc/logback-access.xml
==============================================================================
--- logback-demo/trunk/src/etc/logback-access.xml (original)
+++ logback-demo/trunk/src/etc/logback-access.xml Mon Dec 15 22:41:47 2008
@@ -50,14 +50,16 @@
-->
- <!-- Part JMX
+ <!-- Part JMX
<filter class="ch.qos.logback.access.filter.CountingFilter">
<name>countingFilter</name>
</filter>
-->
-
+
+ <!--
<appender-ref ref="STDOUT" />
-
+ -->
+
<!-- Lottery to Console
<appender-ref ref="STDOUT_LOTTERY" />
-->
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/LoggingTask.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/LoggingTask.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/LoggingTask.java Mon Dec 15 22:41:47 2008
@@ -8,17 +8,24 @@
public class LoggingTask implements Runnable {
static Marker HOWDY_MARKER = MarkerFactory.getMarker("HOWDY");
+ static Marker TOTO = MarkerFactory.getMarker("TOTO");
+
+ static {
+ TOTO.add(HOWDY_MARKER);
+ }
Logger logger = LoggerFactory.getLogger(LoggingTask.class);
-
+
String msg;
+
int i = 0;
-
+
LoggingTask(String msg) {
this.msg = msg;
}
+
public void run() {
- //logger.info(msg +" - " + (i++));
- logger.info(HOWDY_MARKER, msg +" - " + (i++));
+ // logger.info(msg +" - " + (i++));
+ logger.info(HOWDY_MARKER, msg + " - " + (i++), new Exception("e"));
}
}
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/ViewLastLog.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/ViewLastLog.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/ViewLastLog.java Mon Dec 15 22:41:47 2008
@@ -16,11 +16,11 @@
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.html.HTMLLayout;
import ch.qos.logback.classic.html.UrlCssBuilder;
+import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.read.CyclicBufferAppender;
-import ch.qos.logback.classic.spi.ContextListener;
-public class ViewLastLog extends HttpServlet implements ContextListener {
+public class ViewLastLog extends HttpServlet implements LoggerContextListener {
private static final long serialVersionUID = -3551928133801157219L;
private boolean listening = false;
@@ -119,4 +119,11 @@
layout.setTitle("Last Logging Events");
layout.start();
}
+
+ public boolean isResetResistant() {
+ return false;
+ }
+
+ public void onStop(LoggerContext arg0) {
+ }
}
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/NumberCruncherImpl.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/NumberCruncherImpl.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/NumberCruncherImpl.java Mon Dec 15 22:41:47 2008
@@ -33,8 +33,11 @@
logger.info("Beginning to factor.");
if (number <= 0) {
- throw new IllegalArgumentException(number +
+ IllegalArgumentException e = new IllegalArgumentException(number +
" is not a positive integer.");
+ logger.error("Bad argument", e);
+ //throw e;
+ return new Long[] { 0L };
} else if (number == 1) {
return new Long[] { 1L };
}
@@ -51,8 +54,8 @@
logger.warn("Already tried " + MAX_COUNT_BEFORE_WARN + " factors.");
count = 0;
}
- logger.debug("Trying "+i+" as a factor.");
- //logger.debug("Trying {} as a factor.", i);
+ //logger.debug("Trying "+i+" as a factor.");
+ logger.debug("Trying {} as a factor.", i);
if ((n % i) == 0) {
logger.info("Found factor " + i);
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/PrimeForm.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/PrimeForm.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/prime/PrimeForm.java Mon Dec 15 22:41:47 2008
@@ -26,7 +26,7 @@
ActionMapping mapping, HttpServletRequest request ) {
ActionErrors errors = new ActionErrors();
- if( getNumber() == null || getNumber().longValue() < 1 ) {
+ if( getNumber() == null || ((getNumber().longValue()) != -1 && (getNumber().longValue() < 1))) {
errors.add("number",new ActionMessage("errors.minNumber"));
}
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/reload/ReloadConfigAction.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/reload/ReloadConfigAction.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/reload/ReloadConfigAction.java Mon Dec 15 22:41:47 2008
@@ -64,7 +64,7 @@
configurator.setContext(lc);
logger.info("Shutting down active logging configuration.");
- lc.shutdownAndReset();
+ lc.reset();
configurator.doConfigure(url);
lc.start();
logger.info("Now using new configuration.");
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseContextAction.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseContextAction.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseContextAction.java Mon Dec 15 22:41:47 2008
@@ -31,12 +31,12 @@
ChooseContextForm form = (ChooseContextForm) actionForm;
String contextName = form.getContextName();
- LoggerContext context = StaticLoggerBinder.SINGLETON.getContextSelector().getLoggerContext(contextName);
+ LoggerContext context = StaticLoggerBinder.getSingleton().getContextSelector().getLoggerContext(contextName);
EnhancedStatusPrinter.print(buf, context.getStatusManager());
request.setAttribute(Constants.STATUS, buf.toString());
}
- List<String> contextNames = StaticLoggerBinder.SINGLETON.getContextSelector().getContextNames();
+ List<String> contextNames = StaticLoggerBinder.getSingleton().getContextSelector().getContextNames();
request.setAttribute(Constants.CONTEXT_LIST, contextNames);
return actionMapping.findForward("next");
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseModuleAction.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseModuleAction.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/statii/ChooseModuleAction.java Mon Dec 15 22:41:47 2008
@@ -48,7 +48,7 @@
request.setAttribute(Constants.STATUS, buf.toString());
} else {
- List<String> contextNames = StaticLoggerBinder.SINGLETON.getContextSelector().getContextNames();
+ List<String> contextNames = StaticLoggerBinder.getSingleton().getContextSelector().getContextNames();
request.setAttribute(Constants.CONTEXT_LIST, contextNames);
}
}
Modified: logback-demo/trunk/src/main/java/ch/qos/logback/demo/util/EnhancedStatusPrinter.java
==============================================================================
--- logback-demo/trunk/src/main/java/ch/qos/logback/demo/util/EnhancedStatusPrinter.java (original)
+++ logback-demo/trunk/src/main/java/ch/qos/logback/demo/util/EnhancedStatusPrinter.java Mon Dec 15 22:41:47 2008
@@ -3,18 +3,17 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
-
import java.util.Iterator;
import java.util.List;
-import ch.qos.logback.classic.pattern.ClassNameAbbreviator;
+import ch.qos.logback.classic.pattern.TargetLengthBasedClassNameAbbreviator;
import ch.qos.logback.core.status.Status;
import ch.qos.logback.core.status.StatusManager;
public class EnhancedStatusPrinter {
private static final int ABBR_LENGTH = 17;
- private static ClassNameAbbreviator abbreviator = new ClassNameAbbreviator(ABBR_LENGTH);
+ private static TargetLengthBasedClassNameAbbreviator abbreviator = new TargetLengthBasedClassNameAbbreviator(ABBR_LENGTH);
private static SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd'T'HH:mm:ss");
public static String print(Status s) {
@@ -81,7 +80,6 @@
Status child = ite.next();
print(buf, indentation+" ", child);
}
-
}
}
Modified: logback-demo/trunk/src/main/resources/logback.xml
==============================================================================
--- logback-demo/trunk/src/main/resources/logback.xml (original)
+++ logback-demo/trunk/src/main/resources/logback.xml Mon Dec 15 22:41:47 2008
@@ -5,7 +5,7 @@
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{32} - %msg%n</pattern>
+ <pattern>%marker %d{HH:mm:ss.SSS} [%thread] %-5level %logger{32} - %msg%n</pattern>
</layout>
</appender>
@@ -15,25 +15,26 @@
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
- logFile.%d{yyyy-MM-dd_HH-mm}.log.zip
+ z:/logFile.%d{yyyy-MM-dd_HH-mm}.log.zip
</FileNamePattern>
+ <maxHistory>5</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>
- %-26(%d{HH:mm:ss,SSS} [%thread]) %-5level %logger{32} - %msg%n
+ <Pattern>%marker %-26(%d{HH:mm:ss,SSS} [%thread]) %-5level %logger{32} - %msg%n
</Pattern>
</layout>
</appender>
- <!-- Basic Cyclic buffer
+ <!-- Basic Cyclic buffer
<appender name="CYCLIC"
class="ch.qos.logback.core.read.CyclicBufferAppender">
<MaxSize>512</MaxSize>
</appender>
- -->
+ -->
- <!-- Cyclic buffer with Evaluator
+ <!-- Cyclic buffer with Evaluator -->
+ <!-- -->
<appender name="CYCLIC"
class="ch.qos.logback.core.read.CyclicBufferAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
@@ -47,37 +48,43 @@
<OnMatch>DENY</OnMatch>
</filter>
<MaxSize>512</MaxSize>
- -->
-
- <!-- TurboFilter: by MDC value
+ </appender>
+
+
+ <!-- TurboFilter: by MDC value
<turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
<MDCKey>username</MDCKey>
<Value>sebastien</Value>
<OnMatch>ACCEPT</OnMatch>
</turboFilter>
- -->
+ -->
- <!-- TurboFilter: by Marker
+ <!-- TurboFilter: by Marker -->
+ <!--
<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
<Name>HOWDY_FILTER</Name>
<Marker>HOWDY</Marker>
<OnMatch>DENY</OnMatch>
</turboFilter>
- -->
+-->
+
<!-- JMX Configurator -->
+ <!-- -->
<jmxConfigurator />
-
+
+
<root>
<level value="DEBUG" />
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
-
- <!-- Part I: Basic Cyclic buffer
+
+ <!--
+ Part I: Basic Cyclic buffer -->
<appender-ref ref="CYCLIC" />
- -->
-
+
+
</root>
</configuration>
1
0