[Bug 62195] Save Responses to a file : Improve component and UI

Contributed by UbikLoadPack
Bugzilla Id: 62195

git-svn-id: https://svn.apache.org/repos/asf/jmeter/trunk@1827348 13f79535-47bb-0310-9956-ffa450edef68

Former-commit-id: aac159779d
This commit is contained in:
Philippe Mouawad 2018-03-20 19:23:19 +00:00
parent 85aa886e0e
commit 12190d932a
6 changed files with 227 additions and 88 deletions

View File

@ -28,6 +28,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import org.apache.jmeter.control.TransactionController;
import org.apache.jmeter.engine.util.NoThreadClone; import org.apache.jmeter.engine.util.NoThreadClone;
import org.apache.jmeter.samplers.SampleEvent; import org.apache.jmeter.samplers.SampleEvent;
import org.apache.jmeter.samplers.SampleListener; import org.apache.jmeter.samplers.SampleListener;
@ -36,6 +37,7 @@ import org.apache.jmeter.services.FileServer;
import org.apache.jmeter.testelement.AbstractTestElement; import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestStateListener; import org.apache.jmeter.testelement.TestStateListener;
import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jorphan.util.JMeterStopTestNowException;
import org.apache.jorphan.util.JOrphanUtils; import org.apache.jorphan.util.JOrphanUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -73,6 +75,8 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
public static final String ADD_TIMESTAMP = "FileSaver.addTimstamp"; // $NON-NLS-1$ public static final String ADD_TIMESTAMP = "FileSaver.addTimstamp"; // $NON-NLS-1$
public static final String NUMBER_PAD_LENGTH = "FileSaver.numberPadLen"; // $NON-NLS-1$ public static final String NUMBER_PAD_LENGTH = "FileSaver.numberPadLen"; // $NON-NLS-1$
public static final String IGNORE_TC = "FileSaver.ignoreTC"; // $NON-NLS-1$
//- JMX property names //- JMX property names
@ -150,7 +154,7 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
*/ */
@Override @Override
public void sampleOccurred(SampleEvent e) { public void sampleOccurred(SampleEvent e) {
processSample(e.getResult(), new Counter()); processSample(e.getResult(), new Counter());
} }
/** /**
@ -172,15 +176,11 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
* @param num number to append to variable (if >0) * @param num number to append to variable (if >0)
*/ */
private void saveSample(SampleResult s, int num) { private void saveSample(SampleResult s, int num) {
// Should we save the sample? if(ignoreSampler(s)) {
if (s.isSuccessful()){ if (log.isDebugEnabled()) {
if (getErrorsOnly()){ log.debug("Ignoring SampleResult from Sampler {}", s.getSampleLabel());
return;
}
} else {
if (getSuccessOnly()){
return;
} }
return;
} }
String fileName = makeFileName(s.getContentType(), getSkipAutoNumber(), getSkipSuffix()); String fileName = makeFileName(s.getContentType(), getSkipAutoNumber(), getSkipSuffix());
@ -198,6 +198,7 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
JMeterContextService.getContext().getVariables().put(variable, fileName); JMeterContextService.getContext().getVariables().put(variable, fileName);
} }
File out = new File(fileName); File out = new File(fileName);
createFoldersIfNeeded(out.getParentFile());
try (FileOutputStream fos = new FileOutputStream(out); try (FileOutputStream fos = new FileOutputStream(out);
BufferedOutputStream bos = new BufferedOutputStream(fos)){ BufferedOutputStream bos = new BufferedOutputStream(fos)){
JOrphanUtils.write(s.getResponseData(), bos); // chunk the output if necessary JOrphanUtils.write(s.getResponseData(), bos); // chunk the output if necessary
@ -208,6 +209,34 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
} }
} }
/**
* @param s {@link SamplerResult}
* @return true if we should ignore SampleResult
*/
private boolean ignoreSampler(SampleResult s) {
if(getIgnoreTC() && TransactionController.isFromTransactionController(s)) {
return true;
}
// Should we save the sample?
return ((s.isSuccessful() && getErrorsOnly()) ||
(!s.isSuccessful() && getSuccessOnly()));
}
/**
* Create path hierarchy to parentFile
* @param parentFile
*/
private void createFoldersIfNeeded(File parentFile) {
if (!parentFile.exists()) {
log.debug("Creating path hierarchy for folder {}", parentFile.getAbsolutePath());
if(!parentFile.mkdirs()) {
throw new JMeterStopTestNowException("Cannot create path hierarchy for folder "+ parentFile.getAbsolutePath());
}
} else {
log.debug("Folder {} already exists", parentFile.getAbsolutePath());
}
}
/** /**
* @param contentType Content type * @param contentType Content type
* @param skipAutoNumber Skip auto number * @param skipAutoNumber Skip auto number
@ -263,37 +292,49 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
// not used // not used
} }
private String getFilename() { public String getFilename() {
return getPropertyAsString(FILENAME); return getPropertyAsString(FILENAME);
} }
private String getVariableName() { public String getVariableName() {
return getPropertyAsString(VARIABLE_NAME,""); // $NON-NLS-1$ return getPropertyAsString(VARIABLE_NAME,""); // $NON-NLS-1$
} }
private boolean getErrorsOnly() { public boolean getErrorsOnly() {
return getPropertyAsBoolean(ERRORS_ONLY); return getPropertyAsBoolean(ERRORS_ONLY);
} }
private boolean getSkipAutoNumber() { public boolean getSkipAutoNumber() {
return getPropertyAsBoolean(SKIP_AUTO_NUMBER); return getPropertyAsBoolean(SKIP_AUTO_NUMBER);
} }
private boolean getSkipSuffix() { public boolean getSkipSuffix() {
return getPropertyAsBoolean(SKIP_SUFFIX); return getPropertyAsBoolean(SKIP_SUFFIX);
} }
private boolean getSuccessOnly() { public boolean getSuccessOnly() {
return getPropertyAsBoolean(SUCCESS_ONLY); return getPropertyAsBoolean(SUCCESS_ONLY);
} }
private boolean getAddTimeStamp() { public boolean getAddTimeStamp() {
return getPropertyAsBoolean(ADD_TIMESTAMP); return getPropertyAsBoolean(ADD_TIMESTAMP);
} }
private int getNumberPadLen() { public int getNumberPadLen() {
return getPropertyAsInt(NUMBER_PAD_LENGTH, 0); return getPropertyAsInt(NUMBER_PAD_LENGTH, 0);
} }
public boolean getIgnoreTC() {
return getPropertyAsBoolean(IGNORE_TC, true);
}
public void setIgnoreTC(boolean value) {
setProperty(IGNORE_TC, value, true);
}
public void setFilename(String value) {
setProperty(FILENAME, value);
}
// Mutable int to keep track of sample count // Mutable int to keep track of sample count
private static class Counter{ private static class Counter{
@ -315,4 +356,32 @@ public class ResultSaver extends AbstractTestElement implements NoThreadClone, S
public boolean equals(Object obj) { public boolean equals(Object obj) {
return super.equals(obj); return super.equals(obj);
} }
public void setAddTimestamp(boolean selected) {
setProperty(ADD_TIMESTAMP, selected, false);
}
public void setVariableName(String value) {
setProperty(VARIABLE_NAME, value,""); //$NON-NLS-1$
}
public void setNumberPadLength(String text) {
setProperty(ResultSaver.NUMBER_PAD_LENGTH, text,""); //$NON-NLS-1$
}
public void setErrorsOnly(boolean selected) {
setProperty(ResultSaver.ERRORS_ONLY, selected);
}
public void setSuccessOnly(boolean selected) {
setProperty(ResultSaver.SUCCESS_ONLY, selected);
}
public void setSkipSuffix(boolean selected) {
setProperty(ResultSaver.SKIP_SUFFIX, selected);
}
public void setSkipAutoNumber(boolean selected) {
setProperty(ResultSaver.SKIP_AUTO_NUMBER, selected);
}
} }

View File

@ -19,16 +19,19 @@
package org.apache.jmeter.reporters.gui; package org.apache.jmeter.reporters.gui;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box; import javax.swing.Box;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel; import javax.swing.JComponent;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextField;
import org.apache.jmeter.reporters.ResultSaver; import org.apache.jmeter.reporters.ResultSaver;
import org.apache.jmeter.samplers.Clearable; import org.apache.jmeter.samplers.Clearable;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.visualizers.gui.AbstractListenerGui; import org.apache.jmeter.visualizers.gui.AbstractListenerGui;
@ -39,26 +42,28 @@ import org.apache.jorphan.gui.JLabeledTextField;
* of files * of files
* *
*/ */
public class ResultSaverGui extends AbstractListenerGui implements Clearable { public class ResultSaverGui extends AbstractListenerGui implements Clearable { // NOSONAR Ignore inheritance rule
private static final long serialVersionUID = 240L; private static final long serialVersionUID = 241L;
private JTextField filename; private JLabeledTextField filename;
private JTextField variableName; private JLabeledTextField variableName;
private JLabeledTextField numberPadLength;
private JCheckBox errorsOnly; private JCheckBox errorsOnly;
private JCheckBox successOnly; private JCheckBox successOnly;
private JCheckBox ignoreTC;
private JCheckBox skipAutoNumber; private JCheckBox skipAutoNumber;
private JCheckBox skipSuffix; private JCheckBox skipSuffix;
private JCheckBox addTimestamp; private JCheckBox addTimestamp;
private JLabeledTextField numberPadLength;
public ResultSaverGui() { public ResultSaverGui() {
super(); super();
init(); init();
@ -78,14 +83,17 @@ public class ResultSaverGui extends AbstractListenerGui implements Clearable {
@Override @Override
public void configure(TestElement el) { public void configure(TestElement el) {
super.configure(el); super.configure(el);
filename.setText(el.getPropertyAsString(ResultSaver.FILENAME)); ResultSaver resultSaver = (ResultSaver) el;
errorsOnly.setSelected(el.getPropertyAsBoolean(ResultSaver.ERRORS_ONLY)); filename.setText(resultSaver.getFilename());
successOnly.setSelected(el.getPropertyAsBoolean(ResultSaver.SUCCESS_ONLY)); errorsOnly.setSelected(resultSaver.getErrorsOnly());
skipAutoNumber.setSelected(el.getPropertyAsBoolean(ResultSaver.SKIP_AUTO_NUMBER)); successOnly.setSelected(resultSaver.getSuccessOnly());
skipSuffix.setSelected(el.getPropertyAsBoolean(ResultSaver.SKIP_SUFFIX)); ignoreTC.setSelected(resultSaver.getIgnoreTC());
variableName.setText(el.getPropertyAsString(ResultSaver.VARIABLE_NAME,"")); skipAutoNumber.setSelected(resultSaver.getSkipAutoNumber());
addTimestamp.setSelected(el.getPropertyAsBoolean(ResultSaver.ADD_TIMESTAMP)); skipSuffix.setSelected(resultSaver.getSkipSuffix());
numberPadLength.setText(el.getPropertyAsString(ResultSaver.NUMBER_PAD_LENGTH,"")); variableName.setText(resultSaver.getVariableName());
addTimestamp.setSelected(resultSaver.getAddTimeStamp());
numberPadLength.setText(resultSaver.getNumberPadLen() == 0 ?
"" : Integer.toString(resultSaver.getNumberPadLen()));
} }
/** /**
@ -106,15 +114,16 @@ public class ResultSaverGui extends AbstractListenerGui implements Clearable {
@Override @Override
public void modifyTestElement(TestElement te) { public void modifyTestElement(TestElement te) {
super.configureTestElement(te); super.configureTestElement(te);
te.setProperty(ResultSaver.FILENAME, filename.getText()); ResultSaver resultSaver = (ResultSaver) te;
te.setProperty(ResultSaver.ERRORS_ONLY, errorsOnly.isSelected()); resultSaver.setFilename(filename.getText());
te.setProperty(ResultSaver.SKIP_AUTO_NUMBER, skipAutoNumber.isSelected()); resultSaver.setErrorsOnly(errorsOnly.isSelected());
te.setProperty(ResultSaver.SKIP_SUFFIX, skipSuffix.isSelected()); resultSaver.setSuccessOnly(successOnly.isSelected());
te.setProperty(ResultSaver.SUCCESS_ONLY, successOnly.isSelected()); resultSaver.setSkipSuffix(skipSuffix.isSelected());
te.setProperty(ResultSaver.ADD_TIMESTAMP, addTimestamp.isSelected(), false); resultSaver.setSkipAutoNumber(skipAutoNumber.isSelected());
AbstractTestElement at = (AbstractTestElement) te; resultSaver.setIgnoreTC(ignoreTC.isSelected());
at.setProperty(ResultSaver.VARIABLE_NAME, variableName.getText(),""); //$NON-NLS-1$ resultSaver.setAddTimestamp(addTimestamp.isSelected());
at.setProperty(ResultSaver.NUMBER_PAD_LENGTH, numberPadLength.getText(),""); //$NON-NLS-1$ resultSaver.setVariableName(variableName.getText());
resultSaver.setNumberPadLength(numberPadLength.getText());
} }
/** /**
@ -129,6 +138,7 @@ public class ResultSaverGui extends AbstractListenerGui implements Clearable {
filename.setText(""); //$NON-NLS-1$ filename.setText(""); //$NON-NLS-1$
errorsOnly.setSelected(false); errorsOnly.setSelected(false);
successOnly.setSelected(false); successOnly.setSelected(false);
ignoreTC.setSelected(true);
addTimestamp.setSelected(false); addTimestamp.setSelected(false);
variableName.setText(""); //$NON-NLS-1$ variableName.setText(""); //$NON-NLS-1$
numberPadLength.setText(""); //$NON-NLS-1$ numberPadLength.setText(""); //$NON-NLS-1$
@ -137,57 +147,107 @@ public class ResultSaverGui extends AbstractListenerGui implements Clearable {
private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final) private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
setLayout(new BorderLayout()); setLayout(new BorderLayout());
setBorder(makeBorder()); setBorder(makeBorder());
Box box = Box.createVerticalBox(); Box box = Box.createVerticalBox();
box.add(makeTitlePanel()); box.add(makeTitlePanel());
box.add(createFilenamePrefixPanel()); box.add(createSaveConditionsPanel());
box.add(createVariableNamePanel()); box.add(createSaveFormatPanel());
errorsOnly = new JCheckBox(JMeterUtils.getResString("resultsaver_errors")); // $NON-NLS-1$
box.add(errorsOnly);
successOnly = new JCheckBox(JMeterUtils.getResString("resultsaver_success")); // $NON-NLS-1$
box.add(successOnly);
skipAutoNumber = new JCheckBox(JMeterUtils.getResString("resultsaver_skipautonumber")); // $NON-NLS-1$
box.add(skipAutoNumber);
skipSuffix = new JCheckBox(JMeterUtils.getResString("resultsaver_skipsuffix")); // $NON-NLS-1$
box.add(skipSuffix);
addTimestamp = new JCheckBox(JMeterUtils.getResString("resultsaver_addtimestamp")); // $NON-NLS-1$
box.add(addTimestamp);
numberPadLength = new JLabeledTextField(JMeterUtils.getResString("resultsaver_numberpadlen"));// $NON-NLS-1$
box.add(numberPadLength);
add(box, BorderLayout.NORTH); add(box, BorderLayout.NORTH);
} }
private JPanel createFilenamePrefixPanel() private Component createSaveFormatPanel() {
{ filename = new JLabeledTextField(JMeterUtils.getResString("resultsaver_prefix"));
JLabel label = new JLabel(JMeterUtils.getResString("resultsaver_prefix")); // $NON-NLS-1$
filename = new JTextField(10);
filename.setName(ResultSaver.FILENAME); filename.setName(ResultSaver.FILENAME);
label.setLabelFor(filename);
JPanel filenamePanel = new JPanel(new BorderLayout(5, 0)); numberPadLength = new JLabeledTextField(JMeterUtils.getResString("resultsaver_numberpadlen"));// $NON-NLS-1$
filenamePanel.add(label, BorderLayout.WEST); numberPadLength.setName(ResultSaver.NUMBER_PAD_LENGTH);
filenamePanel.add(filename, BorderLayout.CENTER);
return filenamePanel;
}
skipAutoNumber = new JCheckBox(JMeterUtils.getResString("resultsaver_skipautonumber")); // $NON-NLS-1$
skipSuffix = new JCheckBox(JMeterUtils.getResString("resultsaver_skipsuffix")); // $NON-NLS-1$
addTimestamp = new JCheckBox(JMeterUtils.getResString("resultsaver_addtimestamp")); // $NON-NLS-1$
private JPanel createVariableNamePanel() variableName = new JLabeledTextField(JMeterUtils.getResString("resultsaver_variable"));
{
JLabel label = new JLabel(JMeterUtils.getResString("resultsaver_variable")); // $NON-NLS-1$
variableName = new JTextField(10);
variableName.setName(ResultSaver.VARIABLE_NAME); variableName.setName(ResultSaver.VARIABLE_NAME);
label.setLabelFor(variableName);
JPanel filenamePanel = new JPanel(new BorderLayout(5, 0)); JPanel panel = new JPanel(new GridBagLayout());
filenamePanel.add(label, BorderLayout.WEST); panel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getResString("resultsaver_save_format"))); //$NON-NLS-1$
filenamePanel.add(variableName, BorderLayout.CENTER); GridBagConstraints gbc = new GridBagConstraints();
return filenamePanel; initConstraints(gbc);
addField(panel, variableName, gbc);
resetContraints(gbc);
addField(panel, filename, gbc);
resetContraints(gbc);
addField(panel, skipAutoNumber, gbc);
resetContraints(gbc);
addField(panel, skipSuffix, gbc);
resetContraints(gbc);
addField(panel, addTimestamp, gbc);
resetContraints(gbc);
addField(panel, numberPadLength, gbc);
resetContraints(gbc);
return panel;
} }
private Component createSaveConditionsPanel() {
successOnly = new JCheckBox(JMeterUtils.getResString("resultsaver_success")); // $NON-NLS-1$
errorsOnly = new JCheckBox(JMeterUtils.getResString("resultsaver_errors")); // $NON-NLS-1$
ignoreTC = new JCheckBox(JMeterUtils.getResString("resultsaver_ignore_tc")); // $NON-NLS-1$
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getResString("resultsaver_save_conditions"))); //$NON-NLS-1$
GridBagConstraints gbc = new GridBagConstraints();
initConstraints(gbc);
addField(panel, successOnly, gbc);
resetContraints(gbc);
addField(panel, errorsOnly, gbc);
resetContraints(gbc);
addField(panel, ignoreTC, gbc);
resetContraints(gbc);
return panel;
}
// Needed to avoid Class cast error in Clear.java // Needed to avoid Class cast error in Clear.java
@Override @Override
public void clearData() { public void clearData() {
// NOOP
}
private void addField(JPanel panel, JCheckBox field, GridBagConstraints gbc) {
gbc.weightx = 2;
gbc.fill=GridBagConstraints.HORIZONTAL;
panel.add(field, gbc.clone());
}
private void addField(JPanel panel, JLabeledTextField field, GridBagConstraints gbc) {
List<JComponent> item = field.getComponentList();
panel.add(item.get(0), gbc.clone());
gbc.gridx++;
gbc.weightx = 1;
gbc.fill=GridBagConstraints.HORIZONTAL;
panel.add(item.get(1), gbc.clone());
}
// Next line
private void resetContraints(GridBagConstraints gbc) {
gbc.gridx = 0;
gbc.gridy++;
gbc.weightx = 0;
gbc.fill=GridBagConstraints.NONE;
}
private void initConstraints(GridBagConstraints gbc) {
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.fill = GridBagConstraints.NONE;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0;
gbc.weighty = 0;
} }
} }

View File

@ -939,13 +939,16 @@ restart=Restart
resultaction_title=Result Status Action Handler resultaction_title=Result Status Action Handler
resultsaver_addtimestamp=Add timestamp resultsaver_addtimestamp=Add timestamp
resultsaver_errors=Save Failed Responses only resultsaver_errors=Save Failed Responses only
resultsaver_numberpadlen=Minimum Length of sequence number resultsaver_ignore_tc=Don't save Transaction Controller SampleResult
resultsaver_prefix=Filename prefix\: resultsaver_numberpadlen=Minimum Length of sequence number \:
resultsaver_prefix=Filename prefix (can include folders) \:
resultsaver_save_conditions=Save conditions
resultsaver_save_format=Save details
resultsaver_skipautonumber=Don't add number to prefix resultsaver_skipautonumber=Don't add number to prefix
resultsaver_skipsuffix=Don't add suffix resultsaver_skipsuffix=Don't add content type suffix
resultsaver_success=Save Successful Responses only resultsaver_success=Save Successful Responses only
resultsaver_title=Save Responses to a file resultsaver_title=Save Responses to a file
resultsaver_variable=Variable Name: resultsaver_variable=Variable Name containing saved file name \:
result_function=The result of the function is result_function=The result of the function is
retobj=Return object retobj=Return object
return_code_config_box_title=Return Code Configuration return_code_config_box_title=Return Code Configuration

View File

@ -929,8 +929,11 @@ result_function=Le r\u00E9sultat de la fonction est \:
resultaction_title=Op\u00E9rateur R\u00E9sultats Action resultaction_title=Op\u00E9rateur R\u00E9sultats Action
resultsaver_addtimestamp=Ajouter un timestamp resultsaver_addtimestamp=Ajouter un timestamp
resultsaver_errors=Enregistrer seulement les r\u00E9ponses en \u00E9checs resultsaver_errors=Enregistrer seulement les r\u00E9ponses en \u00E9checs
resultsaver_ignore_tc=Ne pas enregistrer l''\u00E9chantillon Transaction Controller
resultsaver_numberpadlen=Taille minimale du num\u00E9ro de s\u00E9quence resultsaver_numberpadlen=Taille minimale du num\u00E9ro de s\u00E9quence
resultsaver_prefix=Pr\u00E9fixe du nom de fichier \: resultsaver_prefix=Pr\u00E9fixe du nom de fichier \:
resultsaver_save_conditions=Conditions d''enregistrement
resultsaver_save_format=D\u00E9tails de l''enregistrement
resultsaver_skipautonumber=Ne pas ajouter de nombre au pr\u00E9fixe resultsaver_skipautonumber=Ne pas ajouter de nombre au pr\u00E9fixe
resultsaver_skipsuffix=Ne pas ajouter de suffixe resultsaver_skipsuffix=Ne pas ajouter de suffixe
resultsaver_success=Enregistrer seulement les r\u00E9ponses en succ\u00E8s resultsaver_success=Enregistrer seulement les r\u00E9ponses en succ\u00E8s

View File

@ -98,6 +98,7 @@ this behaviour, set <code>httpclient.reset_state_on_thread_group_iteration=false
<h3>Listeners</h3> <h3>Listeners</h3>
<ul> <ul>
<li><bug>62195</bug>Save Responses to a file : Improve component and UI. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
</ul> </ul>
<h3>Timers, Assertions, Config, Pre- &amp; Post-Processors</h3> <h3>Timers, Assertions, Config, Pre- &amp; Post-Processors</h3>

View File

@ -3178,23 +3178,26 @@ i.e. 30.0 requests/minute is saved as <code>0.5</code>.
</description> </description>
<properties> <properties>
<property name="Name" required="No">Descriptive name for this element that is shown in the tree.</property> <property name="Name" required="No">Descriptive name for this element that is shown in the tree.</property>
<property name="Filename Prefix" required="Yes">Prefix for the generated file names; this can include a directory name. <property name="Filename Prefix (can include folders)" required="Yes">Prefix for the generated file names; this can include a directory name.
Relative paths are resolved relative to the current working directory (which defaults to the <code>bin/</code> directory). Relative paths are resolved relative to the current working directory (which defaults to the <code>bin/</code> directory).
JMeter also supports paths relative to the directory containing the current test plan (JMX file). JMeter also supports paths relative to the directory containing the current test plan (JMX file).
If the path name begins with "<code>~/</code>" (or whatever is in the <code>jmeter.save.saveservice.base_prefix</code> JMeter property), If the path name begins with "<code>~/</code>" (or whatever is in the <code>jmeter.save.saveservice.base_prefix</code> JMeter property),
then the path is assumed to be relative to the JMX file location. then the path is assumed to be relative to the JMX file location. <br/>
If parent folders in prefix do not exists, JMeter will create them and stop test if it fails.
</property> </property>
<property name="Variable Name" required="No"> <property name="Variable Name containing saved file name" required="No">
Name of a variable in which to save the generated file name (so it can be used later in the test plan). Name of a variable in which to save the generated file name (so it can be used later in the test plan).
If there are sub-samples then a numeric suffix is added to the variable name. If there are sub-samples then a numeric suffix is added to the variable name.
E.g. if the variable name is <code>FILENAME</code>, then the parent sample file name is saved in the variable <code>FILENAME</code>, E.g. if the variable name is <code>FILENAME</code>, then the parent sample file name is saved in the variable <code>FILENAME</code>,
and the filenames for the child samplers are saved in <code>FILENAME1</code>, <code>FILENAME2</code> etc. and the filenames for the child samplers are saved in <code>FILENAME1</code>, <code>FILENAME2</code> etc.
</property> </property>
<property name="Minimum Length of sequence number" required="No">If "<code>Don't add number to prefix</code>" is not checked, then numbers added to prefix will be padded by <code>0</code> so that prefix is has size of this value. Defaults to <code>0</code>.</property>
<property name="Save Failed Responses only" required="Yes">If selected, then only failed responses are saved</property> <property name="Save Failed Responses only" required="Yes">If selected, then only failed responses are saved</property>
<property name="Save Successful Responses only" required="Yes">If selected, then only successful responses are saved</property> <property name="Save Successful Responses only" required="Yes">If selected, then only successful responses are saved</property>
<property name="Don't add number to prefix" required="Yes">If selected, then no number is added to the prefix. If you select this option, make sure that the prefix is unique or the file may be overwritten.</property> <property name="Don't add number to prefix" required="Yes">If selected, then no number is added to the prefix. If you select this option, make sure that the prefix is unique or the file may be overwritten.</property>
<property name="Don't add suffix" required="Yes">If selected, then no suffix is added. If you select this option, make sure that the prefix is unique or the file may be overwritten.</property> <property name="Don't add content type suffix" required="Yes">If selected, then no suffix is added. If you select this option, make sure that the prefix is unique or the file may be overwritten.</property>
<property name="Minimum Length of sequence number" required="No">If "<code>Don't add number to prefix</code>" is not checked, then numbers added to prefix will be padded by <code>0</code> so that prefix is has size of this value. Defaults to <code>0</code>.</property> <property name="Add timestamp" required="Yes">If selected, then date will be included in file suffix following format <code>yyyyMMdd-HHmm_</code></property>
<property name="Don't Save Transaction Controller SampleResult" required="Yes">If selected, then SamplerResult generated by Transaction Controller will be ignored</property>
</properties> </properties>
</component> </component>