You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2003/11/03 01:39:19 UTC
cvs commit: jakarta-jmeter/src/core/org/apache/jmeter/reporters/gui SummariserGui.java
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: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org