mirror of https://github.com/apache/jmeter.git
Bug 62367 - HTML Report Generator: Add Graph Total Transactions per Second
Mainly contributed by laks.martha
Bugzilla Id: 62367
git-svn-id: https://svn.apache.org/repos/asf/jmeter/trunk@1831444 13f79535-47bb-0310-9956-ffa450edef68
Former-commit-id: 341fecb621
This commit is contained in:
parent
31cd47cac1
commit
5063b3863e
|
|
@ -1331,6 +1331,84 @@ function refreshTransactionsPerSecond(fixTimestamps) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var totalTPSInfos = {
|
||||||
|
data: ${totalTPS!"{}"},
|
||||||
|
getOptions: function(){
|
||||||
|
return {
|
||||||
|
series: {
|
||||||
|
lines: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
points: {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xaxis: {
|
||||||
|
mode: "time",
|
||||||
|
timeformat: "%H:%M:%S",
|
||||||
|
axisLabel: getElapsedTimeLabel(this.data.result.granularity),
|
||||||
|
axisLabelUseCanvas: true,
|
||||||
|
axisLabelFontSizePixels: 12,
|
||||||
|
axisLabelFontFamily: 'Verdana, Arial',
|
||||||
|
axisLabelPadding: 20,
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
axisLabel: "Number of transactions / sec",
|
||||||
|
axisLabelUseCanvas: true,
|
||||||
|
axisLabelFontSizePixels: 12,
|
||||||
|
axisLabelFontFamily: 'Verdana, Arial',
|
||||||
|
axisLabelPadding: 20
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
noColumns: 2,
|
||||||
|
show: true,
|
||||||
|
container: "#legendTotalTPS"
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
mode: 'xy'
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
hoverable: true // IMPORTANT! this is needed for tooltip to
|
||||||
|
// work
|
||||||
|
},
|
||||||
|
tooltip: true,
|
||||||
|
tooltipOpts: {
|
||||||
|
content: "%s at %x was %y transactions / sec"
|
||||||
|
},
|
||||||
|
colors: ["#9ACD32", "#FF6347"]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
createGraph: function () {
|
||||||
|
var data = this.data;
|
||||||
|
var dataset = prepareData(data.result.series, $("#choicesTotalTPS"));
|
||||||
|
var options = this.getOptions();
|
||||||
|
prepareOptions(options, data);
|
||||||
|
$.plot($("#flotTotalTPS"), dataset, options);
|
||||||
|
// setup overview
|
||||||
|
$.plot($("#overviewTotalTPS"), dataset, prepareOverviewOptions(options));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Total Transactions per second
|
||||||
|
function refreshTotalTPS(fixTimestamps) {
|
||||||
|
var infos = totalTPSInfos;
|
||||||
|
prepareSeries(infos.data);
|
||||||
|
if(fixTimestamps) {
|
||||||
|
fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0});
|
||||||
|
}
|
||||||
|
if(isGraph($("#flotTotalTPS"))){
|
||||||
|
infos.createGraph();
|
||||||
|
}else{
|
||||||
|
var choiceContainer = $("#choicesTotalTPS");
|
||||||
|
createLegend(choiceContainer, infos);
|
||||||
|
infos.createGraph();
|
||||||
|
setGraphZoomable("#flotTotalTPS", "#overviewTotalTPS");
|
||||||
|
$('#footerTotalTPS .legendColorBox > div').each(function(i){
|
||||||
|
$(this).clone().prependTo(choiceContainer.find("li").eq(i));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Collapse the graph matching the specified DOM element depending the collapsed
|
// Collapse the graph matching the specified DOM element depending the collapsed
|
||||||
// status
|
// status
|
||||||
function collapse(elem, collapsed){
|
function collapse(elem, collapsed){
|
||||||
|
|
@ -1388,6 +1466,11 @@ function collapse(elem, collapsed){
|
||||||
refreshTransactionsPerSecond(true);
|
refreshTransactionsPerSecond(true);
|
||||||
}
|
}
|
||||||
document.location.href="#transactionsPerSecond";
|
document.location.href="#transactionsPerSecond";
|
||||||
|
} else if (elem.id == "bodyTotalTPS") {
|
||||||
|
if (isGraph($(elem).find('.flot-chart-content')) == false) {
|
||||||
|
refreshTotalTPS(true);
|
||||||
|
}
|
||||||
|
document.location.href="#totalTPS";
|
||||||
} else if (elem.id == "bodyResponseTimeVsRequest") {
|
} else if (elem.id == "bodyResponseTimeVsRequest") {
|
||||||
if (isGraph($(elem).find('.flot-chart-content')) == false) {
|
if (isGraph($(elem).find('.flot-chart-content')) == false) {
|
||||||
refreshResponseTimeVsRequest();
|
refreshResponseTimeVsRequest();
|
||||||
|
|
@ -1471,6 +1554,9 @@ function toggleAll(id, checked){
|
||||||
} else if ( id == "choicesTransactionsPerSecond"){
|
} else if ( id == "choicesTransactionsPerSecond"){
|
||||||
choiceContainer = $("#choicesTransactionsPerSecond");
|
choiceContainer = $("#choicesTransactionsPerSecond");
|
||||||
refreshTransactionsPerSecond(false);
|
refreshTransactionsPerSecond(false);
|
||||||
|
} else if ( id == "choicesTotalTPS"){
|
||||||
|
choiceContainer = $("#choicesTotalTPS");
|
||||||
|
refreshTotalTPS(false);
|
||||||
} else if ( id == "choicesResponseTimeVsRequest"){
|
} else if ( id == "choicesResponseTimeVsRequest"){
|
||||||
choiceContainer = $("#choicesResponseTimeVsRequest");
|
choiceContainer = $("#choicesResponseTimeVsRequest");
|
||||||
refreshResponseTimeVsRequest();
|
refreshResponseTimeVsRequest();
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,9 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="Throughput.html#transactionsPerSecond" onclick="$('#bodyTransactionsPerSecond').collapse('show');">Transactions Per Second</a>
|
<a href="Throughput.html#transactionsPerSecond" onclick="$('#bodyTransactionsPerSecond').collapse('show');">Transactions Per Second</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="Throughput.html#totalTPS" onclick="$('#bodyTotalTPS').collapse('show');">Total Transactions Per Second</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="Throughput.html#responseTimeVsRequest" onclick="$('#bodyResponseTimeVsRequest').collapse('show');">Response Time Vs Request</a>
|
<a href="Throughput.html#responseTimeVsRequest" onclick="$('#bodyResponseTimeVsRequest').collapse('show');">Response Time Vs Request</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -281,6 +284,52 @@
|
||||||
<!-- /.panel -->
|
<!-- /.panel -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-12 portlet" id="totalTPS">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading portlet-header">
|
||||||
|
<i class="fa fa-bar-chart-o fa-fw"> </i> <span type="button" class="dropdown-toggle click-title span-title" data-toggle="collapse" href="#bodyTotalTPS" aria-expanded="true" aria-controls="bodyTotalTPS">Total Transactions Per Second</span>
|
||||||
|
<div class="pull-right">
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-link btn-xs">
|
||||||
|
<i class="glyphicon glyphicon-resize-vertical"></i>
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-link btn-xs dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fa fa-wrench"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-user">
|
||||||
|
<li><a href="#totalTPS" onClick="checkAll('choicesTotalTPS');">Display all samples</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#totalTPS" onClick="uncheckAll('choicesTotalTPS');">Hide all samples</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#totalTPS" onclick="exportToPNG('flotTotalTPS', this);">Save as PNG</a></li>
|
||||||
|
</ul>
|
||||||
|
<button type="button" class="btn btn-link btn-xs dropdown-toggle" data-toggle="collapse" href="#bodyTotalTPS" aria-expanded="true" aria-controls="bodyTotalTPS">
|
||||||
|
<i class="fa fa-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.panel-heading -->
|
||||||
|
<div class="collapse out portlet-content" id="bodyTotalTPS">
|
||||||
|
<div class="panel-body" id="collapseTotalTPS">
|
||||||
|
<div class="flot-chart">
|
||||||
|
<div class="flot-chart-content" id="flotTotalTPS" style="float: left; width:80%;"></div>
|
||||||
|
<div style="float:left;margin-left:5px">
|
||||||
|
<p>Zoom :</p>
|
||||||
|
<div id="overviewTotalTPS" style="width:190px;height:100px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer" id="footerTotalTPS">
|
||||||
|
<p id="legendTotalTPS" hidden></p>
|
||||||
|
<ul id="choicesTotalTPS" class="legend"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.panel-body -->
|
||||||
|
</div>
|
||||||
|
<!-- /.panel -->
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-12 portlet" id="responseTimeVsRequest">
|
<div class="col-lg-12 portlet" id="responseTimeVsRequest">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading portlet-header">
|
<div class="panel-heading portlet-header">
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,11 @@ jmeter.reportgenerator.graph.codesPerSecond.title=Codes Per Second
|
||||||
jmeter.reportgenerator.graph.codesPerSecond.exclude_controllers=true
|
jmeter.reportgenerator.graph.codesPerSecond.exclude_controllers=true
|
||||||
jmeter.reportgenerator.graph.codesPerSecond.property.set_granularity=${jmeter.reportgenerator.overall_granularity}
|
jmeter.reportgenerator.graph.codesPerSecond.property.set_granularity=${jmeter.reportgenerator.overall_granularity}
|
||||||
|
|
||||||
|
# Total TPS Per Second graph definition
|
||||||
|
jmeter.reportgenerator.graph.totalTPS.classname=org.apache.jmeter.report.processor.graph.impl.TotalTPSGraphConsumer
|
||||||
|
jmeter.reportgenerator.graph.totalTPS.title=Total Transactions Per Second
|
||||||
|
jmeter.reportgenerator.graph.totalTPS.property.set_granularity=${jmeter.reportgenerator.overall_granularity}
|
||||||
|
|
||||||
# Transactions Per Second graph definition
|
# Transactions Per Second graph definition
|
||||||
jmeter.reportgenerator.graph.transactionsPerSecond.classname=org.apache.jmeter.report.processor.graph.impl.TransactionsPerSecondGraphConsumer
|
jmeter.reportgenerator.graph.transactionsPerSecond.classname=org.apache.jmeter.report.processor.graph.impl.TransactionsPerSecondGraphConsumer
|
||||||
jmeter.reportgenerator.graph.transactionsPerSecond.title=Transactions Per Second
|
jmeter.reportgenerator.graph.transactionsPerSecond.title=Transactions Per Second
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.apache.jmeter.report.processor.graph.impl;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.jmeter.report.core.Sample;
|
||||||
|
import org.apache.jmeter.report.processor.ListResultData;
|
||||||
|
import org.apache.jmeter.report.processor.MapResultData;
|
||||||
|
import org.apache.jmeter.report.processor.TimeRateAggregatorFactory;
|
||||||
|
import org.apache.jmeter.report.processor.graph.AbstractGraphConsumer;
|
||||||
|
import org.apache.jmeter.report.processor.graph.AbstractOverTimeGraphConsumer;
|
||||||
|
import org.apache.jmeter.report.processor.graph.AbstractSeriesSelector;
|
||||||
|
import org.apache.jmeter.report.processor.graph.CountValueSelector;
|
||||||
|
import org.apache.jmeter.report.processor.graph.GroupInfo;
|
||||||
|
import org.apache.jmeter.report.processor.graph.SeriesData;
|
||||||
|
import org.apache.jmeter.report.processor.graph.TimeStampKeysSelector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class TotalTPSGraphConsumer provides a graph to visualize transactions
|
||||||
|
* rate per second.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public class TotalTPSGraphConsumer extends AbstractOverTimeGraphConsumer {
|
||||||
|
|
||||||
|
private static final String STATUS_SERIES_FORMAT = "%s-%s";
|
||||||
|
private static final String SUCCESS_SERIES_SUFFIX = "success";
|
||||||
|
private static final String FAILURE_SERIES_SUFFIX = "failure";
|
||||||
|
private static final String TRANSACTION_SUCCESS_LABEL = String.format(STATUS_SERIES_FORMAT, "Transaction", SUCCESS_SERIES_SUFFIX);
|
||||||
|
private static final String TRANSACTION_FAILURE_LABEL = String.format(STATUS_SERIES_FORMAT, "Transaction", FAILURE_SERIES_SUFFIX);
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.apache.jmeter.report.csv.processor.impl.AbstractOverTimeGraphConsumer
|
||||||
|
* #createTimeStampKeysSelector()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected TimeStampKeysSelector createTimeStampKeysSelector() {
|
||||||
|
TimeStampKeysSelector keysSelector = new TimeStampKeysSelector();
|
||||||
|
keysSelector.setSelectBeginTime(false);
|
||||||
|
return keysSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.apache.jmeter.report.csv.processor.impl.AbstractGraphConsumer#
|
||||||
|
* createGroupInfos()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Map<String, GroupInfo> createGroupInfos() {
|
||||||
|
Map<String, GroupInfo> groupInfos = new HashMap<>(1);
|
||||||
|
groupInfos.put(AbstractGraphConsumer.DEFAULT_GROUP,
|
||||||
|
new GroupInfo(new TimeRateAggregatorFactory(), new AbstractSeriesSelector(true) {
|
||||||
|
@Override
|
||||||
|
public Iterable<String> select(Sample sample) {
|
||||||
|
return Arrays.asList(sample.getSuccess() ? TRANSACTION_SUCCESS_LABEL : TRANSACTION_FAILURE_LABEL);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// We include Transaction Controller results
|
||||||
|
new CountValueSelector(false), false, false));
|
||||||
|
return groupInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.apache.jmeter.report.csv.processor.impl.AbstractOverTimeGraphConsumer
|
||||||
|
* #setGranularity(long)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setGranularity(long granularity) {
|
||||||
|
super.setGranularity(granularity);
|
||||||
|
// Override the granularity of the aggregators factory
|
||||||
|
((TimeRateAggregatorFactory) getGroupInfos().get(AbstractGraphConsumer.DEFAULT_GROUP).getAggregatorFactory())
|
||||||
|
.setGranularity(granularity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeExtraResults(MapResultData parentResult) {
|
||||||
|
super.initializeExtraResults(parentResult);
|
||||||
|
String[] seriesLabels = new String[]{
|
||||||
|
TRANSACTION_SUCCESS_LABEL, TRANSACTION_FAILURE_LABEL
|
||||||
|
};
|
||||||
|
initializeSeries(parentResult, seriesLabels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initializeSeries(MapResultData parentResult, String[] series) {
|
||||||
|
ListResultData listResultData = (ListResultData) parentResult.getResult("series");
|
||||||
|
for (int i = 0; i < series.length; i++) {
|
||||||
|
listResultData.addResult(create(series[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MapResultData create(String serie) {
|
||||||
|
GroupInfo groupInfo = getGroupInfos().get(AbstractGraphConsumer.DEFAULT_GROUP);
|
||||||
|
SeriesData seriesData = new SeriesData(groupInfo.getAggregatorFactory(),
|
||||||
|
groupInfo.enablesAggregatedKeysSeries(), false,
|
||||||
|
groupInfo.enablesOverallSeries());
|
||||||
|
return createSerieResult(serie, seriesData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -130,6 +130,7 @@ this behaviour, set <code>httpclient.reset_state_on_thread_group_iteration=false
|
||||||
<h3>Report / Dashboard</h3>
|
<h3>Report / Dashboard</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><bug>62243</bug>Dashboard : make option "<code>--forceDeleteResultFile</code>"/"<code>-f</code>" option delete folder referenced by "<code>-o</code>" option</li>
|
<li><bug>62243</bug>Dashboard : make option "<code>--forceDeleteResultFile</code>"/"<code>-f</code>" option delete folder referenced by "<code>-o</code>" option</li>
|
||||||
|
<li><bug>62367</bug>HTML Report Generator: Add Graph Total Transactions per Second. Contributed mainly by Martha Laks (laks.martha at gmail.com)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>General</h3>
|
<h3>General</h3>
|
||||||
|
|
@ -245,6 +246,7 @@ this behaviour, set <code>httpclient.reset_state_on_thread_group_iteration=false
|
||||||
<li>Imane Ankhila (iankhila at ahlane.net)</li>
|
<li>Imane Ankhila (iankhila at ahlane.net)</li>
|
||||||
<li>jffagot05 (jffagot05 at gmail.com)</li>
|
<li>jffagot05 (jffagot05 at gmail.com)</li>
|
||||||
<li>Perze Ababa (perze.ababa at gmail.com)</li>
|
<li>Perze Ababa (perze.ababa at gmail.com)</li>
|
||||||
|
<li>Martha Laks (laks.martha at gmail.com)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>We also thank bug reporters who helped us improve JMeter.</p>
|
<p>We also thank bug reporters who helped us improve JMeter.</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue