--- bin/jmeter.properties (revision 1642402) +++ bin/jmeter.properties (working copy) @@ -775,6 +775,20 @@ # Write messages to System.out #summariser.out=true + +#--------------------------------------------------------------------------- +# Aggregate Report and Aggregate Graph - configuration +#--------------------------------------------------------------------------- +# +# Percentiles to display in reports +# Can be float value between 0 and 100 +# First percentile to display, defaults to 90% +#aggregate_rpt_pct1=90 +# Second percentile to display, defaults to 95% +#aggregate_rpt_pct2=95 +# Second percentile to display, defaults to 99% +#aggregate_rpt_pct3=99 + #--------------------------------------------------------------------------- # BeanShell configuration #--------------------------------------------------------------------------- --- src/components/org/apache/jmeter/visualizers/BarGraph.java (revision 1642402) +++ src/components/org/apache/jmeter/visualizers/BarGraph.java (working copy) @@ -23,8 +23,6 @@ import javax.swing.JCheckBox; -import org.apache.jmeter.util.JMeterUtils; - public class BarGraph { private String label; @@ -34,13 +32,13 @@ private Color backColor; /** - * @param resString The label of this component + * @param label The label of this component * @param checked Flag whether the corresponding checkbox should be checked * @param backColor The color of the background */ - public BarGraph(String resString, boolean checked, Color backColor) { + public BarGraph(String label, boolean checked, Color backColor) { super(); - this.label = JMeterUtils.getResString(resString); + this.label = label; this.chkBox = new JCheckBox(this.label, checked); this.backColor = backColor; } --- src/components/org/apache/jmeter/visualizers/StatGraphVisualizer.java (revision 1642402) +++ src/components/org/apache/jmeter/visualizers/StatGraphVisualizer.java (working copy) @@ -28,6 +28,7 @@ import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -65,6 +66,7 @@ import org.apache.jmeter.gui.action.SaveGraphics; import org.apache.jmeter.gui.util.FileDialoger; import org.apache.jmeter.gui.util.FilePanel; +import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer; import org.apache.jmeter.gui.util.VerticalPanel; import org.apache.jmeter.samplers.Clearable; import org.apache.jmeter.samplers.SampleResult; @@ -92,24 +94,50 @@ public class StatGraphVisualizer extends AbstractVisualizer implements Clearable, ActionListener { private static final long serialVersionUID = 240L; + private static final String pct1Label = JMeterUtils.getPropDefault("aggregate_rpt_pct1", "90"); + private static final String pct2Label = JMeterUtils.getPropDefault("aggregate_rpt_pct2", "95"); + private static final String pct3Label = JMeterUtils.getPropDefault("aggregate_rpt_pct3", "99"); + + private static final Float pct1Value = new Float(Float.parseFloat(pct1Label)/100); + private static final Float pct2Value = new Float(Float.parseFloat(pct2Label)/100); + private static final Float pct3Value = new Float(Float.parseFloat(pct3Label)/100); + private static final Logger log = LoggingManager.getLoggerForClass(); - private final String[] COLUMNS = { JMeterUtils.getResString("sampler_label"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_count"), //$NON-NLS-1$ - JMeterUtils.getResString("average"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_median"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_90%_line"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_min"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_max"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_error%"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_rate"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_bandwidth") }; //$NON-NLS-1$ + static final String[] COLUMNS = { + "sampler_label", //$NON-NLS-1$ + "aggregate_report_count", //$NON-NLS-1$ + "average", //$NON-NLS-1$ + "aggregate_report_median", //$NON-NLS-1$ + "aggregate_report_xx_pct1_line", //$NON-NLS-1$ + "aggregate_report_xx_pct2_line", //$NON-NLS-1$ + "aggregate_report_xx_pct3_line", //$NON-NLS-1$ + "aggregate_report_min", //$NON-NLS-1$ + "aggregate_report_max", //$NON-NLS-1$ + "aggregate_report_error%", //$NON-NLS-1$ + "aggregate_report_rate", //$NON-NLS-1$ + "aggregate_report_bandwidth" }; //$NON-NLS-1$ + + static final Object[][] COLUMNS_MSG_PARAMETERS = { null, //$NON-NLS-1$ + null, //$NON-NLS-1$ + null, //$NON-NLS-1$ + null, //$NON-NLS-1$ + new Object[]{pct1Label}, //$NON-NLS-1$ + new Object[]{pct2Label}, //$NON-NLS-1$ + new Object[]{pct3Label}, //$NON-NLS-1$ + null, //$NON-NLS-1$ + null, //$NON-NLS-1$ + null, //$NON-NLS-1$ + null, //$NON-NLS-1$ + null }; //$NON-NLS-1$ - private final String[] GRAPH_COLUMNS = {JMeterUtils.getResString("average"),//$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_median"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_90%_line"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_min"), //$NON-NLS-1$ - JMeterUtils.getResString("aggregate_report_max")}; //$NON-NLS-1$ + private final String[] GRAPH_COLUMNS = {"average",//$NON-NLS-1$ + "aggregate_report_median", //$NON-NLS-1$ + "aggregate_report_xx_pct1_line", //$NON-NLS-1$ + "aggregate_report_xx_pct2_line", //$NON-NLS-1$ + "aggregate_report_xx_pct3_line", //$NON-NLS-1$ + "aggregate_report_min", //$NON-NLS-1$ + "aggregate_report_max"}; //$NON-NLS-1$ private final String TOTAL_ROW_LABEL = JMeterUtils.getResString("aggregate_report_total_label"); //$NON-NLS-1$ @@ -239,7 +267,24 @@ public StatGraphVisualizer() { super(); - model = new ObjectTableModel(COLUMNS, + model = createObjectTableModel(); + eltList.add(new BarGraph(JMeterUtils.getResString("average"), true, new Color(202, 0, 0))); + eltList.add(new BarGraph(JMeterUtils.getResString("aggregate_report_median"), false, new Color(49, 49, 181))); + eltList.add(new BarGraph(MessageFormat.format(JMeterUtils.getResString("aggregate_report_xx_pct1_line"),new Object[]{pct1Label}), false, new Color(42, 121, 42))); + eltList.add(new BarGraph(MessageFormat.format(JMeterUtils.getResString("aggregate_report_xx_pct2_line"),new Object[]{pct2Label}), false, new Color(242, 226, 8))); + eltList.add(new BarGraph(MessageFormat.format(JMeterUtils.getResString("aggregate_report_xx_pct3_line"),new Object[]{pct3Label}), false, new Color(202, 10 , 232))); + eltList.add(new BarGraph(JMeterUtils.getResString("aggregate_report_min"), false, Color.LIGHT_GRAY)); + eltList.add(new BarGraph(JMeterUtils.getResString("aggregate_report_max"), false, Color.DARK_GRAY)); + clearData(); + init(); + } + + /** + * Creates that Table model + * @return ObjectTableModel + */ + static ObjectTableModel createObjectTableModel() { + return new ObjectTableModel(COLUMNS, SamplingStatCalculator.class, new Functor[] { new Functor("getLabel"), //$NON-NLS-1$ @@ -247,37 +292,37 @@ new Functor("getMeanAsNumber"), //$NON-NLS-1$ new Functor("getMedian"), //$NON-NLS-1$ new Functor("getPercentPoint", //$NON-NLS-1$ - new Object[] { new Float(.900) }), + new Object[] { pct1Value }), + new Functor("getPercentPoint", //$NON-NLS-1$ + new Object[] { pct2Value }), + new Functor("getPercentPoint", //$NON-NLS-1$ + new Object[] { pct3Value }), new Functor("getMin"), //$NON-NLS-1$ new Functor("getMax"), //$NON-NLS-1$ new Functor("getErrorPercentage"), //$NON-NLS-1$ new Functor("getRate"), //$NON-NLS-1$ new Functor("getKBPerSecond") }, //$NON-NLS-1$ - new Functor[] { null, null, null, null, null, null, null, null, null, null }, - new Class[] { String.class, Long.class, Long.class, Long.class, Long.class, Long.class, - Long.class, String.class, String.class, String.class }); - eltList.add(new BarGraph("average", true, new Color(202, 0, 0))); - eltList.add(new BarGraph("aggregate_report_median", false, new Color(49, 49, 181))); - eltList.add(new BarGraph("aggregate_report_90%_line", false, new Color(42, 121, 42))); - eltList.add(new BarGraph("aggregate_report_min", false, Color.LIGHT_GRAY)); - eltList.add(new BarGraph("aggregate_report_max", false, Color.DARK_GRAY)); - clearData(); - init(); + new Functor[] { null, null, null, null, null, null, null, null, null, null, null, null }, + new Class[] { String.class, Long.class, Long.class, Long.class, Long.class, + Long.class, Long.class, Long.class, Long.class, String.class, + String.class, String.class }); } // Column renderers - private static final TableCellRenderer[] RENDERERS = + static final TableCellRenderer[] RENDERERS = new TableCellRenderer[]{ null, // Label null, // count null, // Mean null, // median null, // 90% + null, // 95% + null, // 99% null, // Min null, // Max - new NumberRenderer("#0.00%"), // Error %age - new RateRenderer("#.0"), // Throughpur - new NumberRenderer("#.0"), // pageSize + new NumberRenderer("#0.00%"), // Error %age //$NON-NLS-1$ + new RateRenderer("#.0"), // Throughput //$NON-NLS-1$ + new NumberRenderer("#.0"), // pageSize //$NON-NLS-1$ }; public static boolean testFunctors(){ @@ -347,7 +392,9 @@ mainPanel.add(makeTitlePanel()); myJTable = new JTable(model); - myJTable.setPreferredScrollableViewportSize(new Dimension(500, 80)); + // Fix centering of titles + myJTable.getTableHeader().setDefaultRenderer(new HeaderAsPropertyRenderer(COLUMNS_MSG_PARAMETERS)); + myJTable.setPreferredScrollableViewportSize(new Dimension(500, 70)); RendererUtils.applyRenderers(myJTable, RENDERERS); myScrollPane = new JScrollPane(myJTable); @@ -424,7 +471,7 @@ graphPanel.setMaxLength(maxLength); graphPanel.setMaxYAxisScale(maxYAxisScale); graphPanel.setXAxisLabels(getAxisLabels()); - graphPanel.setXAxisTitle((String) columnsList.getSelectedItem()); + graphPanel.setXAxisTitle(JMeterUtils.getResString((String) columnsList.getSelectedItem())); graphPanel.setYAxisLabels(this.yAxisLabel); graphPanel.setYAxisTitle(this.yAxisTitle); graphPanel.setLegendLabels(getLegendLabels()); --- src/components/org/apache/jmeter/visualizers/StatVisualizer.java (revision 1642402) +++ src/components/org/apache/jmeter/visualizers/StatVisualizer.java (working copy) @@ -37,7 +37,6 @@ import javax.swing.JTable; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; -import javax.swing.table.TableCellRenderer; import org.apache.jmeter.gui.util.FileDialoger; import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer; @@ -47,11 +46,8 @@ import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.visualizers.gui.AbstractVisualizer; -import org.apache.jorphan.gui.NumberRenderer; import org.apache.jorphan.gui.ObjectTableModel; -import org.apache.jorphan.gui.RateRenderer; import org.apache.jorphan.gui.RendererUtils; -import org.apache.jorphan.reflect.Functor; import org.apache.jorphan.util.JOrphanUtils; /** @@ -69,18 +65,6 @@ private static final String SAVE_HEADERS = "saveHeaders"; //$NON-NLS-1$ - private static final String[] COLUMNS = { - "sampler_label", //$NON-NLS-1$ - "aggregate_report_count", //$NON-NLS-1$ - "average", //$NON-NLS-1$ - "aggregate_report_median", //$NON-NLS-1$ - "aggregate_report_90%_line", //$NON-NLS-1$ - "aggregate_report_min", //$NON-NLS-1$ - "aggregate_report_max", //$NON-NLS-1$ - "aggregate_report_error%", //$NON-NLS-1$ - "aggregate_report_rate", //$NON-NLS-1$ - "aggregate_report_bandwidth" }; //$NON-NLS-1$ - private final String TOTAL_ROW_LABEL = JMeterUtils.getResString("aggregate_report_total_label"); //$NON-NLS-1$ @@ -109,43 +93,11 @@ public StatVisualizer() { super(); - model = new ObjectTableModel(COLUMNS, - SamplingStatCalculator.class, - new Functor[] { - new Functor("getLabel"), //$NON-NLS-1$ - new Functor("getCount"), //$NON-NLS-1$ - new Functor("getMeanAsNumber"), //$NON-NLS-1$ - new Functor("getMedian"), //$NON-NLS-1$ - new Functor("getPercentPoint", //$NON-NLS-1$ - new Object[] { new Float(.900) }), - new Functor("getMin"), //$NON-NLS-1$ - new Functor("getMax"), //$NON-NLS-1$ - new Functor("getErrorPercentage"), //$NON-NLS-1$ - new Functor("getRate"), //$NON-NLS-1$ - new Functor("getKBPerSecond") //$NON-NLS-1$ - }, - new Functor[] { null, null, null, null, null, null, null, null, null, null }, - new Class[] { String.class, Long.class, Long.class, Long.class, Long.class, - Long.class, Long.class, String.class, String.class, String.class }); + model = StatGraphVisualizer.createObjectTableModel(); clearData(); init(); } - // Column renderers - private static final TableCellRenderer[] RENDERERS = - new TableCellRenderer[]{ - null, // Label - null, // count - null, // Mean - null, // median - null, // 90% - null, // Min - null, // Max - new NumberRenderer("#0.00%"), // Error %age //$NON-NLS-1$ - new RateRenderer("#.0"), // Throughput //$NON-NLS-1$ - new NumberRenderer("#.0"), // pageSize //$NON-NLS-1$ - }; - /** @deprecated - only for use in testing */ @Deprecated public static boolean testFunctors(){ @@ -219,9 +171,9 @@ // SortFilterModel mySortedModel = // new SortFilterModel(myStatTableModel); myJTable = new JTable(model); - myJTable.getTableHeader().setDefaultRenderer(new HeaderAsPropertyRenderer()); + myJTable.getTableHeader().setDefaultRenderer(new HeaderAsPropertyRenderer(StatGraphVisualizer.COLUMNS_MSG_PARAMETERS)); myJTable.setPreferredScrollableViewportSize(new Dimension(500, 70)); - RendererUtils.applyRenderers(myJTable, RENDERERS); + RendererUtils.applyRenderers(myJTable, StatGraphVisualizer.RENDERERS); myScrollPane = new JScrollPane(myJTable); this.add(mainPanel, BorderLayout.NORTH); this.add(myScrollPane, BorderLayout.CENTER); --- src/core/org/apache/jmeter/gui/util/HeaderAsPropertyRenderer.java (revision 1642402) +++ src/core/org/apache/jmeter/gui/util/HeaderAsPropertyRenderer.java (working copy) @@ -19,6 +19,7 @@ package org.apache.jmeter.gui.util; import java.awt.Component; +import java.text.MessageFormat; import javax.swing.JTable; import javax.swing.SwingConstants; @@ -34,9 +35,21 @@ public class HeaderAsPropertyRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 240L; + private Object[][] columnsMsgParameters; + /** + * + */ public HeaderAsPropertyRenderer() { + this(null); + } + + /** + * @param columnsMsgParameters Optional parameters of i18n keys + */ + public HeaderAsPropertyRenderer(Object[][] columnsMsgParameters) { super(); + this.columnsMsgParameters = columnsMsgParameters; } @Override @@ -68,6 +81,10 @@ if (value == null){ return ""; } - return JMeterUtils.getResString(value.toString()); + if(columnsMsgParameters != null && columnsMsgParameters[column] != null) { + return MessageFormat.format(JMeterUtils.getResString(value.toString()), columnsMsgParameters[column]); + } else { + return JMeterUtils.getResString(value.toString()); + } } } --- src/core/org/apache/jmeter/resources/messages.properties (revision 1642402) +++ src/core/org/apache/jmeter/resources/messages.properties (working copy) @@ -77,8 +77,10 @@ aggregate_graph_yaxis_group=Y Axis (milli-seconds) aggregate_graph_yaxis_max_value=Scale maximum value\: aggregate_report=Aggregate Report +aggregate_report_xx_pct1_line={0}% Line +aggregate_report_xx_pct2_line={0}% Line +aggregate_report_xx_pct3_line={0}% Line aggregate_report_90=90% -aggregate_report_90%_line=90% Line aggregate_report_bandwidth=KB/sec aggregate_report_count=# Samples aggregate_report_error=Error --- src/core/org/apache/jmeter/resources/messages_fr.properties (revision 1642402) +++ src/core/org/apache/jmeter/resources/messages_fr.properties (working copy) @@ -71,8 +71,10 @@ aggregate_graph_yaxis_group=Ordonn\u00E9es (milli-secondes) aggregate_graph_yaxis_max_value=Echelle maximum \: aggregate_report=Rapport agr\u00E9g\u00E9 +aggregate_report_xx_pct1_line={0}% centile +aggregate_report_xx_pct2_line={0}% centile +aggregate_report_xx_pct3_line={0}% centile aggregate_report_90=90% -aggregate_report_90%_line=90e centile aggregate_report_bandwidth=Ko/sec aggregate_report_count=\# Echantillons aggregate_report_error=Erreur --- xdocs/usermanual/component_reference.xml (revision 1642402) +++ xdocs/usermanual/component_reference.xml (working copy) @@ -2922,12 +2922,20 @@

Calculation of the Median and 90% Line (90th percentile) values requires additional memory. -For JMeter 2.3.4 and earlier, details of each sample were saved separately, which meant a lot of memory was needed. JMeter now combines samples with the same elapsed time, so far less memory is used. However, for samples that take more than a few seconds, the probability is that fewer samples will have identical times, in which case more memory will be needed. +Note you can use this listener afterwards to reload a CSV or XML results file which is the recommended way to avoid performance impacts. See the for a similar Listener that does not store individual samples and so needs constant memory.

+ +Starting with JMeter 2.12, you can configure the 3 percentile values you want to compute, this can be done by setting properties: + +