You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2020/04/26 12:55:46 UTC

[jmeter] branch master updated: Add a 'Median' field to the dashboard and make the response time percentile fields support floating-point numbers (#567)

This is an automated email from the ASF dual-hosted git repository.

pmouawad pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git


The following commit(s) were added to refs/heads/master by this push:
     new 9a8ca62  Add a 'Median' field to the dashboard and make the response time percentile fields support floating-point numbers (#567)
9a8ca62 is described below

commit 9a8ca629dec1bf70444161988481399332434173
Author: Keith Mo <ke...@gmail.com>
AuthorDate: Sun Apr 26 20:55:36 2020 +0800

    Add a 'Median' field to the dashboard and make the response time percentile fields support floating-point numbers (#567)
    
    * add median field and fix percentiles
    * fix imports
    * fix style
    
    Contributed by Keith Mo keithmork
---
 bin/report-template/content/js/dashboard.js.fmkr   | 14 ++++---
 .../jmeter/report/dashboard/JsonExporter.java      | 13 ++++---
 .../jmeter/report/dashboard/SamplingStatistic.java | 15 ++++++++
 .../processor/StatisticsSummaryConsumer.java       | 40 +++++++++++---------
 .../report/processor/StatisticsSummaryData.java    | 13 ++++++-
 ...sponseTimePercentilesOverTimeGraphConsumer.java | 43 ++++++++++++++--------
 .../java/org/apache/jmeter/util/JMeterUtils.java   | 18 +++++++++
 .../apache/jmeter/resources/messages.properties    |  3 +-
 .../apache/jmeter/resources/messages_fr.properties |  3 +-
 ...TimePercentilesOverTimeGraphConsumerSpec.groovy |  3 +-
 .../apache/jmeter/gui/report/HTMLReportExpect.json |  3 ++
 11 files changed, 118 insertions(+), 50 deletions(-)

diff --git a/bin/report-template/content/js/dashboard.js.fmkr b/bin/report-template/content/js/dashboard.js.fmkr
index 94cd0f2..31836ad 100644
--- a/bin/report-template/content/js/dashboard.js.fmkr
+++ b/bin/report-template/content/js/dashboard.js.fmkr
@@ -40,7 +40,7 @@ function summaryTableHeader(header) {
 
     cell = document.createElement('th');
     cell.setAttribute("data-sorter", false);
-    cell.colSpan = 6;
+    cell.colSpan = 7;
     cell.innerHTML = "Response Times (ms)";
     newRow.appendChild(cell);
 
@@ -197,16 +197,18 @@ $(document).ready(function() {
             case 4:
             // Mean
             case 7:
-            // Percentile 1
+            // Median
             case 8:
-            // Percentile 2
+            // Percentile 1
             case 9:
-            // Percentile 3
+            // Percentile 2
             case 10:
-            // Throughput
+            // Percentile 3
             case 11:
-            // Kbytes/s
+            // Throughput
             case 12:
+            // Kbytes/s
+            case 13:
             // Sent Kbytes/s
                 item = item.toFixed(2);
                 break;
diff --git a/src/core/src/main/java/org/apache/jmeter/report/dashboard/JsonExporter.java b/src/core/src/main/java/org/apache/jmeter/report/dashboard/JsonExporter.java
index d93b25b..8fffcec 100644
--- a/src/core/src/main/java/org/apache/jmeter/report/dashboard/JsonExporter.java
+++ b/src/core/src/main/java/org/apache/jmeter/report/dashboard/JsonExporter.java
@@ -125,12 +125,13 @@ public class JsonExporter extends AbstractDataExporter {
         statistic.setMeanResTime((Double) ((ValueResultData)listResultData.get(4)).getValue());
         statistic.setMinResTime((Long) ((ValueResultData)listResultData.get(5)).getValue());
         statistic.setMaxResTime((Long) ((ValueResultData)listResultData.get(6)).getValue());
-        statistic.setPct1ResTime((Double) ((ValueResultData)listResultData.get(7)).getValue());
-        statistic.setPct2ResTime((Double) ((ValueResultData)listResultData.get(8)).getValue());
-        statistic.setPct3ResTime((Double) ((ValueResultData)listResultData.get(9)).getValue());
-        statistic.setThroughput((Double) ((ValueResultData)listResultData.get(10)).getValue());
-        statistic.setReceivedKBytesPerSec((Double) ((ValueResultData)listResultData.get(11)).getValue());
-        statistic.setSentKBytesPerSec((Double) ((ValueResultData)listResultData.get(12)).getValue());
+        statistic.setMedianResTime((Double) ((ValueResultData)listResultData.get(7)).getValue());
+        statistic.setPct1ResTime((Double) ((ValueResultData)listResultData.get(8)).getValue());
+        statistic.setPct2ResTime((Double) ((ValueResultData)listResultData.get(9)).getValue());
+        statistic.setPct3ResTime((Double) ((ValueResultData)listResultData.get(10)).getValue());
+        statistic.setThroughput((Double) ((ValueResultData)listResultData.get(11)).getValue());
+        statistic.setReceivedKBytesPerSec((Double) ((ValueResultData)listResultData.get(12)).getValue());
+        statistic.setSentKBytesPerSec((Double) ((ValueResultData)listResultData.get(13)).getValue());
         statistics.put(statistic.getTransaction(), statistic);
     }
 }
diff --git a/src/core/src/main/java/org/apache/jmeter/report/dashboard/SamplingStatistic.java b/src/core/src/main/java/org/apache/jmeter/report/dashboard/SamplingStatistic.java
index ff4a77b..eb0d209 100644
--- a/src/core/src/main/java/org/apache/jmeter/report/dashboard/SamplingStatistic.java
+++ b/src/core/src/main/java/org/apache/jmeter/report/dashboard/SamplingStatistic.java
@@ -28,6 +28,7 @@ public class SamplingStatistic {
     private long errorCount;
     private float errorPct;
     private double meanResTime;
+    private double medianResTime;
     private double minResTime;
     private double maxResTime;
     private double pct1ResTime;
@@ -112,6 +113,20 @@ public class SamplingStatistic {
     }
 
     /**
+     * @return medianResTime
+     */
+    public double getMedianResTime() {
+        return medianResTime;
+    }
+
+    /**
+     * @param medianResTime the meanResTime to set
+     */
+    public void setMedianResTime(double medianResTime) {
+        this.medianResTime = medianResTime;
+    }
+
+    /**
      * @return the minResTime
      */
     public double getMinResTime() {
diff --git a/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryConsumer.java b/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryConsumer.java
index 1ea06ba..2223bd8 100644
--- a/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryConsumer.java
+++ b/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryConsumer.java
@@ -17,6 +17,8 @@
 
 package org.apache.jmeter.report.processor;
 
+import java.math.BigDecimal;
+
 import org.apache.jmeter.report.core.Sample;
 import org.apache.jmeter.util.JMeterUtils;
 
@@ -27,6 +29,7 @@ import org.apache.jmeter.util.JMeterUtils;
  *      <li>errors</li>
  *      <li>error %</li>
  *      <li>mean response time</li>
+ *      <li>median response time</li>
  *      <li>percentile 1 (90% by default)</li>
  *      <li>percentile 2 (95% by default)</li>
  *      <li>percentile 3 (99% by default)</li>
@@ -41,13 +44,16 @@ import org.apache.jmeter.util.JMeterUtils;
  */
 public class StatisticsSummaryConsumer extends
         AbstractSummaryConsumer<StatisticsSummaryData> {
+    private static final String PCT1_LABEL = JMeterUtils.getPropDefault(
+            "aggregate_rpt_pct1", "90");
+    private static final String PCT2_LABEL = JMeterUtils.getPropDefault(
+            "aggregate_rpt_pct2", "95");
+    private static final String PCT3_LABEL = JMeterUtils.getPropDefault(
+            "aggregate_rpt_pct3", "99");
 
-    private static final int PERCENTILE_INDEX1 = JMeterUtils.getPropDefault(
-        "aggregate_rpt_pct1", 90);
-    private static final int PERCENTILE_INDEX2 = JMeterUtils.getPropDefault(
-        "aggregate_rpt_pct2", 95);
-    private static final int PERCENTILE_INDEX3 = JMeterUtils.getPropDefault(
-        "aggregate_rpt_pct3", 99);
+    private static final double PERCENTILE_INDEX1 = new BigDecimal(PCT1_LABEL).doubleValue();
+    private static final double PERCENTILE_INDEX2 = new BigDecimal(PCT2_LABEL).doubleValue();
+    private static final double PERCENTILE_INDEX3 = new BigDecimal(PCT3_LABEL).doubleValue();
 
     /**
      * Instantiates a new statistics summary consumer.
@@ -79,6 +85,7 @@ public class StatisticsSummaryConsumer extends
         data.getPercentile2().addValue(elapsedTime);
         data.getPercentile3().addValue(elapsedTime);
         data.getMean().addValue(elapsedTime);
+        data.getMedian().addValue(elapsedTime);
         data.setMin(elapsedTime);
         data.setMax(elapsedTime);
 
@@ -139,6 +146,7 @@ public class StatisticsSummaryConsumer extends
         result.addResult(new ValueResultData(data.getMean().getResult()));
         result.addResult(new ValueResultData(data.getMin()));
         result.addResult(new ValueResultData(data.getMax()));
+        result.addResult(new ValueResultData(data.getMedian().getResult()));
         result.addResult(new ValueResultData(data.getPercentile1().getResult()));
         result.addResult(new ValueResultData(data.getPercentile2().getResult()));
         result.addResult(new ValueResultData(data.getPercentile3().getResult()));
@@ -182,18 +190,10 @@ public class StatisticsSummaryConsumer extends
                 JMeterUtils.getResString("reportgenerator_summary_statistics_mean")));
         titles.addResult(new ValueResultData(JMeterUtils.getResString("reportgenerator_summary_statistics_min")));
         titles.addResult(new ValueResultData(JMeterUtils.getResString("reportgenerator_summary_statistics_max")));
-        titles.addResult(new ValueResultData(
-            String.format(
-                JMeterUtils.getResString("reportgenerator_summary_statistics_percentile_fmt"),
-                    PERCENTILE_INDEX1)));
-        titles.addResult(new ValueResultData(
-            String.format(
-                JMeterUtils.getResString("reportgenerator_summary_statistics_percentile_fmt"),
-                    PERCENTILE_INDEX2)));
-        titles.addResult(new ValueResultData(
-            String.format(
-                JMeterUtils.getResString("reportgenerator_summary_statistics_percentile_fmt"),
-                    PERCENTILE_INDEX3)));
+        titles.addResult(new ValueResultData(JMeterUtils.getResString("reportgenerator_summary_statistics_median")));
+        titles.addResult(new ValueResultData(formatPercentile(PCT1_LABEL)));
+        titles.addResult(new ValueResultData(formatPercentile(PCT2_LABEL)));
+        titles.addResult(new ValueResultData(formatPercentile(PCT3_LABEL)));
         titles.addResult(new ValueResultData(JMeterUtils.getResString("reportgenerator_summary_statistics_throughput")));
         titles.addResult(new ValueResultData(JMeterUtils.getResString("reportgenerator_summary_statistics_kbytes")));
         titles.addResult(new ValueResultData(JMeterUtils.getResString("reportgenerator_summary_statistics_sent_kbytes")));
@@ -201,4 +201,8 @@ public class StatisticsSummaryConsumer extends
         return titles;
     }
 
+    private String formatPercentile(String percentileLabel) {
+        return String.format(JMeterUtils.getResString("reportgenerator_summary_statistics_percentile_fmt"),
+                percentileLabel);
+    }
 }
diff --git a/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryData.java b/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryData.java
index ca95a49..a217c37 100644
--- a/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryData.java
+++ b/src/core/src/main/java/org/apache/jmeter/report/processor/StatisticsSummaryData.java
@@ -33,6 +33,7 @@ public class StatisticsSummaryData {
     private long errors = 0L;
     private long total = 0L;
     private final MeanAggregator mean;
+    private final PercentileAggregator median;
     private final PercentileAggregator percentile1;
     private final PercentileAggregator percentile2;
     private final PercentileAggregator percentile3;
@@ -191,12 +192,13 @@ public class StatisticsSummaryData {
      * @param percentileIndex2 value of second percentile
      * @param percentileIndex3 value of third percentile
      */
-    public StatisticsSummaryData(long percentileIndex1, long percentileIndex2,
-            long percentileIndex3) {
+    public StatisticsSummaryData(double percentileIndex1, double percentileIndex2,
+            double percentileIndex3) {
         percentile1 = new PercentileAggregator(percentileIndex1);
         percentile2 = new PercentileAggregator(percentileIndex2);
         percentile3 = new PercentileAggregator(percentileIndex3);
         mean = new MeanAggregator();
+        median = new PercentileAggregator(50);
     }
 
     /**
@@ -260,6 +262,13 @@ public class StatisticsSummaryData {
     }
 
     /**
+     * @return the median response times
+     */
+    public PercentileAggregator getMedian() {
+        return median;
+    }
+
+    /**
      * @return the sentBytes
      */
     public long getSentBytes() {
diff --git a/src/core/src/main/java/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumer.java b/src/core/src/main/java/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumer.java
index c8a3d91..2598292 100644
--- a/src/core/src/main/java/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumer.java
+++ b/src/core/src/main/java/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumer.java
@@ -17,11 +17,14 @@
 
 package org.apache.jmeter.report.processor.graph.impl;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.jmeter.report.processor.AggregatorFactory;
 import org.apache.jmeter.report.processor.MaxAggregatorFactory;
+import org.apache.jmeter.report.processor.MedianAggregatorFactory;
 import org.apache.jmeter.report.processor.MinAggregatorFactory;
 import org.apache.jmeter.report.processor.PercentileAggregatorFactory;
 import org.apache.jmeter.report.processor.graph.AbstractOverTimeGraphConsumer;
@@ -40,14 +43,14 @@ import org.apache.jmeter.util.JMeterUtils;
  */
 public class ResponseTimePercentilesOverTimeGraphConsumer
         extends AbstractOverTimeGraphConsumer {
-    private static final int PERCENTILE_INDEX1 = JMeterUtils.getPropDefault(
-            "aggregate_rpt_pct1", 90);
-    private static final int PERCENTILE_INDEX2 = JMeterUtils.getPropDefault(
-            "aggregate_rpt_pct2", 95);
-    private static final int PERCENTILE_INDEX3 = JMeterUtils.getPropDefault(
-            "aggregate_rpt_pct3", 99);
+    private static final String PCT1_LABEL = JMeterUtils.getPropDefault(
+            "aggregate_rpt_pct1", "90");
+    private static final String PCT2_LABEL = JMeterUtils.getPropDefault(
+            "aggregate_rpt_pct2", "95");
+    private static final String PCT3_LABEL = JMeterUtils.getPropDefault(
+            "aggregate_rpt_pct3", "99");
 
-    private static final String PERCENTILE_FORMAT = "%dth percentile";
+    private static final String PERCENTILE_FORMAT = "%sth percentile";
 
     @Override
     protected TimeStampKeysSelector createTimeStampKeysSelector() {
@@ -62,18 +65,19 @@ public class ResponseTimePercentilesOverTimeGraphConsumer
 
         groupInfos.put("aggregate_report_min", createMinGroupInfo());
         groupInfos.put("aggregate_report_max", createMaxGroupInfo());
+        groupInfos.put("aggregate_report_median", createMedianGroupInfo());
         groupInfos.put("aggregate_rpt_pct1",
-                createPercentileGroupInfo("aggregate_rpt_pct1", PERCENTILE_INDEX1));
+                createPercentileGroupInfo("aggregate_rpt_pct1", PCT1_LABEL));
         groupInfos.put("aggregate_rpt_pct2",
-                createPercentileGroupInfo("aggregate_rpt_pct2", PERCENTILE_INDEX2));
+                createPercentileGroupInfo("aggregate_rpt_pct2", PCT2_LABEL));
         groupInfos.put("aggregate_rpt_pct3",
-                createPercentileGroupInfo("aggregate_rpt_pct3", PERCENTILE_INDEX3));
+                createPercentileGroupInfo("aggregate_rpt_pct3", PCT3_LABEL));
 
         return groupInfos;
     }
 
-    private String formatPercentile(int percentile) {
-        return String.format(PERCENTILE_FORMAT, percentile);
+    private String formatPercentile(String percentileLabel) {
+        return String.format(PERCENTILE_FORMAT, percentileLabel);
     }
 
     private GroupInfo createMinGroupInfo() {
@@ -88,10 +92,19 @@ public class ResponseTimePercentilesOverTimeGraphConsumer
         return createGroupInfo(new MaxAggregatorFactory(), seriesSelector);
     }
 
-    private GroupInfo createPercentileGroupInfo(String propKey, int defaultValue) {
-        String seriesName = formatPercentile(defaultValue);
+    private GroupInfo createMedianGroupInfo() {
+        StaticSeriesSelector seriesSelector = new StaticSeriesSelector();
+        seriesSelector.setSeriesName("Median");
+        return createGroupInfo(new MedianAggregatorFactory(), seriesSelector);
+    }
+
+    private GroupInfo createPercentileGroupInfo(String propKey, String label) {
+        String seriesName = formatPercentile(label);
+        double defaultValue = new BigDecimal(label)
+                .divide(new BigDecimal("100"), 6, RoundingMode.CEILING)
+                .doubleValue();
 
-        int property = JMeterUtils.getPropDefault(propKey, defaultValue);
+        double property = JMeterUtils.getPropDefault(propKey, defaultValue);
         PercentileAggregatorFactory factory = new PercentileAggregatorFactory();
         factory.setPercentileIndex(property);
         StaticSeriesSelector seriesSelector = new StaticSeriesSelector();
diff --git a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java
index fc9d021..2f6360a 100644
--- a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java
+++ b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java
@@ -765,6 +765,24 @@ public class JMeterUtils implements UnitTestManager {
     }
 
     /**
+     * Get a double value with default if not present.
+     *
+     * @param propName
+     *            the name of the property.
+     * @param defaultVal
+     *            the default value.
+     * @return The PropDefault value
+     */
+    public static double getPropDefault(String propName, double defaultVal) {
+        try {
+            return Float.parseFloat(appProperties.getProperty(propName, Double.toString(defaultVal)).trim());
+        } catch (Exception e) {
+            log.warn("Exception '{}' occurred when fetching double property:'{}', defaulting to: {}", e.getMessage(), propName, defaultVal);
+        }
+        return defaultVal;
+    }
+
+    /**
      * Get a String value with default if not present.
      *
      * @param propName
diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties
index feccfc7..1489b45 100644
--- a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties
+++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties
@@ -974,8 +974,9 @@ reportgenerator_summary_statistics_sent_kbytes=Sent
 reportgenerator_summary_statistics_label=Label
 reportgenerator_summary_statistics_max=Max
 reportgenerator_summary_statistics_mean=Average
+reportgenerator_summary_statistics_median=Median
 reportgenerator_summary_statistics_min=Min
-reportgenerator_summary_statistics_percentile_fmt=%dth pct
+reportgenerator_summary_statistics_percentile_fmt=%sth pct
 reportgenerator_summary_statistics_throughput=Transactions/s
 reportgenerator_summary_total=Total
 request_data=Request Data
diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages_fr.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages_fr.properties
index 5dab3c4..9e04a2d 100644
--- a/src/core/src/main/resources/org/apache/jmeter/resources/messages_fr.properties
+++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages_fr.properties
@@ -957,8 +957,9 @@ reportgenerator_summary_statistics_kbytes=Reçues
 reportgenerator_summary_statistics_label=Libellé
 reportgenerator_summary_statistics_max=Max
 reportgenerator_summary_statistics_mean=Temps moyen
+reportgenerator_summary_statistics_median=Médiane
 reportgenerator_summary_statistics_min=Min
-reportgenerator_summary_statistics_percentile_fmt=%d%% centile
+reportgenerator_summary_statistics_percentile_fmt=%s%% centile
 reportgenerator_summary_statistics_sent_kbytes=Envoyés
 reportgenerator_summary_statistics_throughput=Débit
 reportgenerator_summary_total=Total
diff --git a/src/core/src/test/groovy/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumerSpec.groovy b/src/core/src/test/groovy/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumerSpec.groovy
index 9ea7f08..2036bf0 100644
--- a/src/core/src/test/groovy/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumerSpec.groovy
+++ b/src/core/src/test/groovy/org/apache/jmeter/report/processor/graph/impl/ResponseTimePercentilesOverTimeGraphConsumerSpec.groovy
@@ -28,7 +28,8 @@ class ResponseTimePercentilesOverTimeGraphConsumerSpec extends JMeterSpec {
              'aggregate_report_max',
              'aggregate_rpt_pct1',
              'aggregate_rpt_pct2',
-             'aggregate_rpt_pct3'] as Set
+             'aggregate_rpt_pct3',
+            'aggregate_report_median'] as Set
 
     def sut = new ResponseTimePercentilesOverTimeGraphConsumer()
 
diff --git a/src/dist-check/src/test/resources/org/apache/jmeter/gui/report/HTMLReportExpect.json b/src/dist-check/src/test/resources/org/apache/jmeter/gui/report/HTMLReportExpect.json
index c0421e5..25505fb 100644
--- a/src/dist-check/src/test/resources/org/apache/jmeter/gui/report/HTMLReportExpect.json
+++ b/src/dist-check/src/test/resources/org/apache/jmeter/gui/report/HTMLReportExpect.json
@@ -5,6 +5,7 @@
     "errorCount" : 3,
     "errorPct" : 100.0,
     "meanResTime" : 199.66666666666666,
+    "medianResTime":170.0,
     "minResTime" : 100.0,
     "maxResTime" : 329.0,
     "pct1ResTime" : 329.0,
@@ -20,6 +21,7 @@
     "errorCount" : 3,
     "errorPct" : 1.1764706,
     "meanResTime" : 235.47450980392148,
+    "medianResTime":232.0,
     "minResTime" : 100.0,
     "maxResTime" : 353.0,
     "pct1ResTime" : 337.0,
@@ -35,6 +37,7 @@
     "errorCount" : 0,
     "errorPct" : 0.0,
     "meanResTime" : 235.90079365079367,
+    "medianResTime":232.0,
     "minResTime" : 101.0,
     "maxResTime" : 353.0,
     "pct1ResTime" : 337.0,