This commit is contained in:
chenjianxing 2020-04-07 17:57:08 +08:00
commit 2364fac57b
3 changed files with 162 additions and 155 deletions

View File

@ -12,10 +12,8 @@ import io.metersphere.engine.EngineContext;
import io.metersphere.engine.EngineFactory; import io.metersphere.engine.EngineFactory;
import io.metersphere.engine.docker.request.BaseRequest; import io.metersphere.engine.docker.request.BaseRequest;
import io.metersphere.engine.docker.request.TestRequest; import io.metersphere.engine.docker.request.TestRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -83,16 +81,6 @@ public class DockerTestEngine extends AbstractEngine {
testRequest.setImage(JMETER_IMAGE); testRequest.setImage(JMETER_IMAGE);
testRequest.setTestData(context.getTestData()); testRequest.setTestData(context.getTestData());
// todo 判断测试状态
String taskStatusUri = String.format(BASE_URL + "/jmeter/task/status/" + testId, nodeIp, port);
List containerList = restTemplate.postForObject(taskStatusUri, testRequest, List.class);
for (int i = 0; i < containerList.size(); i++) {
HashMap h = (HashMap) containerList.get(i);
if (StringUtils.equals((String) h.get("State"), "running")) {
MSException.throwException("The test is running!");
}
}
restTemplate.postForObject(uri, testRequest, String.class); restTemplate.postForObject(uri, testRequest, String.class);
} }

View File

@ -8,7 +8,6 @@ import io.metersphere.report.base.*;
import io.metersphere.report.dto.ErrorsTop5DTO; import io.metersphere.report.dto.ErrorsTop5DTO;
import io.metersphere.report.dto.RequestStatisticsDTO; import io.metersphere.report.dto.RequestStatisticsDTO;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.text.DecimalFormat; import java.text.DecimalFormat;
@ -20,7 +19,6 @@ import java.util.stream.Collectors;
public class JtlResolver { public class JtlResolver {
private static final Integer ERRORS_TOP_SIZE = 5; private static final Integer ERRORS_TOP_SIZE = 5;
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static List<Metric> resolver(String jtlString) { private static List<Metric> resolver(String jtlString) {
HeaderColumnNameMappingStrategy<Metric> ms = new HeaderColumnNameMappingStrategy<>(); HeaderColumnNameMappingStrategy<Metric> ms = new HeaderColumnNameMappingStrategy<>();
@ -378,27 +376,37 @@ public class JtlResolver {
entries.sort(JtlResolver::sortByDate); entries.sort(JtlResolver::sortByDate);
List<String> resTimeList = new ArrayList<>(); List<String> resTimeList = new ArrayList<>();
List<String> users = new ArrayList<>();
List<String> timestampList = new ArrayList<>(); List<String> timestampList = new ArrayList<>();
for (Map.Entry<String, List<Metric>> entry : entries) { for (Map.Entry<String, List<Metric>> entry : entries) {
List<Metric> metricList = entry.getValue(); List<Metric> metricList = entry.getValue();
Map<String, List<Metric>> metricsMap = metricList.stream().collect(Collectors.groupingBy(Metric::getThreadName));
int maxUsers = metricsMap.size();
int sumElapsedTime = metricList.stream().mapToInt(metric -> Integer.parseInt(metric.getElapsed())).sum(); int sumElapsedTime = metricList.stream().mapToInt(metric -> Integer.parseInt(metric.getElapsed())).sum();
timestampList.add(entry.getKey()); timestampList.add(entry.getKey());
users.add(String.valueOf(maxUsers));
resTimeList.add(String.valueOf(sumElapsedTime / metricList.size())); resTimeList.add(String.valueOf(sumElapsedTime / metricList.size()));
} }
Map<String, Object> resultMap = new HashMap<>(2);
resultMap.put("users", users);
resultMap.put("resTime", resTimeList);
JSONObject serices = new JSONObject(resultMap);
chartsData.setxAxis(StringUtils.join(",", timestampList)); chartsData.setxAxis(StringUtils.join(",", timestampList));
chartsData.setSerices(StringUtils.join(",", resTimeList)); chartsData.setSerices(serices.toString());
return chartsData; return chartsData;
} }
private static String stampToDate(String s) { private static String stampToDate(String timeStamp) {
long lt = Long.parseLong(s); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long lt = Long.parseLong(timeStamp);
Date date = new Date(lt); Date date = new Date(lt);
return simpleDateFormat.format(date); return simpleDateFormat.format(date);
} }
private static int sortByDate(Map.Entry<String, List<Metric>> map1, Map.Entry<String, List<Metric>> map2) { private static int sortByDate(Map.Entry<String, List<Metric>> map1, Map.Entry<String, List<Metric>> map2) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date1 = null, date2 = null; Date date1 = null, date2 = null;
try { try {
date1 = simpleDateFormat.parse(map1.getKey()); date1 = simpleDateFormat.parse(map1.getKey());
@ -406,6 +414,15 @@ public class JtlResolver {
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
} }
return (int) (Objects.requireNonNull(date1).getTime() - Objects.requireNonNull(date2).getTime());
Long time1 = date1.getTime();
Long time2 = date2.getTime();
if (time1.equals(time2)) {
return 0;
} else {
return time1 > time2 ? 1 : -1;
}
} }
} }

View File

@ -59,10 +59,10 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<chart ref="chart1" :options="option" :autoresize="true"></chart> <chart ref="chart1" :options="loadOption" :autoresize="true"></chart>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<chart ref="chart2" :options="option2" :autoresize="true"></chart> <chart ref="chart2" :options="resOption" :autoresize="true"></chart>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -79,84 +79,8 @@
avgResponseTime: "0", avgResponseTime: "0",
responseTime90: "0", responseTime90: "0",
avgBandwidth: "0", avgBandwidth: "0",
option: { loadOption: {},
legend: { resOption: {}
top: 20,
data: ['Users', 'Hits/s', 'Error(s)']
},
xAxis: {
type: 'category',
},
yAxis: [{
name: 'User',
type: 'value',
min: 0,
splitNumber: 5,
// interval: 10 / 5
},
{
name: 'Hits/s',
type: 'value',
splitNumber: 5,
min: 0,
// max: 5,
// interval: 5 / 5
}
],
series: [
{
name: 'Users',
color: '#0CA74A',
type: 'line',
yAxisIndex: 0
},
{
name: 'Hits/s',
color: '#65A2FF',
type: 'line',
yAxisIndex: 1
},
{
name: 'Error(s)',
color: '#E6113C',
type: 'line',
yAxisIndex: 1
}
]
},
option2: {
legend: {
top: 20,
data: ['Users', 'Response Time']
},
xAxis: {
type: 'category',
data: []
},
yAxis: [{
name: 'User',
type: 'value',
},
{
name: 'Response Time',
type: 'value'
}
],
series: [
{
name: 'Users',
color: '#0CA74A',
data: [],
type: 'line',
},
{
name: 'Response Time',
color: '#99743C',
data: [],
type: 'line',
}
]
}
} }
}, },
methods: { methods: {
@ -172,7 +96,108 @@
}) })
this.$get("/report/content/load_chart/" + this.id, res => { this.$get("/report/content/load_chart/" + this.id, res => {
let data = res.data; let data = res.data;
this.option = this.generateOption(data); let loadOption = {
title: {
text: 'Load',
left: 'center',
top: 20,
textStyle: {
color: '#65A2FF'
},
},
legend: {
bottom: 10,
data: ['Users', 'Hits/s', 'Error(s)']
},
xAxis: {
type: 'category',
},
yAxis: [{
name: 'User',
type: 'value',
min: 0,
splitNumber: 5,
// interval: 10 / 5
},
{
name: 'Hits/s',
type: 'value',
splitNumber: 5,
min: 0,
// max: 5,
// interval: 5 / 5
}
],
series: [
{
name: 'Users',
color: '#0CA74A',
type: 'line',
yAxisIndex: 0
},
{
name: 'Hits/s',
color: '#65A2FF',
type: 'line',
yAxisIndex: 1
},
{
name: 'Error(s)',
color: '#E6113C',
type: 'line',
yAxisIndex: 1
}
]
}
this.loadOption = this.generateLoadOption(loadOption, data);
})
this.$get("/report/content/res_chart/" + this.id, res => {
let data = res.data;
let resOption = {
title: {
text: 'Response Time',
left: 'center',
top: 20,
textStyle: {
color: '#99743C'
},
},
legend: {
bottom: 10,
data: ['Users', 'Response Time']
},
xAxis: {
type: 'category'
},
yAxis: [{
name: 'User',
type: 'value',
splitNumber: 5,
min: 0
},
{
name: 'Response Time',
type: 'value',
splitNumber: 5,
min: 0
}
],
series: [
{
name: 'Users',
color: '#0CA74A',
type: 'line',
yAxisIndex: 0
},
{
name: 'Response Time',
color: '#99743C',
type: 'line',
yAxisIndex: 1
}
]
}
this.resOption = this.generateResponseOption(resOption, data);
}) })
}, },
_objToStrMap(obj){ _objToStrMap(obj){
@ -185,55 +210,10 @@
_jsonToMap(jsonStr){ _jsonToMap(jsonStr){
return this._objToStrMap(JSON.parse(jsonStr)); return this._objToStrMap(JSON.parse(jsonStr));
}, },
generateOption(data) { generateLoadOption(loadOption, data) {
let option = {
legend: {
top: 20,
data: ['Users', 'Hits/s', 'Error(s)']
},
xAxis: {
type: 'category',
},
yAxis: [{
name: 'User',
type: 'value',
min: 0,
splitNumber: 5,
// interval: 10 / 5
},
{
name: 'Hits/s',
type: 'value',
splitNumber: 5,
min: 0,
// max: 5,
// interval: 5 / 5
}
],
series: [
{
name: 'Users',
color: '#0CA74A',
type: 'line',
yAxisIndex: 0
},
{
name: 'Hits/s',
color: '#65A2FF',
type: 'line',
yAxisIndex: 1
},
{
name: 'Error(s)',
color: '#E6113C',
type: 'line',
yAxisIndex: 1
}
]
}
let map = this._jsonToMap(data.serices); let map = this._jsonToMap(data.serices);
let xAxis = data.xAxis; let xAxis = data.xAxis;
this.$set(option.xAxis, "data", xAxis.split(',')); this.$set(loadOption.xAxis, "data", xAxis.split(','));
let user = map.get("users").slice(0); let user = map.get("users").slice(0);
let hit = map.get("hits").slice(0); let hit = map.get("hits").slice(0);
user.sort(function (a,b) { user.sort(function (a,b) {
@ -242,16 +222,38 @@
hit.sort(function (a,b) { hit.sort(function (a,b) {
return parseFloat(a) - parseFloat(b); return parseFloat(a) - parseFloat(b);
}) })
this.$set(option.yAxis[0], "max",user[user.length-1]); this.$set(loadOption.yAxis[0], "max",user[user.length-1]);
this.$set(option.yAxis[0], "interval", user[user.length-1]/5); this.$set(loadOption.yAxis[0], "interval", user[user.length-1]/5);
this.$set(option.yAxis[1], "max", hit[hit.length-1]); this.$set(loadOption.yAxis[1], "max", hit[hit.length-1]);
this.$set(option.yAxis[1], "interval", hit[hit.length-1]/5); this.$set(loadOption.yAxis[1], "interval", hit[hit.length-1]/5);
this.$set(option.series[0], "data", map.get("users")); this.$set(loadOption.series[0], "data", map.get("users"));
this.$set(option.series[1], "data", map.get("hits")); this.$set(loadOption.series[1], "data", map.get("hits"));
this.$set(option.series[2], "data", map.get("errors")); this.$set(loadOption.series[2], "data", map.get("errors"));
return option; return loadOption;
} },
generateResponseOption(resOption, data) {
let map = this._jsonToMap(data.serices);
let user = map.get("users").slice(0);
let res = map.get("resTime").slice(0);
user.sort(function (a,b) {
return parseInt(a) - parseInt(b);
})
res.sort(function (a,b) {
return parseFloat(a) - parseFloat(b);
})
this.$set(resOption.yAxis[0], "max",user[user.length-1]);
this.$set(resOption.yAxis[0], "interval", user[user.length-1]/5);
this.$set(resOption.yAxis[1], "max", res[res.length-1]);
this.$set(resOption.yAxis[1], "interval", res[res.length-1]/5);
let xAxis = data.xAxis;
this.$set(resOption.xAxis, "data", xAxis.split(','));
this.$set(resOption.series[0], "data", map.get("users"));
this.$set(resOption.series[1], "data", map.get("resTime"));
return resOption;
},
}, },
watch: { watch: {
status() { status() {