User: danch   
  Date: 01/04/03 21:49:52

  Added:       src/main/org/jboss/util CounterInterceptor.java
                        CounterService.java CounterServiceMBean.java
  Log:
  MBean and interceptor to allow statistics gathering on time spent in EJB methods
  
  Revision  Changes    Path
  1.1                  jboss/src/main/org/jboss/util/CounterInterceptor.java
  
  Index: CounterInterceptor.java
  ===================================================================
  package org.jboss.util;
  
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  import org.jboss.ejb.MethodInvocation;
  import org.jboss.ejb.Container;
  import org.jboss.ejb.plugins.*;
  import org.jboss.logging.Logger;
  import org.jboss.util.CounterService;
  
  /**
   * Interceptor that uses the CounterService MBean to record the length of time
   * spent in 'lower' interceptors (below it in the stack). 
   * <p><b>How to use:</b></p>
   * <p>First, the CounterService MBean must be installed in JBoss. To do this,
   * place the following in your JBoss.jcml file, near the very end.</p>
   * <code>
   * &lt;mbean code="org.jboss.util.CounterService" 
name="DefaultDomain:service=CounterService" &gt; &lt;/mbean&gt;
   * </code>
   * <p>This will start up and enable the centralized counter in your JBoss server
   * instance.
   * <p>Next, you need to configure this interceptor into the interceptor stacks
   * of any beans you wish to monitor. This can be done either globally for a 
   * container-config in standardjboss.xml, or on a per-bean basis in a jar's 
   * jboss.jcml. Just insert the following at the top of the 
&lt;container-interceptors&gt;
   * section. If you're overriding this for a bean in jboss.xml, you'll need to
   * override the entire container-interceptors section.</p>
   * <code>
   * &lt;interceptor&gt;org.jboss.util.CounterInterceptor&lt;/interceptor&gt;
   * </code>
   * <p>This can go anywhere in the container-interceptors section, but either
   * the top or the bottom will probably be best for gathering application 
   * statistics.
   * @author <a href="mailto:[EMAIL PROTECTED]">Dan Christopherson</href>
   */
  public class CounterInterceptor extends AbstractInterceptor {
  
     Container container = null;
     CounterService counter = null;
     boolean loggedNoCounter = false;
     StringBuffer baseCounterName = null;
     int baseNameLength = 0;
     
     public CounterInterceptor() {
     }
     public void setContainer(Container container) {
        baseCounterName = new StringBuffer(container.getBeanClass().getName());
        baseNameLength = baseCounterName.length();
        this.container = container;
     }
     public Container getContainer() {
        return container;
     }
     
     public Object invokeHome(MethodInvocation mi) throws Exception {
        long startTime=System.currentTimeMillis();
        try {
           return super.invokeHome(mi);
        } finally {
           if (getCounter() != null) {
              long endTime=System.currentTimeMillis();
              baseCounterName.append("Home.");
              baseCounterName.append(mi.getMethod().getName());
              counter.accumulate(baseCounterName.toString(), endTime-startTime);
              baseCounterName.setLength(baseNameLength);
           }
        }
     }
        
     public Object invoke(MethodInvocation mi) throws Exception {
        long startTime=System.currentTimeMillis();
        try {
           return super.invoke(mi);
        } finally {
           if (getCounter() != null) {
              long endTime=System.currentTimeMillis();
              baseCounterName.append('.');
              baseCounterName.append(mi.getMethod().getName());
              counter.accumulate(baseCounterName.toString(), endTime-startTime);
              baseCounterName.setLength(baseNameLength);
           }
        }
     }
     
     public void init() throws java.lang.Exception {
        //get a reference to the CounterService from JNDI
        Logger.debug("CounterInterceptor initializing");
     }
     
     private CounterService getCounter() {
        if (counter == null) {
           try {
              InitialContext ctx = new InitialContext();
              counter = (CounterService)ctx.lookup("java:/CounterService");
           } catch (NamingException ne) {
              if (!loggedNoCounter) {
                 Logger.warning("CounterInterceptor can't get counter service "+ne);
                 loggedNoCounter = true;
              }
           }
        }
        return counter;
     }
  }
  
  
  
  1.1                  jboss/src/main/org/jboss/util/CounterService.java
  
  Index: CounterService.java
  ===================================================================
  package org.jboss.util;
  
  import java.text.DecimalFormat;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Vector;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  import javax.naming.Reference;
  import javax.naming.StringRefAddr;
  import org.jboss.util.ServiceMBeanSupport;
  import org.jboss.logging.Log;
  import org.jboss.naming.NonSerializableFactory;
  
  /** A service offering accumulator style counters to help in diagnosing
   *  performance issues. 
   *  @author <a href="mailto:[EMAIL PROTECTED]">Dan Christopherson</href> 
   *  */
  public class CounterService 
     extends ServiceMBeanSupport
     implements CounterServiceMBean
  {
     private HashMap counterMap = new HashMap();
     
  
     
     /** accumulate a count into a named counter. will initialize the named
      *  counter if neccessary. */
     public void accumulate(String counterName, long add) {
        Counter counter = null;
        synchronized (counterMap) {
           counter = (Counter)counterMap.get(counterName);
           if (counter == null) {
              counter = new Counter(counterName);
              counterMap.put(counterName, counter);
           }
        }
        counter.addToCount(add);
     }
     
     protected void startService() throws java.lang.Exception {
        super.startService();
        
        InitialContext ctx = new InitialContext();
        
        //bind myself into JNDI, at java:/CounterService
                NonSerializableFactory.bind("java:/CounterService", this);
                StringRefAddr addr = new StringRefAddr("nns", "java:/CounterService");
                Reference ref = new Reference(this.getClass().getName(), addr, 
NonSerializableFactory.class.getName(), null);
                ctx.bind("java:/CounterService", ref);
     }
     protected void stopService() {
        super.stopService();
        try {
           InitialContext ctx = new InitialContext();
           ctx.unbind("java:/CounterService");
                        NonSerializableFactory.unbind("java:/CounterService");
        } catch (NamingException ne) {
           log.error("Coulnd't unbind CounterService: "+ne.getMessage());
        }
     }
     
     public String getName() {
        return "Counter Service";
     }
     
     public String list() {
        DecimalFormat format = new DecimalFormat("####0.0000");
        String retVal = "";
        Iterator keys = counterMap.keySet().iterator();
        while (keys.hasNext()) {
           String key = (String)keys.next();
           Counter counter = (Counter)counterMap.get(key);
           long total = 0;
           int entries = 0;
           synchronized (counter) {//so we dont catch half of it.
              total = counter.getCount();
              entries = counter.getEntries();
           }
           double avg = ((double)total)/((double)entries);
           String descrip = key+": total="+total+" on "+entries+"entries for "+
                            "an average of "+format.format(avg)+"<br>\n";
           retVal += descrip;
        }
        return retVal;
     }
     
     private static class Counter {
        private String name;
        private long count=0;
        private int entries=0;
        
        public Counter(String n) {
           name = n;
        }
        
        public String getName() {
           return name;
        }
        
        public synchronized long getCount() {
           return count;
        }
        
        public synchronized int getEntries() {
           return entries;
        }
        
        public synchronized void addToCount(long add) {
           count += add;
           entries++;
        }
     }
  }
  
  
  1.1                  jboss/src/main/org/jboss/util/CounterServiceMBean.java
  
  Index: CounterServiceMBean.java
  ===================================================================
  package org.jboss.util;
  
  import java.util.Vector;
  
  /** 
   * MBean interface for the CounterService.
   * @author <a href="mailto:[EMAIL PROTECTED]">Dan Christopherson</href>
   */
  public interface CounterServiceMBean 
     extends org.jboss.util.ServiceMBean
  {
     public String list();
  }
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to