Merge branch 'dev' of https://github.com/fit2cloudrd/metersphere-server into dev
This commit is contained in:
commit
968af6614f
|
@ -1,5 +1,16 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum FileType {
|
||||
JMX, CSV
|
||||
JMX(".jmx"), CSV(".csv");
|
||||
|
||||
// 保存后缀
|
||||
private String suffix;
|
||||
|
||||
FileType(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public String suffix() {
|
||||
return this.suffix;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum JmeterReportType {
|
||||
AggregateReport,
|
||||
SynthesisReport,
|
||||
ThreadsStateOverTime,
|
||||
BytesThroughputOverTime,
|
||||
HitsPerSecond,
|
||||
LatenciesOverTime,
|
||||
PerfMon,
|
||||
DbMon,
|
||||
JMXMon,
|
||||
ResponseCodesPerSecond,
|
||||
ResponseTimesDistribution,
|
||||
ResponseTimesOverTime,
|
||||
ResponseTimesPercentiles,
|
||||
ThroughputVsThreads,
|
||||
TimesVsThreads,
|
||||
TransactionsPerSecond,
|
||||
PageDataExtractorOverTime,
|
||||
MergeResults,
|
||||
}
|
|
@ -5,6 +5,7 @@ import io.fabric8.kubernetes.api.model.ConfigMap;
|
|||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.metersphere.base.domain.LoadTestWithBLOBs;
|
||||
import io.metersphere.commons.constants.FileType;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
|
@ -74,7 +75,7 @@ public class KubernetesTestEngine extends AbstractEngine {
|
|||
setName(configMapName);
|
||||
}});
|
||||
item.setData(new HashMap<String, String>() {{
|
||||
put(context.getTestId() + ".jmx", context.getContent());
|
||||
put(context.getTestId() + FileType.JMX.suffix(), context.getContent());
|
||||
if (MapUtils.isNotEmpty(context.getTestData())) {
|
||||
putAll(context.getTestData());
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import javax.xml.transform.TransformerFactory;
|
|||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class JmeterDocumentParser implements DocumentParser {
|
||||
|
@ -32,6 +33,7 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
private final static String CONFIG_TEST_ELEMENT = "ConfigTestElement";
|
||||
private final static String DNS_CACHE_MANAGER = "DNSCacheManager";
|
||||
private final static String ARGUMENTS = "Arguments";
|
||||
private final static String RESPONSE_ASSERTION = "ResponseAssertion";
|
||||
private EngineContext context;
|
||||
|
||||
@Override
|
||||
|
@ -87,6 +89,7 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
processCheckoutConfigTestElement(ele);
|
||||
processCheckoutDnsCacheManager(ele);
|
||||
processCheckoutArguments(ele);
|
||||
processCheckoutResponseAssertion(ele);
|
||||
} else if (nodeNameEquals(ele, CONCURRENCY_THREAD_GROUP)) {
|
||||
processConcurrencyThreadGroup(ele);
|
||||
processCheckoutTimer(ele);
|
||||
|
@ -107,13 +110,86 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
processDnsCacheManager(ele);
|
||||
} else if (nodeNameEquals(ele, ARGUMENTS)) {
|
||||
processArguments(ele);
|
||||
} else if (nodeNameEquals(ele, RESPONSE_ASSERTION)) {
|
||||
processResponseAssertion(ele);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processResponseAssertion(Element element) {
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node item = childNodes.item(i);
|
||||
if (item instanceof Element && nodeNameEquals(item, "collectionProp")) {
|
||||
removeChildren(item);
|
||||
Document document = item.getOwnerDocument();
|
||||
Object params = context.getProperty("statusCode");
|
||||
if (params instanceof List) {
|
||||
HashSet set = new HashSet((List) params);
|
||||
for (Object p : set) {
|
||||
element.appendChild(createStringProp(document, p.toString(), p.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processCheckoutResponseAssertion(Element element) {
|
||||
if (context.getProperty("statusCode") == null || JSON.parseArray(context.getProperty("statusCode").toString()).size() == 0) {
|
||||
return;
|
||||
}
|
||||
Document document = element.getOwnerDocument();
|
||||
|
||||
Node hashTree = element.getNextSibling();
|
||||
while (!(hashTree instanceof Element)) {
|
||||
hashTree = hashTree.getNextSibling();
|
||||
}
|
||||
|
||||
NodeList childNodes = hashTree.getChildNodes();
|
||||
for (int i = 0, l = childNodes.getLength(); i < l; i++) {
|
||||
Node item = childNodes.item(i);
|
||||
if (nodeNameEquals(item, RESPONSE_ASSERTION)) {
|
||||
// 如果已经存在,不再添加
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="50548">301</stringProp>
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">33</intProp>
|
||||
</ResponseAssertion>
|
||||
*/
|
||||
|
||||
// add class name
|
||||
Element responseAssertion = document.createElement(RESPONSE_ASSERTION);
|
||||
responseAssertion.setAttribute("guiclass", "AssertionGui");
|
||||
responseAssertion.setAttribute("testclass", "ResponseAssertion");
|
||||
responseAssertion.setAttribute("testname", "Response Assertion");
|
||||
responseAssertion.setAttribute("enabled", "true");
|
||||
Element collectionProp = document.createElement(COLLECTION_PROP);
|
||||
collectionProp.setAttribute("name", "Asserion.test_strings");
|
||||
//
|
||||
responseAssertion.appendChild(collectionProp);
|
||||
responseAssertion.appendChild(createStringProp(document, "Assertion.custom_message", ""));
|
||||
responseAssertion.appendChild(createStringProp(document, "Assertion.test_field", ""));
|
||||
responseAssertion.appendChild(createBoolProp(document, "Assertion.assume_success", false));
|
||||
responseAssertion.appendChild(createIntProp(document, "Assertion.test_type", 33));
|
||||
hashTree.appendChild(responseAssertion);
|
||||
hashTree.appendChild(document.createElement(HASH_TREE_ELEMENT));
|
||||
}
|
||||
|
||||
private void processCheckoutArguments(Element ele) {
|
||||
if (context.getProperty("params") == null || JSON.parseArray(context.getProperty("params").toString()).size() == 0) {
|
||||
return;
|
||||
}
|
||||
Node hashTree = ele.getNextSibling();
|
||||
while (!(hashTree instanceof Element)) {
|
||||
hashTree = hashTree.getNextSibling();
|
||||
|
@ -154,6 +230,9 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
}
|
||||
|
||||
private void processCheckoutDnsCacheManager(Element ele) {
|
||||
if (context.getProperty("domains") == null || JSON.parseArray(context.getProperty("domains").toString()).size() == 0) {
|
||||
return;
|
||||
}
|
||||
Node hashTree = ele.getNextSibling();
|
||||
while (!(hashTree instanceof Element)) {
|
||||
hashTree = hashTree.getNextSibling();
|
||||
|
@ -204,6 +283,9 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
}
|
||||
|
||||
private void processCheckoutConfigTestElement(Element ele) {
|
||||
if (context.getProperty("timeout") == null || StringUtils.isBlank(context.getProperty("timeout").toString())) {
|
||||
return;
|
||||
}
|
||||
Node hashTree = ele.getNextSibling();
|
||||
while (!(hashTree instanceof Element)) {
|
||||
hashTree = hashTree.getNextSibling();
|
||||
|
@ -438,6 +520,13 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
return tearDownSwitch;
|
||||
}
|
||||
|
||||
private Element createIntProp(Document document, String name, int value) {
|
||||
Element tearDownSwitch = document.createElement("intProp");
|
||||
tearDownSwitch.setAttribute("name", name);
|
||||
tearDownSwitch.appendChild(document.createTextNode(String.valueOf(value)));
|
||||
return tearDownSwitch;
|
||||
}
|
||||
|
||||
private void processBackendListener(Element backendListener) {
|
||||
KafkaProperties kafkaProperties = CommonBeanFactory.getBean(KafkaProperties.class);
|
||||
Document document = backendListener.getOwnerDocument();
|
||||
|
@ -557,7 +646,6 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
threadGroup.appendChild(createStringProp(document, "Hold", "12"));
|
||||
threadGroup.appendChild(createStringProp(document, "LogFilename", ""));
|
||||
threadGroup.appendChild(createStringProp(document, "Iterations", "1"));
|
||||
// todo 单位是S 要修改 成M
|
||||
threadGroup.appendChild(createStringProp(document, "Unit", "M"));
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -282,4 +284,69 @@ public class JtlResolver {
|
|||
return testOverview;
|
||||
}
|
||||
|
||||
|
||||
public static ChartsData getLoadChartData(String jtlString) {
|
||||
ChartsData data = new ChartsData();
|
||||
List<Metric> total = JtlResolver.resolver(jtlString);
|
||||
|
||||
////
|
||||
List<String> users = new ArrayList<>();
|
||||
List<String> hits = new ArrayList<>();
|
||||
List<String> erorrs = new ArrayList<>();
|
||||
List<String> timeList = new ArrayList<>();
|
||||
////
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
DecimalFormat df = new DecimalFormat("0.0");
|
||||
|
||||
total.sort(Comparator.comparing(metric -> Long.valueOf(metric.getTimestamp())));
|
||||
total.forEach(metric -> {
|
||||
metric.setTimestamp(stampToDate(metric.getTimestamp()));
|
||||
});
|
||||
|
||||
Map<String, List<Metric>> collect = total.stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
||||
List<Map.Entry<String, List<Metric>>> entries = new ArrayList<>(collect.entrySet());
|
||||
Collections.sort(entries, new Comparator<Map.Entry<String, List<Metric>>>() {
|
||||
@Override
|
||||
public int compare(Map.Entry<String, List<Metric>> t1, Map.Entry<String, List<Metric>> t2) {
|
||||
Date date1 = null,date2 = null;
|
||||
try {
|
||||
date1 = sdf.parse(t1.getKey());
|
||||
date2 = sdf.parse(t2.getKey());
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return (int) (date1.getTime() - date2.getTime());
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
int failSize = 0;
|
||||
Map.Entry<String, List<Metric>> map = entries.get(i);
|
||||
List<Metric> metrics = map.getValue();
|
||||
for (int j = 0; j < metrics.size(); j++) {
|
||||
Metric metric = metrics.get(j);
|
||||
String success = metric.getSuccess();
|
||||
if (!"true".equals(success)){
|
||||
failSize++;
|
||||
}
|
||||
}
|
||||
timeList.add(map.getKey());
|
||||
hits.add(String.valueOf(metrics.size()));
|
||||
users.add(String.valueOf(metrics.size()));
|
||||
erorrs.add(String.valueOf(failSize));
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
private static String stampToDate(String s){
|
||||
String res;
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
long lt = Long.parseLong(s);
|
||||
Date date = new Date(lt);
|
||||
res = simpleDateFormat.format(date);
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package io.metersphere.report.base;
|
||||
|
||||
public class ChartsData {
|
||||
|
||||
private String xAxis;
|
||||
private String yAxis;
|
||||
private String yAxis1;
|
||||
private String serices;
|
||||
|
||||
public String getxAxis() {
|
||||
return xAxis;
|
||||
}
|
||||
|
||||
public void setxAxis(String xAxis) {
|
||||
this.xAxis = xAxis;
|
||||
}
|
||||
|
||||
public String getyAxis() {
|
||||
return yAxis;
|
||||
}
|
||||
|
||||
public void setyAxis(String yAxis) {
|
||||
this.yAxis = yAxis;
|
||||
}
|
||||
|
||||
public String getyAxis1() {
|
||||
return yAxis1;
|
||||
}
|
||||
|
||||
public void setyAxis1(String yAxis1) {
|
||||
this.yAxis1 = yAxis1;
|
||||
}
|
||||
|
||||
public String getSerices() {
|
||||
return serices;
|
||||
}
|
||||
|
||||
public void setSerices(String serices) {
|
||||
this.serices = serices;
|
||||
}
|
||||
}
|
|
@ -113,7 +113,7 @@ CREATE TABLE IF NOT EXISTS `system_parameter` (
|
|||
|
||||
CREATE TABLE IF NOT EXISTS `test_resource` (
|
||||
`id` varchar(50) NOT NULL COMMENT 'Test resource ID',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT 'Test resource description',
|
||||
`test_resource_pool_id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT 'Test resource pool ID this test resource belongs to',
|
||||
`configuration` longtext COMMENT 'Test resource configuration',
|
||||
`status` varchar(64) NOT NULL COMMENT 'Test resource status',
|
||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||
|
@ -239,7 +239,7 @@ CREATE TABLE IF NOT EXISTS `test_plan` (
|
|||
`executor_match_rule` varchar(255) DEFAULT NULL COMMENT 'Executor match rule)',
|
||||
`tags` text COMMENT 'Test plan tags (JSON format)',
|
||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp'
|
||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
|
||||
PRIMARY KEY (`id`)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
|
@ -275,8 +275,8 @@ CREATE TABLE IF NOT EXISTS `test_case` (
|
|||
`remark` text DEFAULT NULL COMMENT 'Test case remark',
|
||||
`steps` text DEFAULT NULL COMMENT 'Test case steps (JSON format)',
|
||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp'
|
||||
PRIMARY KEY (`id`),
|
||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
|
||||
PRIMARY KEY (`id`)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
|
|
|
@ -204,7 +204,7 @@
|
|||
name: "PerformanceAdvancedConfig",
|
||||
data() {
|
||||
return {
|
||||
timeout: 10,
|
||||
timeout: 100,
|
||||
statusCode: [],
|
||||
domains: [],
|
||||
params: [],
|
||||
|
@ -339,12 +339,16 @@
|
|||
configurations() {
|
||||
this.domains.forEach(d => this.delOriginObject(d));
|
||||
this.params.forEach(d => this.delOriginObject(d));
|
||||
let statusCode = [];
|
||||
if (this.statusCodeStr) {
|
||||
statusCode = this.statusCodeStr.split(',');
|
||||
}
|
||||
return {
|
||||
timeout: this.timeout,
|
||||
statusCode: this.statusCodeStr.split(','),
|
||||
statusCode: statusCode,
|
||||
params: this.params,
|
||||
domains: this.domains,
|
||||
}
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
getFileMetadata(testPlan) {
|
||||
this.fileList = [];
|
||||
this.tableData = [];
|
||||
this.uploadList = [];
|
||||
this.result = this.$get(this.getFileMetadataPath + "/" + testPlan.id, response => {
|
||||
let files = response.data;
|
||||
|
||||
|
@ -184,10 +185,10 @@
|
|||
validConfig() {
|
||||
let newJmxNum = 0, oldJmxNum = 0;
|
||||
if (this.uploadList.length > 0) {
|
||||
newJmxNum = this.uploadList.filter(f => f.name.endsWith(".jmx")).length;
|
||||
newJmxNum = this.uploadList.filter(f => f.name.toLowerCase().endsWith(".jmx")).length;
|
||||
}
|
||||
if (this.fileList.length > 0) {
|
||||
oldJmxNum = this.fileList.filter(f => f.name.endsWith(".jmx")).length;
|
||||
oldJmxNum = this.fileList.filter(f => f.name.toLowerCase().endsWith(".jmx")).length;
|
||||
}
|
||||
if (newJmxNum + oldJmxNum !== 1) {
|
||||
this.$message({
|
||||
|
|
|
@ -86,11 +86,16 @@
|
|||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['12:40', '12:50', '13:00', '13:10', '13:20', '13:30', '13:40']
|
||||
data: ["10:22:01", "10:22:02", "10:22:04", "10:22:06",
|
||||
"10:22:07", "10:22:08", "10:22:09", "10:22:10", "10:22:11", "10:22:12"]
|
||||
},
|
||||
yAxis: [{
|
||||
name: 'User',
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: 30,
|
||||
splitNumber: 5,
|
||||
interval: 30 / 5
|
||||
},
|
||||
{
|
||||
name: 'Hits/s',
|
||||
|
@ -101,20 +106,23 @@
|
|||
{
|
||||
name: 'Users',
|
||||
color: '#0CA74A',
|
||||
data: [20, 40, 40, 40, 40, 40, 40],
|
||||
data: [6,9,10,15,1,10,25,19,15,2],
|
||||
type: 'line',
|
||||
yAxisIndex: 0
|
||||
},
|
||||
{
|
||||
name: 'Hits/s',
|
||||
color: '#65A2FF',
|
||||
data: [15, 38, 35, 39, 36, 37, 5],
|
||||
data: [1,1,1,1,1,1,1,1,1,1],
|
||||
type: 'line',
|
||||
yAxisIndex: 1
|
||||
},
|
||||
{
|
||||
name: 'Error(s)',
|
||||
color: '#E6113C',
|
||||
data: [0, 0, 0, 0, 0, 0, 0],
|
||||
data: [0,0,0,0,1,1,2,0,5,2],
|
||||
type: 'line',
|
||||
yAxisIndex: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -125,7 +133,8 @@
|
|||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['12:40', '12:50', '13:00', '13:10', '13:20', '13:30', '13:40']
|
||||
data: ["2020-03-25 10:22:01", "2020-03-25 10:22:02", "2020-03-25 10:22:04", "2020-03-25 10:22:06",
|
||||
"2020-03-25 10:22:07", "2020-03-25 10:22:08", "2020-03-25 10:22:09", "2020-03-25 10:22:10", "2020-03-25 10:22:11", "2020-03-25 10:22:12"]
|
||||
},
|
||||
yAxis: [{
|
||||
name: 'User',
|
||||
|
|
Loading…
Reference in New Issue