[LOGBack-dev] svn commit: r535 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic main/java/ch/qos/logback/classic/spi test/java/ch/qos/logback/classic/net
noreply.seb at qos.ch
noreply.seb at qos.ch
Fri Sep 8 12:29:30 CEST 2006
Author: seb
Date: Fri Sep 8 12:29:30 2006
New Revision: 535
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/MDC.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java
Log:
- Updated MDC to create a new map instance each time a property is added
- Modified method name in MDC: getContext is now getPropertyMap
- Updated LoggingEvent to provide access to the MDC Properties
- Updated SocketAppenderTest to verify that the LoggingEvent always exposes the last version of the MDC Properties
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/MDC.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/MDC.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/MDC.java Fri Sep 8 12:29:30 2006
@@ -30,16 +30,23 @@
* <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 map
+ * and not send a reference to the old map, thus not allowing the remote logback
+ * component to see the latest changes.
*/
public static void put(String key, String val) {
- HashMap<String, String> hashMap = threadLocal.get();
+ HashMap<String, String> oldMap = threadLocal.get();
- if (hashMap == null) {
- hashMap = new HashMap<String, String>();
- threadLocal.set(hashMap);
+ HashMap<String, String> newMap = new HashMap<String, String>();
+ if (oldMap != null) {
+ newMap.putAll(oldMap);
}
-
- hashMap.put(key, val);
+ threadLocal.set(newMap);
+
+ newMap.put(key, val);
}
/**
@@ -60,13 +67,22 @@
/**
* 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.
*/
public static void remove(String key) {
- HashMap<String, String> hashMap = threadLocal.get();
+ HashMap<String, String> oldMap = threadLocal.get();
- if (hashMap != null) {
- hashMap.remove(key);
+ HashMap<String, String> newMap = new HashMap<String, String>();
+ if (oldMap != null) {
+ newMap.putAll(oldMap);
}
+
+ newMap.remove(key);
}
/**
@@ -85,7 +101,7 @@
* Get the current thread's MDC as a map. This method is intended to be used
* internally.
*/
- public static Map<String, String> getContext() {
+ public static Map<String, String> getPropertyMap() {
return threadLocal.get();
}
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEvent.java Fri Sep 8 12:29:30 2006
@@ -14,13 +14,14 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
+import java.util.Map;
import org.slf4j.Marker;
import org.slf4j.impl.MessageFormatter;
-
-import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.MDC;
/**
* The internal representation of logging events. When an affirmative decision
@@ -84,8 +85,10 @@
private CallerData[] callerDataArray;
private LoggerRemoteView loggerRemoteView;
-
+
private Marker marker;
+
+ private Map<String, String> MDCPropertyMap;
/**
* The number of milliseconds elapsed from 1/1/1970 until logging event was
@@ -262,20 +265,22 @@
public String getFormattedMessage() {
return formattedMessage;
}
+
+ public Map<String, String> getMDCPropertyMap() {
+ //no lazy init since the MDC might
+ //change its map instance.
+ this.MDCPropertyMap = MDC.getPropertyMap();
+ return MDCPropertyMap;
+ }
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
- //out.writeObject(loggerView);
-
out.writeInt(level.levelInt);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
- //String loggerName = (String) in.readObject();
- //logger = LoggerFactory.getLogger(loggerName);
- //loggerView = (LoggerView)in.readObject();
int levelInt = in.readInt();
level = Level.toLevel(levelInt);
}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java Fri Sep 8 12:29:30 2006
@@ -3,16 +3,21 @@
import java.util.Map;
import junit.framework.TestCase;
+import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.MDC;
import ch.qos.logback.classic.spi.LoggerContextRemoteView;
import ch.qos.logback.classic.spi.LoggerRemoteView;
import ch.qos.logback.classic.spi.LoggingEvent;
public class SocketAppenderTest extends TestCase {
+ private LoggerContext lc;
+ private MockSocketServer mockSocketServer;
+
public void testStartFailNoRemoteHost() {
- LoggerContext lc = new LoggerContext();
+ lc = new LoggerContext();
SocketAppender appender = new SocketAppender();
appender.setContext(lc);
appender.setPort(123);
@@ -21,36 +26,39 @@
}
public void testRecieveMessage() throws InterruptedException {
- MockSocketServer mockServer = new MockSocketServer(1);
- mockServer.start();
- // give MockSyslogServer head start
- Thread.sleep(100);
+ startServer(1);
+ configureClient();
+
+ Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
+ logger.debug("test msg");
+ // Wait max 2 seconds for mock server to finish. However, it should
+ // finish much sooner than that.
+ mockSocketServer.join(2000);
+ assertTrue(mockSocketServer.finished);
+ assertEquals(1, mockSocketServer.loggingEventList.size());
+
+ LoggingEvent remoteEvent = mockSocketServer.loggingEventList.get(0);
+ assertEquals("test msg", remoteEvent.getMessage());
+ assertEquals(Level.DEBUG, remoteEvent.getLevel());
+ }
+
+ public void testRecieveWithContext() throws InterruptedException {
+ startServer(1);
+ configureClient();
- // client configuration
- LoggerContext lc = new LoggerContext();
- lc.setName("test");
- lc.setProperty("testKey", "testValue");
- Logger root = lc.getLogger(LoggerContext.ROOT_NAME);
- SocketAppender socketAppender = new SocketAppender();
- socketAppender.setContext(lc);
- socketAppender.setName("socket");
- socketAppender.setPort(4560);
- socketAppender.setRemoteHost("localhost");
- root.addAppender(socketAppender);
- socketAppender.start();
-
Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
logger.debug("test msg");
// Wait max 2 seconds for mock server to finish. However, it should
// finish much sooner than that.
- mockServer.join(2000);
- assertTrue(mockServer.finished);
- assertEquals(1, mockServer.loggingEventList.size());
- LoggingEvent remoteEvent = mockServer.loggingEventList.get(0);
+ mockSocketServer.join(2000);
+ assertTrue(mockSocketServer.finished);
+ assertEquals(1, mockSocketServer.loggingEventList.size());
+
+ LoggingEvent remoteEvent = mockSocketServer.loggingEventList.get(0);
+
LoggerRemoteView loggerRemoteView = remoteEvent.getLoggerRemoteView();
- assertEquals("test msg", remoteEvent.getMessage());
assertNotNull(loggerRemoteView);
assertEquals("root", loggerRemoteView.getName());
@@ -60,4 +68,71 @@
Map<String, String> props = loggerContextRemoteView.getPropertyMap();
assertEquals("testValue", props.get("testKey"));
}
+
+
+ public void testMessageWithMDC() throws InterruptedException {
+ startServer(1);
+ configureClient();
+
+ Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
+
+ MDC.put("key", "testValue");
+ logger.debug("test msg");
+
+ // Wait max 2 seconds for mock server to finish. However, it should
+ // finish much sooner than that.
+ mockSocketServer.join(2000);
+ assertTrue(mockSocketServer.finished);
+ assertEquals(1, mockSocketServer.loggingEventList.size());
+
+ LoggingEvent remoteEvent = mockSocketServer.loggingEventList.get(0);
+ Map<String, String> MDCPropertyMap = remoteEvent.getMDCPropertyMap();
+ assertEquals("testValue", MDCPropertyMap.get("key"));
+ }
+
+ public void testMessageWithUpdatedMDC() throws InterruptedException {
+ startServer(2);
+ configureClient();
+
+ Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
+
+ MDC.put("key", "testValue");
+ logger.debug("test msg");
+
+ MDC.put("key", "updatedTestValue");
+ logger.debug("test msg 2");
+
+ // Wait max 2 seconds for mock server to finish. However, it should
+ // finish much sooner than that.
+ mockSocketServer.join(2000);
+ assertTrue(mockSocketServer.finished);
+ assertEquals(2, mockSocketServer.loggingEventList.size());
+
+ //We observe the second logging event. It should provide us with
+ //the updated MDC property.
+ LoggingEvent remoteEvent = mockSocketServer.loggingEventList.get(1);
+ Map<String, String> MDCPropertyMap = remoteEvent.getMDCPropertyMap();
+ assertEquals("updatedTestValue", MDCPropertyMap.get("key"));
+ }
+
+ private void startServer(int expectedEventNumber) throws InterruptedException {
+ mockSocketServer = new MockSocketServer(expectedEventNumber);
+ mockSocketServer.start();
+ // give MockSocketServer head start
+ Thread.sleep(100);
+ }
+
+ private void configureClient() {
+ lc = new LoggerContext();
+ lc.setName("test");
+ lc.setProperty("testKey", "testValue");
+ Logger root = lc.getLogger(LoggerContext.ROOT_NAME);
+ SocketAppender socketAppender = new SocketAppender();
+ socketAppender.setContext(lc);
+ socketAppender.setName("socket");
+ socketAppender.setPort(4560);
+ socketAppender.setRemoteHost("localhost");
+ root.addAppender(socketAppender);
+ socketAppender.start();
+ }
}
More information about the logback-dev
mailing list