You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ma...@apache.org on 2007/10/23 23:29:17 UTC

svn commit: r587660 - in /mina/trunk: core/src/main/java/org/apache/mina/filter/logging/ core/src/test/java/org/apache/mina/filter/logging/ example/src/main/resources/ example/src/main/resources/org/apache/mina/example/chat/

Author: maarten
Date: Tue Oct 23 14:29:16 2007
New Revision: 587660

URL: http://svn.apache.org/viewvc?rev=587660&view=rev
Log:
MdcInjectionFilter: added constructor that takes EnumSet of all keys to should be set in the MDC

Modified:
    mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java
    mina/trunk/core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.java
    mina/trunk/example/src/main/resources/log4j.properties
    mina/trunk/example/src/main/resources/org/apache/mina/example/chat/serverContext.xml

Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java?rev=587660&r1=587659&r2=587660&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/logging/MdcInjectionFilter.java Tue Oct 23 14:29:16 2007
@@ -22,6 +22,9 @@
 import java.net.InetSocketAddress;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
 
 import org.apache.mina.common.AttributeKey;
 import org.apache.mina.common.IoFilterEvent;
@@ -35,7 +38,7 @@
  * These properties will be set in the MDC for all logging events that are generated
  * down the call stack, even in code that is not aware of MINA.
  *
- * The following properties will be set for all transports:
+ * By default, the following properties will be set for all transports:
  * <ul>
  *  <li>"handlerClass"</li>
  *  <li>"remoteAddress"</li>
@@ -66,9 +69,16 @@
 
 public class MdcInjectionFilter extends WrappingFilter {
 
+    public enum MdcKey {
+        handlerClass, remoteAddress, localAddress,
+        remoteIp, remotePort, localIp, localPort }
+
     /** key used for storing the context map in the IoSession */
     private static final AttributeKey CONTEXT_KEY = new AttributeKey(MdcInjectionFilter.class, "context");
 
+    /** key used for storing the mDCInjectionFilter  itself in the IoSession */
+    private static final AttributeKey MDC_FILTER_KEY = new AttributeKey(MdcInjectionFilter.class, "mdcFilter");
+
     private ThreadLocal<Integer> callDepth = new ThreadLocal<Integer>() {
         @Override
         protected Integer initialValue() {
@@ -76,12 +86,50 @@
         }
     };
 
+    private EnumSet<MdcKey> mdcKeys;
+
+    /**
+     * Use this constructor when you want to specify which keys to add to the MDC.
+     * You could still add custom keys via <code>setproperty</code>
+     * @param keys set of keys that should be added to the MDC
+     *
+     * @see #setProperty(org.apache.mina.common.IoSession, String, String)
+     */
+    public MdcInjectionFilter(EnumSet<MdcKey> keys) {
+        this.mdcKeys = keys;
+    }
+
+    /**
+     * Use this constructor when you want to specify which keys to add to the MDC
+     * You could still add custom keys via <code>setProperty</code>
+     * @param keys list of keys that should be added to the MDC
+     *
+     * @see #setProperty(org.apache.mina.common.IoSession, String, String)
+     */
+    public MdcInjectionFilter(MdcKey... keys) {
+        Set<MdcKey> keySet = new HashSet<MdcKey>();
+        for (MdcKey key : keys) {
+            keySet.add(key);
+        }
+        this.mdcKeys = EnumSet.copyOf(keySet);        
+    }
+
+
+    public MdcInjectionFilter() {
+      this.mdcKeys = EnumSet.allOf(MdcKey.class);
+    }
+
     @Override
     protected void filter(IoFilterEvent event) throws Exception {
         // since this method can potentially call into itself
         // we need to check the call depth before clearing the MDC
         callDepth.set (callDepth.get() + 1);
-        Context context = getContext(event.getSession());
+        Context context = getAndFillContext(event.getSession());
+
+        if (event.getSession().getAttribute(MDC_FILTER_KEY) == null) {
+          event.getSession().setAttribute(MDC_FILTER_KEY, this);  
+        }
+
         /* copy context to the MDC */
         for (Map.Entry<String,String> e : context.entrySet()) {
             MDC.put(e.getKey(), e.getValue());
@@ -101,12 +149,18 @@
         }
     }
 
+    private Context getAndFillContext(final IoSession session) {
+        Context context = getContext(session);
+        if (context.isEmpty()) {
+            fillContext(session, context);
+        }
+        return context;
+    }
 
     private static Context getContext(final IoSession session) {
         Context context = (Context) session.getAttribute(CONTEXT_KEY);
         if (context == null) {
             context = new Context();
-            fillContext(session, context);
             session.setAttribute(CONTEXT_KEY, context);
         }
         return context;
@@ -118,17 +172,31 @@
      * @param session the session to map
      * @param context key properties will be added to this map
      */
-    protected static void fillContext(final IoSession session, final Context context) {
-        context.put("handlerClass", session.getHandler().getClass().getName());
-        context.put("remoteAddress", session.getRemoteAddress().toString());
-        context.put("localAddress", session.getLocalAddress().toString());
+    protected void fillContext(final IoSession session, final Context context) {
+        if (mdcKeys.contains(MdcKey.handlerClass)) {
+            context.put(MdcKey.handlerClass.name(), session.getHandler().getClass().getName());
+        }
+        if (mdcKeys.contains(MdcKey.remoteAddress)) {
+            context.put(MdcKey.remoteAddress.name(), session.getRemoteAddress().toString());
+        }
+        if (mdcKeys.contains(MdcKey.localAddress)) {
+            context.put(MdcKey.localAddress.name(), session.getLocalAddress().toString());
+        }
         if (session.getTransportMetadata().getAddressType() == InetSocketAddress.class) {
             InetSocketAddress remoteAddress = (InetSocketAddress) session.getRemoteAddress();
             InetSocketAddress localAddress  = (InetSocketAddress) session.getLocalAddress();
-            context.put("remoteIp", remoteAddress.getAddress().getHostAddress());
-            context.put("remotePort", String.valueOf(remoteAddress.getPort()));
-            context.put("localIp", localAddress.getAddress().getHostAddress());
-            context.put("localPort", String.valueOf(localAddress.getPort()));
+            if (mdcKeys.contains(MdcKey.remoteIp)) {
+                context.put(MdcKey.remoteIp.name(), remoteAddress.getAddress().getHostAddress());
+            }
+            if (mdcKeys.contains(MdcKey.remotePort)) {
+                context.put(MdcKey.remotePort.name(), String.valueOf(remoteAddress.getPort()));
+            }
+            if (mdcKeys.contains(MdcKey.localIp)) {
+                context.put(MdcKey.localIp.name(), localAddress.getAddress().getHostAddress());
+            }
+            if (mdcKeys.contains(MdcKey.localPort)) {
+                context.put(MdcKey.localPort.name(), String.valueOf(localAddress.getPort()));
+            }
         }
     }
 
@@ -162,6 +230,11 @@
 
     private static class Context extends HashMap<String,String> {
         private static final long serialVersionUID = -673025693009555560L;
+    }
+
+    public static void main(String[] args) {
+        String s = MdcKey.handlerClass.name();
+        System.out.println("s = " + s);
     }
 
 }

Modified: mina/trunk/core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.java?rev=587660&r1=587659&r2=587660&view=diff
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.java (original)
+++ mina/trunk/core/src/test/java/org/apache/mina/filter/logging/MdcInjectionFilterTest.java Tue Oct 23 14:29:16 2007
@@ -32,13 +32,7 @@
 import org.apache.log4j.AppenderSkeleton;
 import org.apache.log4j.Level;
 import org.apache.log4j.spi.LoggingEvent;
-import org.apache.mina.common.IoBuffer;
-import org.apache.mina.common.ConnectFuture;
-import org.apache.mina.common.DefaultIoFilterChainBuilder;
-import org.apache.mina.common.IdleStatus;
-import org.apache.mina.common.IoFilterAdapter;
-import org.apache.mina.common.IoHandlerAdapter;
-import org.apache.mina.common.IoSession;
+import org.apache.mina.common.*;
 import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
 import org.apache.mina.filter.codec.ProtocolDecoder;
@@ -148,6 +142,44 @@
         chain.addLast("executor2" , new ExecutorFilter());
         chain.addLast("mdc-injector2", mdcInjectionFilter);
         test(chain);
+    }
+
+    public void testOnlyRemoteAddress() throws IOException, InterruptedException {
+        DefaultIoFilterChainBuilder chain = new DefaultIoFilterChainBuilder();
+        chain.addFirst("mdc-injector", new MdcInjectionFilter(
+            MdcInjectionFilter.MdcKey.remoteAddress));
+        chain.addLast("dummy", new DummyIoFilter());
+        chain.addLast("protocol", new ProtocolCodecFilter(new DummyProtocolCodecFactory()));
+        SimpleIoHandler simpleIoHandler = new SimpleIoHandler();
+        acceptor.setHandler(simpleIoHandler);
+        acceptor.setLocalAddress(new InetSocketAddress(PORT));
+        acceptor.bind();
+        acceptor.setFilterChainBuilder(chain);
+        // create some clients
+        NioSocketConnector connector = new NioSocketConnector();
+        connector.setHandler(new IoHandlerAdapter());
+        SocketAddress remoteAddressClients[] = new SocketAddress[2];
+        remoteAddressClients[0] = connectAndWrite(connector,0);
+        remoteAddressClients[1] = connectAndWrite(connector,1);
+        // wait until Iohandler has received all events
+        simpleIoHandler.messageSentLatch.await();
+        simpleIoHandler.sessionIdleLatch.await();
+        simpleIoHandler.sessionClosedLatch.await();
+        // make a copy to prevent ConcurrentModificationException
+        List<LoggingEvent> events = new ArrayList<LoggingEvent>(appender.events);
+        // verify that all logging events have correct MDC
+        for (LoggingEvent event : events) {
+            for (MdcInjectionFilter.MdcKey mdcKey : MdcInjectionFilter.MdcKey.values()) {
+              String key = mdcKey.name();
+              Object value = event.getMDC(key);
+              if (mdcKey == MdcInjectionFilter.MdcKey.remoteAddress) {
+                  assertNotNull(
+                      "MDC[remoteAddress] not set for [" + event.getMessage() + "]", value);
+              } else {
+                  assertNull("MDC[" + key + "] set for [" + event.getMessage() + "]", value);
+              }
+            }
+        }
     }
 
     private void test(DefaultIoFilterChainBuilder chain) throws IOException, InterruptedException {

Modified: mina/trunk/example/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/resources/log4j.properties?rev=587660&r1=587659&r2=587660&view=diff
==============================================================================
--- mina/trunk/example/src/main/resources/log4j.properties (original)
+++ mina/trunk/example/src/main/resources/log4j.properties Tue Oct 23 14:29:16 2007
@@ -7,4 +7,4 @@
 log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
 
 # you could use this pattern to test the MDC with the Chat server
-#log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %t %p %X{name} [%X{user}] [%X{remoteIp}:%X{remotePort}] [%c] - %m%n
\ No newline at end of file
+# log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %t %p %X{name} [%X{user}] [%X{remoteAddress}] [%c] - %m%n
\ No newline at end of file

Modified: mina/trunk/example/src/main/resources/org/apache/mina/example/chat/serverContext.xml
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/resources/org/apache/mina/example/chat/serverContext.xml?rev=587660&r1=587659&r2=587660&view=diff
==============================================================================
--- mina/trunk/example/src/main/resources/org/apache/mina/example/chat/serverContext.xml (original)
+++ mina/trunk/example/src/main/resources/org/apache/mina/example/chat/serverContext.xml Tue Oct 23 14:29:16 2007
@@ -40,7 +40,9 @@
     <property name="filters">
       <list>
         <bean class="org.apache.mina.filter.executor.ExecutorFilter"/>
-        <bean class="org.apache.mina.filter.logging.MdcInjectionFilter"/>
+        <bean class="org.apache.mina.filter.logging.MdcInjectionFilter">
+            <constructor-arg value="remoteAddress"/>
+        </bean>
         <bean class="org.apache.mina.filter.codec.ProtocolCodecFilter">
           <constructor-arg>
             <bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" />