sebb        2003/11/02 16:39:19

  Added:       src/core/org/apache/jmeter/reporters Summariser.java
               src/core/org/apache/jmeter/reporters/gui SummariserGui.java
  Log:
  New Summariser test element (mainly for use with non-GUI runs)
  
  Revision  Changes    Path
  1.1                  
jakarta-jmeter/src/core/org/apache/jmeter/reporters/Summariser.java
  
  Index: Summariser.java
  ===================================================================
  package org.apache.jmeter.reporters;
  
  import java.io.Serializable;
  import java.text.ChoiceFormat;
  import java.text.DecimalFormat;
  import java.text.MessageFormat;
  import java.util.Hashtable;
  
  import org.apache.jmeter.engine.event.LoopIterationEvent;
  import org.apache.jmeter.samplers.Clearable;
  import org.apache.jmeter.samplers.SampleEvent;
  import org.apache.jmeter.samplers.SampleListener;
  import org.apache.jmeter.samplers.SampleResult;
  import org.apache.jmeter.testelement.AbstractTestElement;
  import org.apache.jmeter.testelement.TestListener;
  import org.apache.jmeter.util.JMeterUtils;
  import org.apache.jmeter.visualizers.RunningSample;
  import org.apache.jorphan.logging.LoggingManager;
  import org.apache.jorphan.util.JOrphanUtils;
  import org.apache.log.Logger;
  
  /**
   * Generate a summary of the test run so far to the log file and/or 
   * standard output. Both running and differential totals are shown.
   * Output is generated every n seconds (default 3 minutes) on the appropriate
   * time boundary, so that multiple test runs on the same time will be
   * synchronised.
   * 
   * This is mainly intended for batch (non-GUI) runs
   * 
   * @author sebb AT apache DOT org
   * @version $Revision: 1.1 $ Last updated: $Date: 2003/11/03 00:39:19 $
   */
  public class Summariser
      extends AbstractTestElement
      implements Serializable,
      SampleListener,
      TestListener,
      Clearable
  {
      private static final Logger log = LoggingManager.getLoggerForClass();
      
        /** interval between summaries (in seconds) default 3 minutes*/
        private static final long INTERVAL = 
                JMeterUtils.getPropDefault("summariser.interval",3*60); //$NON-NLS-1$
  
        /** Write messages to log file ?*/
        private static final boolean TOLOG = 
                JMeterUtils.getPropDefault("summariser.log",true); //$NON-NLS-1$
  
        /** Write messages to System.out ?*/
        private static final boolean TOOUT = 
                JMeterUtils.getPropDefault("summariser.out",true); //$NON-NLS-1$
  
      /**
       * Summariser elements are cloned for each thread in each group;
       * this Map is used to allow them to share the same statistics.
       * The key is the Summariser name, so all Summarisers with the same name
       * will use the same accumulators.
       */
      private static Hashtable accumulators = new Hashtable(); 
  
      /*
       * Constructor is initially called once for each occurrence in the test plan
       * For GUI, several more instances are created
       * Then clear is called at start of test
       * Called several times during test startup
       * The name will not necessarily have been set at this point.
       */
        public Summariser(){
                super();
                //log.debug(Thread.currentThread().getName());
                //System.out.println(">> "+me+"        "+this.getName()+" 
"+Thread.currentThread().getName());          
        }
  
      /*
       * This is called once for each occurrence in the test plan, before the start of 
the test.
       * The super.clear() method clears the name (and all other properties),
       * so it is called last.
       */
        public void clear()
        {
                //System.out.println("-- "+me+this.getName()+" 
"+Thread.currentThread().getName());
  
                myName = this.getName();
  
          // Hashtable is synchronised, but there could be more than one Summariser
          // with the same name, so we need to synch.
          synchronized(accumulators){
                        Totals tots = (Totals) accumulators.get(myName);
                        if (tots != null){// This can be null (before first sample)
                                tots.clear();
                        } else {
                                //System.out.println("Creating totals for "+myName);
                                tots = new Totals();
                                accumulators.put(myName,tots);
                        }
          }
  
                super.clear();
        }
        
        /**
         * Contains the items needed to collect stats for a summariser
         * 
         * @author sebb AT apache DOT org
         * @version $revision$ Last updated: $date$
         */
        private static class Totals{
  
                /** Time of last summary (to prevent double reporting) */
                private long last = 0;// set to -1 by TestEnded to prevent double 
reporting
  
                private RunningSample delta = new RunningSample("DELTA",0);
                private RunningSample total = new RunningSample("TOTAL",0);
  
          private void clear(){
                delta.clear();
                total.clear();
                last = 0;
          }
          
          /**
           * Add the delta values to the total values and clear the delta
           */
          private synchronized void moveDelta(){
                total.addSample(delta);
                delta.clear();
          }
        }
        
        /**
         * Cached copy of Totals for this instance
         * These do not need to be synchronised, as they are not shared
         * between threads
         */
        private Totals myTotals = null;
        private String myName;
  
  
      /**
       * Ensure that a report is not skipped if we are slightly late in checking
       * the time.
       */
        private static final int INTERVAL_WINDOW = 5; // in seconds
  
        /**
         * Accumulates the sample in two SampleResult objects
         * - one for running totals, and the other for deltas
         * 
         * @see 
org.apache.jmeter.samplers.SampleListener#sampleOccurred(org.apache.jmeter.samplers.SampleEvent)
         */
        public void sampleOccurred(SampleEvent e) {
                SampleResult s = e.getResult();
  
                //System.out.println("SO "+me+this.getName()+" 
"+Thread.currentThread().getName()
                //+" "+s.getSampleLabel());
  
                if (myName == null) myName = getName();
  
                if (myTotals == null) myTotals = (Totals) accumulators.get(myName);
  
          if (s != null)
          {
                        myTotals.delta.addSample(s);
          }
  
          long now = System.currentTimeMillis()/1000;// in seconds
          
                 RunningSample myDelta=null;
           RunningSample myTotal=null;
                 boolean reportNow = false;
  
                /* Have we reached the reporting boundary?
                 * Need to allow for a margin of error, otherwise can miss the slot
                 * Also need to check we've not hit the window already
                 */
                 synchronized(myTotals){
                        if ((now > myTotals.last + INTERVAL_WINDOW) && (now % INTERVAL 
<= INTERVAL_WINDOW))
              {
                reportNow=true;
                                myDelta = new RunningSample(myTotals.delta);// copy 
the data to minimise ...
                                myTotals.moveDelta();
                                myTotal = new RunningSample(myTotals.total);// ... the 
synch time
                                myTotals.last = now;
                        }
          }
          if (reportNow){
                        String str;
                        str = format(myDelta,"+");
                        if (TOLOG) log.info(str);
                        if (TOOUT) System.out.println(str);
        
                        if (myTotal.getNumSamples() != myDelta.getNumSamples()) {// 
Only if we have updated them
                                str = format(myTotal,"=");
                                if (TOLOG) log.info(str);
                                if (TOOUT) System.out.println(str);
                }
                }
      }
  
        private static StringBuffer longToSb(StringBuffer sb,long l, int len){
                sb.setLength(0);
                sb.append(l);
                return JOrphanUtils.rightAlign(sb,len);
        }
        
        private static DecimalFormat dfDouble = new DecimalFormat("#0.0");
        private static StringBuffer doubleToSb(StringBuffer sb,double d, int len, int 
frac){
                sb.setLength(0);
                dfDouble.setMinimumFractionDigits(frac);
                dfDouble.setMaximumFractionDigits(frac);
                sb.append(dfDouble.format(d));
                return JOrphanUtils.rightAlign(sb,len);
        }
      /**
       * @param myTotal
       * @param string
       * @return
       */
      private String format(RunningSample s, String type)
      {
        StringBuffer tmp = new StringBuffer(20); // for intermediate use
          StringBuffer sb = new StringBuffer(100); // output line buffer
          sb.append(myName);
          sb.append(" ");
          sb.append(type);
                sb.append(" ");
          sb.append(longToSb(tmp,s.getNumSamples(),5));
          sb.append(" in ");
                sb.append(longToSb(tmp,s.getElapsed()/1000,5));
                sb.append("s = ");
                sb.append(doubleToSb(tmp,s.getRate(),6,1));
                sb.append("/s Avg: ");
                sb.append(longToSb(tmp,s.getAverage(),5));
                sb.append(" Min: ");
                sb.append(longToSb(tmp,s.getMin(),5));
                sb.append(" Max: ");
                sb.append(longToSb(tmp,s.getMax(),5));
                sb.append(" Err: ");
                sb.append(longToSb(tmp,s.getErrorCount(),5));
                sb.append(" (");
                sb.append(doubleToSb(tmp,s.getErrorPercentage(),3,1));
                sb.append("%)");
          return sb.toString();
      }
  
  
        /* (non-Javadoc)
         * @see 
org.apache.jmeter.samplers.SampleListener#sampleStarted(org.apache.jmeter.samplers.SampleEvent)
         */
        public void sampleStarted(SampleEvent e) 
        {
                // not used
        }
  
        /* (non-Javadoc)
         * @see 
org.apache.jmeter.samplers.SampleListener#sampleStopped(org.apache.jmeter.samplers.SampleEvent)
         */
        public void sampleStopped(SampleEvent e) {
                // not used
        }
  
      /* (non-Javadoc)
       * @see org.apache.jmeter.testelement.TestListener#testStarted()
       */
      public void testStarted()
      {
          // not used
      }
      /* (non-Javadoc)
       * @see org.apache.jmeter.testelement.TestListener#testEnded()
       */
      public void testEnded()
      {
          testEnded("local");
          
      }
      /* (non-Javadoc)
       * @see org.apache.jmeter.testelement.TestListener#testStarted(java.lang.String)
       */
      public void testStarted(String host)
      {
       // not used   
      }
      /* (non-Javadoc)
       * Can be called more than once with the same name, so need to synch.
       * However, there is no need to create copies, to shorten the synch zone,
       * as timing is not critical at the end of the test.
       * 
       * @see org.apache.jmeter.testelement.TestListener#testEnded(java.lang.String)
       */
      public void testEnded(String host)
      {
                //System.out.println("TE "+me+this.getName()+" 
"+Thread.currentThread().getName());
                synchronized(accumulators){
                        Totals t = (Totals) accumulators.get(myName);
                        if (t.last != -1){
                                String str;
                                if (t.total.getNumSamples() != 0){//Only print delta 
if different from total
                                        str = format(t.delta,"+");
                                        if (TOLOG) log.info(str);
                                        if (TOOUT) System.out.println(str);
                                }
                                t.moveDelta();
                                str = format(t.total,"=");
                                if (TOLOG) log.info(str);
                                if (TOOUT) System.out.println(str);
                                t.last = -1;
                        }
                }
      }
      /* (non-Javadoc)
       * @see 
org.apache.jmeter.testelement.TestListener#testIterationStart(org.apache.jmeter.engine.event.LoopIterationEvent)
       */
      public void testIterationStart(LoopIterationEvent event)
      {
                // not used
      }
  
  }
  
  
  
  1.1                  
jakarta-jmeter/src/core/org/apache/jmeter/reporters/gui/SummariserGui.java
  
  Index: SummariserGui.java
  ===================================================================
  package org.apache.jmeter.reporters.gui;
  
  import java.awt.BorderLayout;
  
  import org.apache.jmeter.reporters.Summariser;
  import org.apache.jmeter.processor.gui.AbstractPostProcessorGui;
  import org.apache.jmeter.testelement.TestElement;
  import org.apache.jmeter.util.JMeterUtils;
  
  /**
   * Create a summariser test element.
   * 
   * Note:
   * This is not really a PostProcessor, but that seems to be the closest
   * of the existing types.
   * 
   * @author sebb AT apache DOT org
   * @version $Revision: 1.1 $ Last updated: $date$
   */
  public class SummariserGui extends AbstractPostProcessorGui
  {
     
      public SummariserGui()
      {
          super();
          init();
      }
  
      /**
       * @see org.apache.jmeter.gui.JMeterGUIComponent#getStaticLabel()
       */
      public String getStaticLabel()
      {
          return JMeterUtils.getResString("summariser_title");
      }
      
      public void configure(TestElement el)
      {
          super.configure(el);
      }
  
      /**
       * @see org.apache.jmeter.gui.JMeterGUIComponent#createTestElement()
       */
      public TestElement createTestElement()
      {
          Summariser summariser = new Summariser();
          modifyTestElement(summariser);
          return summariser;
      }
  
      /**
       * Modifies a given TestElement to mirror the data in the gui components.
       * @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(TestElement)
       */
      public void modifyTestElement(TestElement summariser)
      {
          super.configureTestElement(summariser);
      }
      
      private void init()
      {
          setLayout(new BorderLayout());
          setBorder(makeBorder());
          
          add(makeTitlePanel(),BorderLayout.NORTH);
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to