mirror of https://github.com/apache/jmeter.git
Re-work Transaction Controller so original behaviour is the default
git-svn-id: https://svn.apache.org/repos/asf/jakarta/jmeter/branches/rel-2-2@554438 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0c86eada81
commit
9efb5971c6
|
|
@ -20,23 +20,76 @@ package org.apache.jmeter.control;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.jmeter.samplers.SampleEvent;
|
||||
import org.apache.jmeter.samplers.SampleListener;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.samplers.Sampler;
|
||||
import org.apache.jmeter.testelement.property.BooleanProperty;
|
||||
import org.apache.jmeter.threads.JMeterContext;
|
||||
import org.apache.jmeter.threads.JMeterThread;
|
||||
import org.apache.jmeter.threads.JMeterVariables;
|
||||
import org.apache.jmeter.threads.ListenerNotifier;
|
||||
import org.apache.jmeter.threads.SamplePackage;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
/**
|
||||
* Transaction Controller to measure transaction times
|
||||
*
|
||||
* There are two different modes for the controller:
|
||||
* - generate additional total sample after nested samples (as in JMeter 2.2)
|
||||
* - generate parent sampler containing the nested samples
|
||||
*
|
||||
*/
|
||||
public class TransactionController extends GenericController implements Controller, Serializable {
|
||||
public class TransactionController extends GenericController implements SampleListener, Controller, Serializable {
|
||||
private static final Logger log = LoggingManager.getLoggerForClass();
|
||||
|
||||
transient private TransactionSampler transactionSampler;
|
||||
|
||||
transient private ListenerNotifier lnf;
|
||||
|
||||
transient private SampleResult res;
|
||||
|
||||
transient private int calls;
|
||||
|
||||
transient private int noFailingSamples;
|
||||
|
||||
private static final String PARENT = "TransactionController.parent";// $NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Creates a Transaction Controller
|
||||
*/
|
||||
public TransactionController() {
|
||||
lnf = new ListenerNotifier();
|
||||
}
|
||||
|
||||
private Object readResolve(){
|
||||
lnf = new ListenerNotifier();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setParent(boolean _parent){
|
||||
setProperty(new BooleanProperty(PARENT, _parent));
|
||||
}
|
||||
|
||||
public boolean isParent(){
|
||||
return getPropertyAsBoolean(PARENT);
|
||||
}
|
||||
|
||||
public Sampler next(){
|
||||
if (isParent()){
|
||||
return next1();
|
||||
} else {
|
||||
return next2();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////// Transaction Controller - parent ////////////////
|
||||
|
||||
/**
|
||||
* @see org.apache.jmeter.control.Controller#next()
|
||||
*/
|
||||
public Sampler next() {
|
||||
public Sampler next1() {
|
||||
// Check if transaction is done
|
||||
if(transactionSampler != null && transactionSampler.isTransactionDone()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
|
|
@ -67,6 +120,9 @@ public class TransactionController extends GenericController implements Controll
|
|||
}
|
||||
|
||||
protected Sampler nextIsAController(Controller controller) throws NextIsNullException {
|
||||
if (!isParent()) {
|
||||
return super.nextIsAController(controller);
|
||||
}
|
||||
Sampler returnValue;
|
||||
Sampler sampler = controller.next();
|
||||
if (sampler == null) {
|
||||
|
|
@ -80,4 +136,74 @@ public class TransactionController extends GenericController implements Controll
|
|||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
////////////////////// Transaction Controller - additional sample //////////////////////////////
|
||||
|
||||
public Sampler next2() {
|
||||
if (isFirst()) // must be the start of the subtree
|
||||
{
|
||||
calls = 0;
|
||||
noFailingSamples = 0;
|
||||
res = new SampleResult();
|
||||
res.setSampleLabel(getName());
|
||||
// Assume success
|
||||
res.setSuccessful(true);
|
||||
res.sampleStart();
|
||||
}
|
||||
|
||||
Sampler returnValue = super.next();
|
||||
|
||||
if (returnValue == null) // Must be the end of the controller
|
||||
{
|
||||
if (res != null) {
|
||||
res.sampleEnd();
|
||||
res.setResponseMessage("Number of samples in transaction : " + calls + ", number of failing samples : " + noFailingSamples);
|
||||
if(res.isSuccessful()) {
|
||||
res.setResponseCodeOK();
|
||||
}
|
||||
|
||||
// TODO could these be done earlier (or just once?)
|
||||
JMeterContext threadContext = getThreadContext();
|
||||
JMeterVariables threadVars = threadContext.getVariables();
|
||||
|
||||
SamplePackage pack = (SamplePackage) threadVars.getObject(JMeterThread.PACKAGE_OBJECT);
|
||||
if (pack == null) {
|
||||
log.warn("Could not fetch SamplePackage");
|
||||
} else {
|
||||
SampleEvent event = new SampleEvent(res, getName());
|
||||
// We must set res to null now, before sending the event for the transaction,
|
||||
// so that we can ignore that event in our sampleOccured method
|
||||
res = null;
|
||||
lnf.notifyListeners(event, pack.getSampleListeners());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We have sampled one of our children
|
||||
calls++;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void sampleOccurred(SampleEvent se) {
|
||||
if (!isParent()) {
|
||||
// Check if we are still sampling our children
|
||||
if(res != null) {
|
||||
SampleResult sampleResult = se.getResult();
|
||||
res.setThreadName(sampleResult.getThreadName());
|
||||
res.setBytes(res.getBytes() + sampleResult.getBytes());
|
||||
if(!sampleResult.isSuccessful()) {
|
||||
res.setSuccessful(false);
|
||||
noFailingSamples++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sampleStarted(SampleEvent e) {
|
||||
}
|
||||
|
||||
public void sampleStopped(SampleEvent e) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,16 +18,21 @@
|
|||
|
||||
package org.apache.jmeter.control.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import org.apache.jmeter.control.TransactionController;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.gui.layout.VerticalLayout;
|
||||
|
||||
/**
|
||||
* A Transaction controller component.
|
||||
*
|
||||
*/
|
||||
public class TransactionControllerGui extends AbstractControllerGui {
|
||||
|
||||
private JCheckBox parent; // If selected, then generate parent sample, otherwise as per original controller
|
||||
|
||||
/**
|
||||
* Create a new TransactionControllerGui instance.
|
||||
*/
|
||||
|
|
@ -42,9 +47,15 @@ public class TransactionControllerGui extends AbstractControllerGui {
|
|||
return lc;
|
||||
}
|
||||
|
||||
public void configure(TestElement el) {
|
||||
super.configure(el);
|
||||
parent.setSelected(((TransactionController) el).isParent());
|
||||
}
|
||||
|
||||
/* Implements JMeterGUIComponent.modifyTestElement(TestElement) */
|
||||
public void modifyTestElement(TestElement el) {
|
||||
configureTestElement(el);
|
||||
((TransactionController) el).setParent(parent.isSelected());
|
||||
}
|
||||
|
||||
public String getLabelResource() {
|
||||
|
|
@ -55,8 +66,10 @@ public class TransactionControllerGui extends AbstractControllerGui {
|
|||
* Initialize the GUI components and layout for this component.
|
||||
*/
|
||||
private void init() {
|
||||
setLayout(new BorderLayout());
|
||||
setLayout(new VerticalLayout(5, VerticalLayout.BOTH, VerticalLayout.TOP));
|
||||
setBorder(makeBorder());
|
||||
add(makeTitlePanel(), BorderLayout.NORTH);
|
||||
add(makeTitlePanel());
|
||||
parent = new JCheckBox(JMeterUtils.getResString("transaction_controller_parent")); // $NON-NLS-1$
|
||||
add(parent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -743,6 +743,7 @@ throughput_control_title=Throughput Controller
|
|||
throughput_control_tplabel=Throughput
|
||||
time_format=Format string for SimpleDateFormat (optional)
|
||||
timelim=Time limit
|
||||
transaction_controller_parent=Generate parent sample
|
||||
transaction_controller_title=Transaction Controller
|
||||
unbind=Thread Unbind
|
||||
uniform_timer_delay=Constant Delay Offset (in milliseconds)\:
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Some of the main enhancements are:
|
|||
<li>__V() function allows support of nested variable references</li>
|
||||
<li>LDAP Ext sampler optionally parses result sets and supports secure mode</li>
|
||||
<li>FTP Sampler supports Ascii/Binary mode and upload</li>
|
||||
<li>Transaction Controller now generates Sample with subresults</li>
|
||||
<li>Transaction Controller now optionally generates a Sample with subresults</li>
|
||||
<li>HTTPS session contexts are now per-thread, rather than shared. This gives better emulation of multiple users</li>
|
||||
<li>BeanShell elements now support ThreadListener and TestListener interfaces</li>
|
||||
<li>Coloured icons in Tree View Listener and elsewhere to better differentiate failed samples.</li>
|
||||
|
|
@ -58,6 +58,9 @@ The main bug fixes are:
|
|||
<li>Test elements no longer default to previous contents; test elements no longer cleared when changing language.</li>
|
||||
</ul>
|
||||
<h4>Known problems:</h4>
|
||||
<p>Transaction Controller parent mode does not support nested Transaction Controllers.
|
||||
Doing so may cause a Null Pointer Exception in TestCompiler.
|
||||
</p>
|
||||
<p>Thread active counts are always zero in CSV and XML files when running remote tests.
|
||||
</p>
|
||||
<p>The property file_format.testlog=2.1 is treated the same as 2.2.
|
||||
|
|
@ -93,7 +96,6 @@ The HTTP Authorisation Manager now has extra columns for domain and realm,
|
|||
so the temporary work-round of using '\' and '@' in the username to delimit the domain and realm
|
||||
has been removed.
|
||||
</p>
|
||||
<p>The Transaction Controller no longer appears as a separate sample; it now includes its nested samples as subsamples</p>
|
||||
<p>
|
||||
Control-Z no longer used for Remote Start All - this now uses Control+Shift+R
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -1476,31 +1476,41 @@ the contents are used to prefix the pathname.
|
|||
|
||||
<component name="Transaction Controller" index="§-num;.2.15" width="358" height="131" screenshot="transactioncontroller.png">
|
||||
<description>
|
||||
<p>The Transaction Controller times how long it takes for all its children to run.
|
||||
It then adds a "sample" entry to the test output with the total elapsed time.
|
||||
The name of the element is used to name the "sample".
|
||||
</p>
|
||||
<p>
|
||||
The Transaction Comntroller is used to group samplers by generating an additional
|
||||
sample which totals the nested samples.
|
||||
For JMeter versions after 2.3, there are two modes of operation
|
||||
<ul>
|
||||
<li>additional sample is added after the nested samples</li>
|
||||
<li>additional sample is added as a parent of the nested samples</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
The generated sample time includes all the times for the nested samplers, and any timers etc.
|
||||
Depending on the clock resolution, it may be slightly longer than the sum of the individual samplers plus timers.
|
||||
The clock might tick after the controller recorded the start time but before the first sample starts.
|
||||
Similarly at the end.
|
||||
</p>
|
||||
<p>For JMeter versions after 2.2, the controlled samples no longer appear as separate samples, but as subsamples.
|
||||
Also the Transaction Sample is only regarded as successful if all its sub-samples are successful.
|
||||
This is similar to the way the HTTP Samplers work when retrieving embedded objects (images etc).
|
||||
The individual samples can still be seen in the Tree View Listener,
|
||||
<p>The generated sample is only regarded as successful if all its sub-samples are successful.</p>
|
||||
<p>
|
||||
In parent mode, the individual samples can still be seen in the Tree View Listener,
|
||||
but no longer appear as separate entries in other Listeners.
|
||||
Also, the sub-samples do not appear in CSV log files, but they can be saved to XML files.
|
||||
</p>
|
||||
<note>
|
||||
Assertions (etc) can be added to the Transaction Controller.
|
||||
In parent mode, Assertions (etc) can be added to the Transaction Controller.
|
||||
However by default they will be applied to both the individual samples and the overall transaction sample.
|
||||
To limit the scope of the Assertions, use a Simple Controller to contain the samples, and add the Assertions
|
||||
to the Simple Controller.
|
||||
Parent mode controllers do not currently properly support nested transaction controllers of either type.
|
||||
</note>
|
||||
</description>
|
||||
<properties>
|
||||
<property name="Name" required="Yes">Descriptive name for this controller that is shown in the tree, and used to name the transaction.</property>
|
||||
<property name="Generate Parent Sample" required="Yes">
|
||||
If checked, then the sample is generated as a parent of the other samples,
|
||||
otherwise the sample is generated as an independent sample.
|
||||
</property>
|
||||
</properties>
|
||||
</component>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue