Skip to content

Commit 4c6825c

Browse files
committed
Refactored chart JS code.
Made charts support resizing.
1 parent 3328582 commit 4c6825c

File tree

3 files changed

+93
-171
lines changed

3 files changed

+93
-171
lines changed

locust/static/chart.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
(function() {
2+
class LocustLineChart {
3+
constructor(container, title, unit) {
4+
this.container = $(container);
5+
this.title = title;
6+
7+
this.element = $('<div class="chart"></div>').css("width", "100%").appendTo(container);
8+
this.data = [];
9+
this.dates = [];
10+
11+
this.chart = echarts.init(this.element[0], 'vintage');
12+
this.chart.setOption({
13+
title: {
14+
text: this.title,
15+
x: 10,
16+
y: 10,
17+
},
18+
tooltip: {
19+
trigger: 'axis',
20+
formatter: function (params) {
21+
if (!!params && params.length > 0 && !!params[0].value) {
22+
var param = params[0];
23+
return param.name + ': ' + param.value + ' ' + unit;
24+
} else {
25+
return "No data";
26+
}
27+
},
28+
axisPointer: {
29+
animation: true
30+
}
31+
},
32+
xAxis: {
33+
type: 'category',
34+
splitLine: {
35+
show: false
36+
},
37+
data: this.dates,
38+
},
39+
yAxis: {
40+
type: 'value',
41+
boundaryGap: [0, '100%'],
42+
splitLine: {
43+
show: false
44+
}
45+
},
46+
series: [{
47+
name: 'RPS',
48+
type: 'line',
49+
showSymbol: true,
50+
hoverAnimation: false,
51+
data: this.data,
52+
}],
53+
grid: {x:60, y:70, x2:40, y2:40},
54+
})
55+
}
56+
57+
addValue(value) {
58+
value = Math.round(value * 100) / 100;
59+
this.dates.push(new Date().toLocaleTimeString());
60+
this.data.push(value);
61+
this.chart.setOption({
62+
xAxis: {
63+
data: this.dates,
64+
},
65+
series: [{
66+
data: this.data,
67+
}]
68+
});
69+
}
70+
71+
resize() {
72+
this.chart.resize();
73+
}
74+
}
75+
window.LocustLineChart = LocustLineChart;
76+
})();

locust/static/locust.js

Lines changed: 15 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ $(".close_link").click(function(event) {
3838

3939
var alternate = false;
4040

41-
$("ul.tabs").tabs("div.panes > div");
41+
$("ul.tabs").tabs("div.panes > div").on("onClick", function(event) {
42+
if (event.target == $(".chart-tab-link")[0]) {
43+
// trigger resizing of charts
44+
rpsChart.resize();
45+
responseTimeChart.resize();
46+
}
47+
});
4248

4349
var stats_tpl = $('#stats-template');
4450
var errors_tpl = $('#errors-template');
@@ -108,174 +114,9 @@ $(".stats_label").click(function(event) {
108114
$('#errors tbody').jqoteapp(errors_tpl, (report.errors).sort(sortBy(sortAttribute, desc)));
109115
});
110116

111-
112-
var charts = {}
113-
114-
function initChart(stat) {
115-
var width = $(".main").width();
116-
var rps_element = $('<div class="chart"></div>').css("width", width);
117-
var avt_element = $('<div class="chart"></div>').css("width", width);
118-
rps_element.appendTo("#charts .charts-container");
119-
avt_element.appendTo("#charts .charts-container");
120-
121-
var date = [];
122-
var rps_data = [];
123-
var avt_data = [];
124-
125-
now = new Date().toLocaleTimeString();
126-
date.push(now);
127-
rps_data.push({
128-
"name": now,
129-
"value": Math.round(stat.current_rps*100)/100
130-
});
131-
132-
avt_data.push({
133-
"name": now,
134-
"value": Math.round(stat.avg_response_time)
135-
});
136-
137-
var gridSettings = {x:60, y:70, x2:40, y2:40};
138-
139-
var rps_chart = echarts.init(rps_element.get(0), 'vintage');
140-
rps_chart.setOption({
141-
title: {
142-
text: 'Total Requests per Second',
143-
x: 10,
144-
y: 10,
145-
},
146-
tooltip: {
147-
trigger: 'axis',
148-
formatter: function (params) {
149-
param = params[0];
150-
return param.name + ': ' + param.value + ' reqs/s';
151-
},
152-
axisPointer: {
153-
animation: true
154-
}
155-
},
156-
xAxis: {
157-
type: 'category',
158-
splitLine: {
159-
show: false
160-
},
161-
data: date
162-
},
163-
yAxis: {
164-
type: 'value',
165-
boundaryGap: [0, '100%'],
166-
splitLine: {
167-
show: false
168-
}
169-
},
170-
series: [{
171-
name: 'RPS',
172-
type: 'line',
173-
showSymbol: false,
174-
hoverAnimation: false,
175-
data: rps_data
176-
}],
177-
grid: gridSettings,
178-
});
179-
180-
var avt_chart = echarts.init(avt_element.get(0), 'vintage');
181-
avt_chart.setOption({
182-
title: {
183-
text: 'Average Response Time',
184-
x: 10,
185-
y: 10,
186-
},
187-
tooltip: {
188-
trigger: 'axis',
189-
formatter: function (params) {
190-
param = params[0];
191-
return param.name + ': ' + param.value + 'ms';
192-
},
193-
axisPointer: {
194-
animation: true
195-
}
196-
},
197-
xAxis: {
198-
type: 'category',
199-
splitLine: {
200-
show: false
201-
},
202-
data: date
203-
},
204-
yAxis: {
205-
type: 'value',
206-
boundaryGap: [0, '100%'],
207-
splitLine: {
208-
show: false
209-
}
210-
},
211-
series: [{
212-
name: 'AVT',
213-
type: 'line',
214-
showSymbol: false,
215-
hoverAnimation: false,
216-
data: avt_data
217-
}],
218-
grid: gridSettings,
219-
});
220-
221-
charts[stat.name] = {};
222-
charts[stat.name]["date"] = date;
223-
charts[stat.name]["rps_chart"] = rps_chart;
224-
charts[stat.name]["rps_data"] = rps_data;
225-
charts[stat.name]["avt_chart"] = avt_chart;
226-
charts[stat.name]["avt_data"] = avt_data;
227-
228-
}
229-
230-
function updateCharts(stats) {
231-
var rps_chart, rps_data, now, date, avt_chart, avt_data;
232-
233-
$.each(stats, function(index, stat){
234-
if (stat.name != "Total") {
235-
// Only render charts for the total data
236-
return;
237-
}
238-
if (stat.name in charts) {
239-
now = new Date().toLocaleTimeString();
240-
date = charts[stat.name]["date"];
241-
date.push(now);
242-
243-
rps_chart = charts[stat.name]["rps_chart"];
244-
rps_data = charts[stat.name]["rps_data"];
245-
rps_data.push({
246-
"name": now,
247-
"value": Math.round(stat.current_rps*100)/100
248-
});
249-
rps_chart.setOption({
250-
xAxis: {
251-
data: date
252-
},
253-
series: [{
254-
data: rps_data
255-
}]
256-
});
257-
258-
avt_chart = charts[stat.name]["avt_chart"];
259-
avt_data = charts[stat.name]["avt_data"];
260-
avt_data.push({
261-
"name": now,
262-
"value": Math.round(stat.avg_response_time)
263-
});
264-
265-
avt_chart.setOption({
266-
xAxis: {
267-
data: date
268-
},
269-
series: [{
270-
data: avt_data
271-
}]
272-
});
273-
} else {
274-
initChart(stat);
275-
}
276-
});
277-
}
278-
117+
// init charts
118+
var rpsChart = new LocustLineChart($(".charts-container"), "Total Requests per Second", "reqs/s");
119+
var responseTimeChart = new LocustLineChart($(".charts-container"), "Average Response Time", "ms");
279120

280121
function updateStats() {
281122
$.get('/stats/requests', function (data) {
@@ -302,7 +143,11 @@ function updateStats() {
302143
$('#errors tbody').jqoteapp(errors_tpl, (report.errors).sort(sortBy(sortAttribute, desc)));
303144

304145
if (report.state !== "stopped"){
305-
updateCharts(sortedStats);
146+
// get total stats row
147+
var total = report.stats[report.stats.length-1];
148+
// update charts
149+
rpsChart.addValue(total.current_rps);
150+
responseTimeChart.addValue(total.avg_response_time);
306151
}
307152

308153
setTimeout(updateStats, 2000);

locust/templates/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ <h2>Change the locust count</h2>
8484
<div class="status" id="status">
8585
<ul class="tabs">
8686
<li><a href="#">Statistics</a></li>
87-
<li><a href="#">Charts</a></li>
87+
<li><a href="#" class="chart-tab-link">Charts</a></li>
8888
<li><a href="#">Failures</a></li>
8989
<li><a href="#">Exceptions</a></li>
9090
<li><a href="#">Download Data</a></li>
@@ -230,6 +230,7 @@ <h1>Version</h1>
230230
<% alternate = !alternate; %>
231231
]]>
232232
</script>
233+
<script type="text/javascript" src="/static/chart.js"></script>
233234
<script type="text/javascript" src="/static/locust.js"></script>
234235
</body>
235236
</html>

0 commit comments

Comments
 (0)