logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ceki Gülcü <c...@qos.ch>
Subject Re: MDC in J2EE environment
Date Thu, 03 Apr 2003 15:29:32 GMT
Steven,

Your question is quite intriguing.

One solution would be to use some sort of counting. Thus, each time you set 
a key in the MDC you would increment the count of that key in the MDC by 
one. Each time you would "remove" the key you would decrement the count by 
one but not really remove (i.e. call MDC.remove). You would really remove 
only if the count reached zero (assuming the count started at 0). I think 
this provides for quite a solid solution.

Let me give you an example:

-- File XMDC.java ------------------------------------------
import org.apache.log4j.MDC;

public class XMDC {

   static Object get(String key) {
     return  MDC.get(key);
   }

   static void put(String key, Object o) {
     Object value = MDC.get(key);

     if(value == null) {
       ContextCounter cc = new ContextCounter(value);
       cc.incCount();
       MDC.put(key, cc);
     } else if(o instanceof ContextCounter) {
       ContextCounter cc = (ContextCounter) value;
       cc.incCount();
       cc.setContext(o);
     } else {
       MDC.put(key, o);
     }
   }

   static void remove(String key) {
     Object o = MDC.get(key);

     if(o == null) {
       ; // nothing to do because there is nothing there
     } else if(o instanceof ContextCounter) {
       ContextCounter cc = (ContextCounter) o;
       cc.decCount();
       if(cc.isCountZero()) {
         MDC.remove(key);
       }
     } else {
       MDC.remove(key);
     }
   }
}

-- File  ContextCounter.java ---------------------------------
public class ContextCounter {
   int count = 0;
   Object context;

   public ContextCounter(Object c) { context = c; }

   public void setContext(Object c) { context = c; }
   public Object getContext() { return context; }

   public boolean isCountZero() { return (count == 0); }
   public void incCount() { count++; }
   public void decCount() { count--; }
}

In your code you would use XMDC which would automatically track the 
reference count of the keys and values you entered into the MDC. Assuming 
each XMDC.put operation is matched by the corresponding XMDC.remove 
operation, you are guaranteed that "inner" put operations update the value 
of the key while inner remove operation are inoffensive, only the outer or 
topmost XMDC.remove will remove the key and its value from the MDC.

Think about it and let us know if it fits your purposes.

At 08:13 AM 4/3/2003 -0600, Ebersole, Steven wrote:
>There is certain information which is thread contextual which I would like
>to include into log4j's MDC to be available for logging.  One of these, for
>example, is the currently executing user.  My architecture is such that all
>requests come through a layer of stateless session EJBs.  Now these EJBs can
>make calls into other session EJBs in order to fulfill their use-case:
>
>public class SessionBeanA
>...
>{
>     ...
>     public void executeUseCase()
>     {
>         ... // Do some work
>         SessionBeanB sessionBeanB = ...; // Lookup SessionBeanB
>         sessionBeanB.executeSomeRelatedUseCase();
>         ... // Do some more work
>     }
>}
>
>public class SessionBeanB
>...
>{
>     ...
>     public void executeRelatedUseCase()
>     {
>         ... // Do something
>     }
>}
>
>The typical usage of MDC seems to be:
>1) put vars into MDC
>2) do your work
>3) clean up MDC
>
>But if I apply this usage to the scenario above, when
>SessionBeanB.executeRelatedUseCase() cleans up the MDC, the information
>would no longer be contained in the MDC for LoggingEvents generated within
>the "Do some more work" section of SessionBeanA.executeUseCase().
>
>I run weblogic 6.1, which unfortunately does not have support for "call
>interceptors" to know when a user context has been bound to a thread.
>Otherwise, I could simply setup MDC when a "session" is begun and clean up
>the MDC when the session ends.  The only way around this I have been able to
>think of is to just always call MDC.put( "USER",
>mySessionContext.getCallerPrincipal().getName() ) at the beginning of each
>and every session bean method.  But I would not ever be able to clean up the
>MDC because of this nesting described above.
>
>Is this OK?  Or this there a better way to do this?
>
>
>
>Steve Ebersole
>IT Integration Engineer
>Vignette Corporation
>Office: 512.741.4195
>Mobile: 512.297.5438
>
>Visit http://www.vignette.com
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: log4j-user-unsubscribe@jakarta.apache.org
>For additional commands, e-mail: log4j-user-help@jakarta.apache.org

--
Ceki 


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: log4j-user-help@jakarta.apache.org


Mime
View raw message