merge
This commit is contained in:
commit
6b8c059f99
|
@ -152,24 +152,12 @@
|
||||||
<artifactId>jmeter-plugins-casutg</artifactId>
|
<artifactId>jmeter-plugins-casutg</artifactId>
|
||||||
<version>2.9</version>
|
<version>2.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- jmeter graph -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>kg.apc</groupId>
|
|
||||||
<artifactId>jmeter-plugins-cmd</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>kg.apc</groupId>
|
|
||||||
<artifactId>jmeter-plugins-synthesis</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/kg.apc/jmeter-plugins-standard -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>kg.apc</groupId>
|
|
||||||
<artifactId>jmeter-plugins-standard</artifactId>
|
|
||||||
<version>1.4.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.opencsv</groupId>
|
||||||
|
<artifactId>opencsv</artifactId>
|
||||||
|
<version>5.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
|
|
@ -6,6 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
|
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
@SpringBootApplication(exclude = {QuartzAutoConfiguration.class})
|
@SpringBootApplication(exclude = {QuartzAutoConfiguration.class})
|
||||||
@ServletComponentScan
|
@ServletComponentScan
|
||||||
|
@ -14,4 +16,9 @@ public class Application {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(Application.class, args);
|
SpringApplication.run(Application.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate() {
|
||||||
|
return new RestTemplate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@ public class FileMetadata implements Serializable {
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
private String engine;
|
|
||||||
|
|
||||||
private Long createTime;
|
private Long createTime;
|
||||||
|
|
||||||
private Long updateTime;
|
private Long updateTime;
|
||||||
|
@ -43,14 +41,6 @@ public class FileMetadata implements Serializable {
|
||||||
this.type = type == null ? null : type.trim();
|
this.type = type == null ? null : type.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEngine() {
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEngine(String engine) {
|
|
||||||
this.engine = engine == null ? null : engine.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getCreateTime() {
|
public Long getCreateTime() {
|
||||||
return createTime;
|
return createTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,76 +314,6 @@ public class FileMetadataExample {
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andEngineIsNull() {
|
|
||||||
addCriterion("engine is null");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineIsNotNull() {
|
|
||||||
addCriterion("engine is not null");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineEqualTo(String value) {
|
|
||||||
addCriterion("engine =", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineNotEqualTo(String value) {
|
|
||||||
addCriterion("engine <>", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineGreaterThan(String value) {
|
|
||||||
addCriterion("engine >", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineGreaterThanOrEqualTo(String value) {
|
|
||||||
addCriterion("engine >=", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineLessThan(String value) {
|
|
||||||
addCriterion("engine <", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineLessThanOrEqualTo(String value) {
|
|
||||||
addCriterion("engine <=", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineLike(String value) {
|
|
||||||
addCriterion("engine like", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineNotLike(String value) {
|
|
||||||
addCriterion("engine not like", value, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineIn(List<String> values) {
|
|
||||||
addCriterion("engine in", values, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineNotIn(List<String> values) {
|
|
||||||
addCriterion("engine not in", values, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineBetween(String value1, String value2) {
|
|
||||||
addCriterion("engine between", value1, value2, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andEngineNotBetween(String value1, String value2) {
|
|
||||||
addCriterion("engine not between", value1, value2, "engine");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andCreateTimeIsNull() {
|
public Criteria andCreateTimeIsNull() {
|
||||||
addCriterion("create_time is null");
|
addCriterion("create_time is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||||
<result column="type" jdbcType="VARCHAR" property="type" />
|
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||||
<result column="engine" jdbcType="VARCHAR" property="engine" />
|
|
||||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||||
<result column="size" jdbcType="BIGINT" property="size" />
|
<result column="size" jdbcType="BIGINT" property="size" />
|
||||||
|
@ -69,7 +68,7 @@
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, name, type, engine, create_time, update_time, size
|
id, name, type, create_time, update_time, size
|
||||||
</sql>
|
</sql>
|
||||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.FileMetadataExample" resultMap="BaseResultMap">
|
<select id="selectByExample" parameterType="io.metersphere.base.domain.FileMetadataExample" resultMap="BaseResultMap">
|
||||||
select
|
select
|
||||||
|
@ -103,11 +102,11 @@
|
||||||
</delete>
|
</delete>
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.FileMetadata">
|
<insert id="insert" parameterType="io.metersphere.base.domain.FileMetadata">
|
||||||
insert into file_metadata (id, name, type,
|
insert into file_metadata (id, name, type,
|
||||||
engine, create_time, update_time,
|
create_time, update_time, size
|
||||||
size)
|
)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
|
||||||
#{engine,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{size,jdbcType=BIGINT}
|
||||||
#{size,jdbcType=BIGINT})
|
)
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.FileMetadata">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.FileMetadata">
|
||||||
insert into file_metadata
|
insert into file_metadata
|
||||||
|
@ -121,9 +120,6 @@
|
||||||
<if test="type != null">
|
<if test="type != null">
|
||||||
type,
|
type,
|
||||||
</if>
|
</if>
|
||||||
<if test="engine != null">
|
|
||||||
engine,
|
|
||||||
</if>
|
|
||||||
<if test="createTime != null">
|
<if test="createTime != null">
|
||||||
create_time,
|
create_time,
|
||||||
</if>
|
</if>
|
||||||
|
@ -144,9 +140,6 @@
|
||||||
<if test="type != null">
|
<if test="type != null">
|
||||||
#{type,jdbcType=VARCHAR},
|
#{type,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="engine != null">
|
|
||||||
#{engine,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="createTime != null">
|
<if test="createTime != null">
|
||||||
#{createTime,jdbcType=BIGINT},
|
#{createTime,jdbcType=BIGINT},
|
||||||
</if>
|
</if>
|
||||||
|
@ -176,9 +169,6 @@
|
||||||
<if test="record.type != null">
|
<if test="record.type != null">
|
||||||
type = #{record.type,jdbcType=VARCHAR},
|
type = #{record.type,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.engine != null">
|
|
||||||
engine = #{record.engine,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="record.createTime != null">
|
<if test="record.createTime != null">
|
||||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||||
</if>
|
</if>
|
||||||
|
@ -198,7 +188,6 @@
|
||||||
set id = #{record.id,jdbcType=VARCHAR},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
name = #{record.name,jdbcType=VARCHAR},
|
name = #{record.name,jdbcType=VARCHAR},
|
||||||
type = #{record.type,jdbcType=VARCHAR},
|
type = #{record.type,jdbcType=VARCHAR},
|
||||||
engine = #{record.engine,jdbcType=VARCHAR},
|
|
||||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||||
size = #{record.size,jdbcType=BIGINT}
|
size = #{record.size,jdbcType=BIGINT}
|
||||||
|
@ -215,9 +204,6 @@
|
||||||
<if test="type != null">
|
<if test="type != null">
|
||||||
type = #{type,jdbcType=VARCHAR},
|
type = #{type,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="engine != null">
|
|
||||||
engine = #{engine,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="createTime != null">
|
<if test="createTime != null">
|
||||||
create_time = #{createTime,jdbcType=BIGINT},
|
create_time = #{createTime,jdbcType=BIGINT},
|
||||||
</if>
|
</if>
|
||||||
|
@ -234,7 +220,6 @@
|
||||||
update file_metadata
|
update file_metadata
|
||||||
set name = #{name,jdbcType=VARCHAR},
|
set name = #{name,jdbcType=VARCHAR},
|
||||||
type = #{type,jdbcType=VARCHAR},
|
type = #{type,jdbcType=VARCHAR},
|
||||||
engine = #{engine,jdbcType=VARCHAR},
|
|
||||||
create_time = #{createTime,jdbcType=BIGINT},
|
create_time = #{createTime,jdbcType=BIGINT},
|
||||||
update_time = #{updateTime,jdbcType=BIGINT},
|
update_time = #{updateTime,jdbcType=BIGINT},
|
||||||
size = #{size,jdbcType=BIGINT}
|
size = #{size,jdbcType=BIGINT}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package io.metersphere.commons.constants;
|
|
||||||
|
|
||||||
public enum EngineType {
|
|
||||||
DOCKER, KUBERNETES
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
package io.metersphere.commons.constants;
|
package io.metersphere.commons.constants;
|
||||||
|
|
||||||
public enum ResourceTypeEnum {
|
public enum ResourcePoolTypeEnum {
|
||||||
/**
|
/**
|
||||||
* k8s 资源池
|
* k8s 资源池
|
||||||
*/
|
*/
|
|
@ -39,4 +39,13 @@ public class TestResourcePoolController {
|
||||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
return PageUtils.setPageInfo(page, testResourcePoolService.listResourcePools(request));
|
return PageUtils.setPageInfo(page, testResourcePoolService.listResourcePools(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("list/all")
|
||||||
|
public List<TestResourcePool> listResourcePools() {
|
||||||
|
PageHelper.startPage(1, 10000, true);
|
||||||
|
QueryResourcePoolRequest request = new QueryResourcePoolRequest();
|
||||||
|
return testResourcePoolService.listResourcePools(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package io.metersphere.dto;
|
||||||
|
|
||||||
|
public class KubernetesDTO {
|
||||||
|
|
||||||
|
private String masterUrl;
|
||||||
|
private String token;
|
||||||
|
private Integer maxConcurrency;
|
||||||
|
private Boolean validate;
|
||||||
|
|
||||||
|
public String getMasterUrl() {
|
||||||
|
return masterUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMasterUrl(String masterUrl) {
|
||||||
|
this.masterUrl = masterUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxConcurrency() {
|
||||||
|
return maxConcurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxConcurrency(Integer maxConcurrency) {
|
||||||
|
this.maxConcurrency = maxConcurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getValidate() {
|
||||||
|
return validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValidate(Boolean validate) {
|
||||||
|
this.validate = validate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package io.metersphere.dto;
|
||||||
|
|
||||||
|
public class NodeDTO {
|
||||||
|
private String ip;
|
||||||
|
private Integer port;
|
||||||
|
private Integer maxConcurrency;
|
||||||
|
private Boolean validate;
|
||||||
|
|
||||||
|
public String getIp() {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIp(String ip) {
|
||||||
|
this.ip = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(Integer port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxConcurrency() {
|
||||||
|
return maxConcurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxConcurrency(Integer maxConcurrency) {
|
||||||
|
this.maxConcurrency = maxConcurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getValidate() {
|
||||||
|
return validate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValidate(Boolean validate) {
|
||||||
|
this.validate = validate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ public class EngineContext {
|
||||||
private String testId;
|
private String testId;
|
||||||
private String testName;
|
private String testName;
|
||||||
private String namespace;
|
private String namespace;
|
||||||
private String engineType;
|
|
||||||
private String fileType;
|
private String fileType;
|
||||||
private String content;
|
private String content;
|
||||||
private Map<String, Object> properties = new HashMap<>();
|
private Map<String, Object> properties = new HashMap<>();
|
||||||
|
@ -37,14 +36,6 @@ public class EngineContext {
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEngineType() {
|
|
||||||
return engineType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEngineType(String engineType) {
|
|
||||||
this.engineType = engineType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addProperty(String key, Object value) {
|
public void addProperty(String key, Object value) {
|
||||||
this.properties.put(key, value);
|
this.properties.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import com.alibaba.fastjson.JSONObject;
|
||||||
import io.metersphere.base.domain.FileContent;
|
import io.metersphere.base.domain.FileContent;
|
||||||
import io.metersphere.base.domain.FileMetadata;
|
import io.metersphere.base.domain.FileMetadata;
|
||||||
import io.metersphere.base.domain.LoadTestWithBLOBs;
|
import io.metersphere.base.domain.LoadTestWithBLOBs;
|
||||||
import io.metersphere.commons.constants.EngineType;
|
import io.metersphere.base.domain.TestResourcePool;
|
||||||
|
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.engine.docker.DockerTestEngine;
|
import io.metersphere.engine.docker.DockerTestEngine;
|
||||||
import io.metersphere.engine.kubernetes.KubernetesTestEngine;
|
import io.metersphere.engine.kubernetes.KubernetesTestEngine;
|
||||||
|
@ -13,6 +14,7 @@ import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.parse.EngineSourceParser;
|
import io.metersphere.parse.EngineSourceParser;
|
||||||
import io.metersphere.parse.EngineSourceParserFactory;
|
import io.metersphere.parse.EngineSourceParserFactory;
|
||||||
import io.metersphere.service.FileService;
|
import io.metersphere.service.FileService;
|
||||||
|
import io.metersphere.service.TestResourcePoolService;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -26,14 +28,35 @@ import java.util.Map;
|
||||||
@Service
|
@Service
|
||||||
public class EngineFactory {
|
public class EngineFactory {
|
||||||
private static FileService fileService;
|
private static FileService fileService;
|
||||||
|
private static TestResourcePoolService testResourcePoolService;
|
||||||
|
|
||||||
public static Engine createEngine(String engineType) {
|
public static Engine createEngine(LoadTestWithBLOBs loadTest) {
|
||||||
final EngineType type = EngineType.valueOf(engineType);
|
String resourcePoolId = null;
|
||||||
|
if (!StringUtils.isEmpty(loadTest.getLoadConfiguration())) {
|
||||||
|
final JSONArray jsonArray = JSONObject.parseArray(loadTest.getLoadConfiguration());
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
final JSONObject jsonObject = jsonArray.getJSONObject(i);
|
||||||
|
if (StringUtils.equals(jsonObject.getString("key"), "resourcePoolId")) {
|
||||||
|
resourcePoolId = jsonObject.getString("value");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(resourcePoolId)) {
|
||||||
|
MSException.throwException("Resource Pool ID is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TestResourcePool resourcePool = testResourcePoolService.getResourcePool(resourcePoolId);
|
||||||
|
if (resourcePool == null) {
|
||||||
|
MSException.throwException("Resource Pool is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResourcePoolTypeEnum type = ResourcePoolTypeEnum.valueOf(resourcePool.getType());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DOCKER:
|
case NODE:
|
||||||
return new DockerTestEngine();
|
return new DockerTestEngine();
|
||||||
case KUBERNETES:
|
case K8S:
|
||||||
return new KubernetesTestEngine();
|
return new KubernetesTestEngine();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -48,7 +71,6 @@ public class EngineFactory {
|
||||||
engineContext.setTestId(loadTest.getId());
|
engineContext.setTestId(loadTest.getId());
|
||||||
engineContext.setTestName(loadTest.getName());
|
engineContext.setTestName(loadTest.getName());
|
||||||
engineContext.setNamespace(loadTest.getProjectId());
|
engineContext.setNamespace(loadTest.getProjectId());
|
||||||
engineContext.setEngineType(fileMetadata.getEngine());
|
|
||||||
engineContext.setFileType(fileMetadata.getType());
|
engineContext.setFileType(fileMetadata.getType());
|
||||||
|
|
||||||
if (!StringUtils.isEmpty(loadTest.getLoadConfiguration())) {
|
if (!StringUtils.isEmpty(loadTest.getLoadConfiguration())) {
|
||||||
|
@ -86,4 +108,9 @@ public class EngineFactory {
|
||||||
private void setFileService(FileService fileService) {
|
private void setFileService(FileService fileService) {
|
||||||
EngineFactory.fileService = fileService;
|
EngineFactory.fileService = fileService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
public void setTestResourcePoolService(TestResourcePoolService testResourcePoolService) {
|
||||||
|
EngineFactory.testResourcePoolService = testResourcePoolService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
package io.metersphere.engine.docker;
|
package io.metersphere.engine.docker;
|
||||||
|
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.controller.request.TestRequest;
|
import io.metersphere.controller.request.TestRequest;
|
||||||
import io.metersphere.engine.Engine;
|
import io.metersphere.engine.Engine;
|
||||||
import io.metersphere.engine.EngineContext;
|
import io.metersphere.engine.EngineContext;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DockerTestEngine implements Engine {
|
public class DockerTestEngine implements Engine {
|
||||||
private EngineContext context;
|
private EngineContext context;
|
||||||
|
|
||||||
|
RestTemplate restTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean init(EngineContext context) {
|
public boolean init(EngineContext context) {
|
||||||
|
this.restTemplate = CommonBeanFactory.getBean(RestTemplate.class);
|
||||||
// todo 初始化操作
|
// todo 初始化操作
|
||||||
this.context = context;
|
this.context = context;
|
||||||
return true;
|
return true;
|
||||||
|
@ -22,8 +25,8 @@ public class DockerTestEngine implements Engine {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
// todo 运行测试
|
||||||
|
// RestTemplate restTemplate = new RestTemplate();
|
||||||
String testId = context.getTestId();
|
String testId = context.getTestId();
|
||||||
String content = context.getContent();
|
String content = context.getContent();
|
||||||
|
|
||||||
|
@ -34,6 +37,7 @@ public class DockerTestEngine implements Engine {
|
||||||
testRequest.setTestId(testId);
|
testRequest.setTestId(testId);
|
||||||
testRequest.setFileString(content);
|
testRequest.setFileString(content);
|
||||||
|
|
||||||
|
// todo 判断测试状态
|
||||||
String taskStatusUri = "http://localhost:8082/jmeter/task/status/" + testId;
|
String taskStatusUri = "http://localhost:8082/jmeter/task/status/" + testId;
|
||||||
List containerList = restTemplate.getForObject(taskStatusUri, List.class);
|
List containerList = restTemplate.getForObject(taskStatusUri, List.class);
|
||||||
for (int i = 0; i < containerList.size(); i++) {
|
for (int i = 0; i < containerList.size(); i++) {
|
||||||
|
@ -48,12 +52,13 @@ public class DockerTestEngine implements Engine {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
// TODO 停止运行测试
|
||||||
|
// RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
String testId = context.getTestId();
|
String testId = context.getTestId();
|
||||||
|
|
||||||
String uri = "http://localhost:8082/jmeter/container/stop" + testId;
|
String uri = "http://localhost:8082/jmeter/container/stop/" + testId;
|
||||||
restTemplate.getForObject(uri, String.class);
|
restTemplate.postForObject(uri, "", String.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
||||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.engine.Engine;
|
import io.metersphere.engine.Engine;
|
||||||
import io.metersphere.engine.EngineContext;
|
import io.metersphere.engine.EngineContext;
|
||||||
|
@ -11,17 +12,20 @@ import io.metersphere.engine.kubernetes.crds.jmeter.Jmeter;
|
||||||
import io.metersphere.engine.kubernetes.crds.jmeter.JmeterSpec;
|
import io.metersphere.engine.kubernetes.crds.jmeter.JmeterSpec;
|
||||||
import io.metersphere.engine.kubernetes.provider.ClientCredential;
|
import io.metersphere.engine.kubernetes.provider.ClientCredential;
|
||||||
import io.metersphere.engine.kubernetes.provider.KubernetesProvider;
|
import io.metersphere.engine.kubernetes.provider.KubernetesProvider;
|
||||||
|
import io.metersphere.service.TestResourcePoolService;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class KubernetesTestEngine implements Engine {
|
public class KubernetesTestEngine implements Engine {
|
||||||
private EngineContext context;
|
private EngineContext context;
|
||||||
|
private TestResourcePoolService testResourcePoolService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean init(EngineContext context) {
|
public boolean init(EngineContext context) {
|
||||||
// todo 初始化操作
|
// todo 初始化操作
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.testResourcePoolService = CommonBeanFactory.getBean(TestResourcePoolService.class);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -233,9 +233,11 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
collectionProp.appendChild(createKafkaProp(document, "kafka.batch.size", kafkaProperties.getBatchSize()));
|
collectionProp.appendChild(createKafkaProp(document, "kafka.batch.size", kafkaProperties.getBatchSize()));
|
||||||
collectionProp.appendChild(createKafkaProp(document, "kafka.client.id", kafkaProperties.getClientId()));
|
collectionProp.appendChild(createKafkaProp(document, "kafka.client.id", kafkaProperties.getClientId()));
|
||||||
collectionProp.appendChild(createKafkaProp(document, "kafka.connections.max.idle.ms", kafkaProperties.getConnectionsMaxIdleMs()));
|
collectionProp.appendChild(createKafkaProp(document, "kafka.connections.max.idle.ms", kafkaProperties.getConnectionsMaxIdleMs()));
|
||||||
// 添加关联关系 test.id test.name
|
// 添加关联关系 test.id test.name test.startTime test.size
|
||||||
collectionProp.appendChild(createKafkaProp(document, "test.id", context.getTestId()));
|
collectionProp.appendChild(createKafkaProp(document, "test.id", context.getTestId()));
|
||||||
collectionProp.appendChild(createKafkaProp(document, "test.name", context.getTestName()));
|
collectionProp.appendChild(createKafkaProp(document, "test.name", context.getTestName()));
|
||||||
|
collectionProp.appendChild(createKafkaProp(document, "test.startTime", "" + System.currentTimeMillis()));
|
||||||
|
collectionProp.appendChild(createKafkaProp(document, "test.size", "1"));
|
||||||
|
|
||||||
elementProp.appendChild(collectionProp);
|
elementProp.appendChild(collectionProp);
|
||||||
// set elementProp
|
// set elementProp
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
package io.metersphere.report;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.opencsv.bean.CsvToBean;
|
||||||
|
import com.opencsv.bean.CsvToBeanBuilder;
|
||||||
|
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
|
||||||
|
import io.metersphere.report.base.Metric;
|
||||||
|
import io.metersphere.report.base.RequestStatistics;
|
||||||
|
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class JtlResolver {
|
||||||
|
|
||||||
|
private List<Metric> resolver(String jtlString) {
|
||||||
|
HeaderColumnNameMappingStrategy<Metric> ms = new HeaderColumnNameMappingStrategy<>();
|
||||||
|
ms.setType(Metric.class);
|
||||||
|
try (Reader reader = new StringReader(jtlString)) {
|
||||||
|
|
||||||
|
CsvToBean<Metric> cb = new CsvToBeanBuilder<Metric>(reader)
|
||||||
|
.withType(Metric.class)
|
||||||
|
.withSkipLines(0)
|
||||||
|
.withMappingStrategy(ms)
|
||||||
|
.withIgnoreLeadingWhiteSpace(true)
|
||||||
|
.build();
|
||||||
|
return cb.parse();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RequestStatistics> getOneRpsResult(Map<String, List<Metric>> map){
|
||||||
|
List<RequestStatistics> requestStatisticsList = new ArrayList<>();
|
||||||
|
Iterator<Map.Entry<String, List<Metric>>> iterator = map.entrySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<String, List<Metric>> entry = iterator.next();
|
||||||
|
String label = entry.getKey();
|
||||||
|
List<Metric> list = entry.getValue();
|
||||||
|
List<String> timestampList = list.stream().map(Metric::getTimestamp).collect(Collectors.toList());
|
||||||
|
int index=0;
|
||||||
|
//总的响应时间
|
||||||
|
int sumElapsed=0;
|
||||||
|
Integer failSize = 0;
|
||||||
|
Integer totalBytes = 0;
|
||||||
|
List<Integer> elapsedList = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
try {
|
||||||
|
Metric row = list.get(i);
|
||||||
|
//响应时间
|
||||||
|
String elapsed = row.getElapsed();
|
||||||
|
sumElapsed += Integer.valueOf(elapsed);
|
||||||
|
elapsedList.add(Integer.valueOf(elapsed));
|
||||||
|
//成功与否
|
||||||
|
String success = row.getSuccess();
|
||||||
|
if (!"true".equals(success)){
|
||||||
|
failSize++;
|
||||||
|
}
|
||||||
|
//字节
|
||||||
|
String bytes = row.getBytes();
|
||||||
|
totalBytes += Integer.valueOf(bytes);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("exception i:"+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(elapsedList, new Comparator<Integer>() {
|
||||||
|
public int compare(Integer o1, Integer o2) {
|
||||||
|
return o1-o2;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Integer tp90 = elapsedList.size()*9/10;
|
||||||
|
Integer tp95 = elapsedList.size()*95/100;
|
||||||
|
Integer tp99 = elapsedList.size()*99/100;
|
||||||
|
|
||||||
|
Long l = Long.valueOf(timestampList.get(index-1)) - Long.valueOf(timestampList.get(0));
|
||||||
|
|
||||||
|
RequestStatistics requestStatistics = new RequestStatistics();
|
||||||
|
requestStatistics.setRequestLabel(label);
|
||||||
|
requestStatistics.setSamples(index+"");
|
||||||
|
requestStatistics.setAverage(sumElapsed/index+"");
|
||||||
|
/**
|
||||||
|
* TP90的计算
|
||||||
|
* 1,把一段时间内全部的请求的响应时间,从小到大排序,获得序列A
|
||||||
|
* 2,总的请求数量,乘以90%,获得90%对应的请求个数C
|
||||||
|
* 3,从序列A中找到第C个请求,它的响应时间,即为TP90的值
|
||||||
|
* 其余相似的指标还有TP95, TP99
|
||||||
|
*/
|
||||||
|
requestStatistics.setTp90(elapsedList.get(tp90)+"");
|
||||||
|
requestStatistics.setTp95(elapsedList.get(tp95)+"");
|
||||||
|
requestStatistics.setTp99(elapsedList.get(tp99)+"");
|
||||||
|
requestStatistics.setMin(elapsedList.get(0)+"");
|
||||||
|
requestStatistics.setMax(elapsedList.get(index-1)+"");
|
||||||
|
requestStatistics.setErrors(String.format("%.2f",failSize*100.0/index)+"%");
|
||||||
|
requestStatistics.setKbPerSec(String.format("%.2f",totalBytes*1.0/1024/(l*1.0/1000)));
|
||||||
|
requestStatisticsList.add(requestStatistics);
|
||||||
|
}
|
||||||
|
return requestStatisticsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RequestStatistics> getRequestStatistics(String jtlString) {
|
||||||
|
List<Metric> totalLines = resolver(jtlString);
|
||||||
|
Map<String, List<Metric>> map = totalLines.stream().collect(Collectors.groupingBy(Metric::getLabel));
|
||||||
|
return getOneRpsResult(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
package io.metersphere.report.base;
|
||||||
|
|
||||||
|
import com.opencsv.bean.CsvBindByName;
|
||||||
|
|
||||||
|
public class Metric {
|
||||||
|
// timestamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect
|
||||||
|
|
||||||
|
@CsvBindByName(column = "timestamp") // 访问开始时间
|
||||||
|
private String timestamp;
|
||||||
|
@CsvBindByName(column = "elapsed") // 访问开始到结束的用时 - 响应时间
|
||||||
|
private String elapsed;
|
||||||
|
@CsvBindByName(column = "label") // 请求的标签
|
||||||
|
private String label;
|
||||||
|
@CsvBindByName(column = "responseCode") // 响应码
|
||||||
|
private String responseCode;
|
||||||
|
@CsvBindByName(column = "responseMessage") // 响应信息
|
||||||
|
private String responseMessage;
|
||||||
|
@CsvBindByName(column = "threadName") // 请求所属线程
|
||||||
|
private String threadName;
|
||||||
|
@CsvBindByName(column = "dataType") // 数据类型
|
||||||
|
private String dataType;
|
||||||
|
@CsvBindByName(column = "success") // 访问是否成功
|
||||||
|
private String success;
|
||||||
|
@CsvBindByName(column = "failureMessage") // 访问失败信息
|
||||||
|
private String failureMessage;
|
||||||
|
@CsvBindByName(column = "bytes") //
|
||||||
|
private String bytes;
|
||||||
|
@CsvBindByName(column = "sentBytes") //
|
||||||
|
private String sentBytes;
|
||||||
|
@CsvBindByName(column = "grpThreads") // 线程组
|
||||||
|
private String grpThreads;
|
||||||
|
@CsvBindByName(column = "allThreads") //
|
||||||
|
private String allThreads;
|
||||||
|
@CsvBindByName(column = "URL") //
|
||||||
|
private String url;
|
||||||
|
@CsvBindByName(column = "Latency") // 延时
|
||||||
|
private String latency;
|
||||||
|
@CsvBindByName(column = "IdleTime") // 闲置时间
|
||||||
|
private String idleTime;
|
||||||
|
@CsvBindByName(column = "Connect") //
|
||||||
|
private String connect;
|
||||||
|
|
||||||
|
|
||||||
|
public String getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(String timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElapsed() {
|
||||||
|
return elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElapsed(String elapsed) {
|
||||||
|
this.elapsed = elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabel(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseCode() {
|
||||||
|
return responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseCode(String responseCode) {
|
||||||
|
this.responseCode = responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseMessage() {
|
||||||
|
return responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseMessage(String responseMessage) {
|
||||||
|
this.responseMessage = responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getThreadName() {
|
||||||
|
return threadName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThreadName(String threadName) {
|
||||||
|
this.threadName = threadName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataType() {
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataType(String dataType) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSuccess(String success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFailureMessage() {
|
||||||
|
return failureMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFailureMessage(String failureMessage) {
|
||||||
|
this.failureMessage = failureMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBytes() {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBytes(String bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSentBytes() {
|
||||||
|
return sentBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSentBytes(String sentBytes) {
|
||||||
|
this.sentBytes = sentBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrpThreads() {
|
||||||
|
return grpThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrpThreads(String grpThreads) {
|
||||||
|
this.grpThreads = grpThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAllThreads() {
|
||||||
|
return allThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllThreads(String allThreads) {
|
||||||
|
this.allThreads = allThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLatency() {
|
||||||
|
return latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLatency(String latency) {
|
||||||
|
this.latency = latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdleTime() {
|
||||||
|
return idleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdleTime(String idleTime) {
|
||||||
|
this.idleTime = idleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConnect() {
|
||||||
|
return connect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnect(String connect) {
|
||||||
|
this.connect = connect;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
package io.metersphere.report.base;
|
||||||
|
|
||||||
|
public class RequestStatistics {
|
||||||
|
|
||||||
|
/**请求标签*/
|
||||||
|
private String requestLabel;
|
||||||
|
|
||||||
|
/**压测请求数*/
|
||||||
|
private String samples;
|
||||||
|
|
||||||
|
/**平均响应时间*/
|
||||||
|
private String average;
|
||||||
|
|
||||||
|
/**平均点击率*/
|
||||||
|
private Double avgHits;
|
||||||
|
|
||||||
|
/**90% Line*/
|
||||||
|
private String tp90;
|
||||||
|
|
||||||
|
/**95% Line*/
|
||||||
|
private String tp95;
|
||||||
|
|
||||||
|
/**99% Line*/
|
||||||
|
private String tp99;
|
||||||
|
|
||||||
|
/**最小请求时间 Min Response Time /ms */
|
||||||
|
private String min;
|
||||||
|
|
||||||
|
/**最大请求时间 Max Response Time /ms */
|
||||||
|
private String max;
|
||||||
|
|
||||||
|
/**吞吐量 KB/sec*/
|
||||||
|
private String kbPerSec;
|
||||||
|
|
||||||
|
/**错误率 Error Percentage */
|
||||||
|
private String errors;
|
||||||
|
|
||||||
|
public String getRequestLabel() {
|
||||||
|
return requestLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestLabel(String requestLabel) {
|
||||||
|
this.requestLabel = requestLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSamples() {
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSamples(String samples) {
|
||||||
|
this.samples = samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAverage() {
|
||||||
|
return average;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAverage(String average) {
|
||||||
|
this.average = average;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getAvgHits() {
|
||||||
|
return avgHits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvgHits(Double avgHits) {
|
||||||
|
this.avgHits = avgHits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTp90() {
|
||||||
|
return tp90;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTp90(String tp90) {
|
||||||
|
this.tp90 = tp90;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTp95() {
|
||||||
|
return tp95;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTp95(String tp95) {
|
||||||
|
this.tp95 = tp95;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTp99() {
|
||||||
|
return tp99;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTp99(String tp99) {
|
||||||
|
this.tp99 = tp99;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMin(String min) {
|
||||||
|
this.min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMax(String max) {
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKbPerSec() {
|
||||||
|
return kbPerSec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKbPerSec(String kbPerSec) {
|
||||||
|
this.kbPerSec = kbPerSec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrors() {
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrors(String errors) {
|
||||||
|
this.errors = errors;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,12 +3,9 @@ package io.metersphere.service;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.*;
|
import io.metersphere.base.mapper.*;
|
||||||
import io.metersphere.base.mapper.ext.ExtFunctionalTestMapper;
|
import io.metersphere.base.mapper.ext.ExtFunctionalTestMapper;
|
||||||
import io.metersphere.commons.constants.EngineType;
|
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.controller.request.testplan.*;
|
import io.metersphere.controller.request.testplan.*;
|
||||||
import io.metersphere.dto.FunctionalTestDTO;
|
import io.metersphere.dto.FunctionalTestDTO;
|
||||||
import io.metersphere.engine.Engine;
|
|
||||||
import io.metersphere.engine.EngineFactory;
|
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -94,8 +91,6 @@ public class FuctionalTestService {
|
||||||
fileMetadata.setCreateTime(System.currentTimeMillis());
|
fileMetadata.setCreateTime(System.currentTimeMillis());
|
||||||
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
||||||
fileMetadata.setType("jmx");
|
fileMetadata.setType("jmx");
|
||||||
// TODO engine 选择
|
|
||||||
fileMetadata.setEngine(EngineType.DOCKER.name());
|
|
||||||
fileMetadataMapper.insert(fileMetadata);
|
fileMetadataMapper.insert(fileMetadata);
|
||||||
|
|
||||||
FileContent fileContent = new FileContent();
|
FileContent fileContent = new FileContent();
|
||||||
|
|
|
@ -6,7 +6,6 @@ import io.metersphere.base.mapper.FileMetadataMapper;
|
||||||
import io.metersphere.base.mapper.LoadTestFileMapper;
|
import io.metersphere.base.mapper.LoadTestFileMapper;
|
||||||
import io.metersphere.base.mapper.LoadTestMapper;
|
import io.metersphere.base.mapper.LoadTestMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
||||||
import io.metersphere.commons.constants.EngineType;
|
|
||||||
import io.metersphere.commons.constants.FileType;
|
import io.metersphere.commons.constants.FileType;
|
||||||
import io.metersphere.commons.constants.TestStatus;
|
import io.metersphere.commons.constants.TestStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
@ -45,6 +44,8 @@ public class LoadTestService {
|
||||||
private LoadTestFileMapper loadTestFileMapper;
|
private LoadTestFileMapper loadTestFileMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private FileService fileService;
|
private FileService fileService;
|
||||||
|
@Resource
|
||||||
|
private TestResourcePoolService testResourcePoolService;
|
||||||
|
|
||||||
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
|
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
|
||||||
return extLoadTestMapper.list(request);
|
return extLoadTestMapper.list(request);
|
||||||
|
@ -102,8 +103,6 @@ public class LoadTestService {
|
||||||
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
||||||
FileType fileType = getFileType(fileMetadata.getName());
|
FileType fileType = getFileType(fileMetadata.getName());
|
||||||
fileMetadata.setType(fileType.name());
|
fileMetadata.setType(fileType.name());
|
||||||
// TODO engine 选择
|
|
||||||
fileMetadata.setEngine(EngineType.DOCKER.name());
|
|
||||||
fileMetadataMapper.insert(fileMetadata);
|
fileMetadataMapper.insert(fileMetadata);
|
||||||
|
|
||||||
FileContent fileContent = new FileContent();
|
FileContent fileContent = new FileContent();
|
||||||
|
@ -179,9 +178,8 @@ public class LoadTestService {
|
||||||
List<FileMetadata> csvFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.CSV.name())).collect(Collectors.toList());
|
List<FileMetadata> csvFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.CSV.name())).collect(Collectors.toList());
|
||||||
|
|
||||||
LogUtil.info("Load test started " + loadTest.getName());
|
LogUtil.info("Load test started " + loadTest.getName());
|
||||||
// engine type (DOCKER|KUBERNETES)
|
// engine type (NODE|K8S)
|
||||||
// todo set type
|
final Engine engine = EngineFactory.createEngine(loadTest);
|
||||||
final Engine engine = EngineFactory.createEngine(fileMetadata.getEngine());
|
|
||||||
if (engine == null) {
|
if (engine == null) {
|
||||||
MSException.throwException(String.format("Test cannot be run,test ID:%s,file type:%s", request.getId(), fileMetadata.getType()));
|
MSException.throwException(String.format("Test cannot be run,test ID:%s,file type:%s", request.getId(), fileMetadata.getType()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,4 +41,8 @@ public class ReportService {
|
||||||
public ReportDTO getReportTestAndProInfo(String reportId) {
|
public ReportDTO getReportTestAndProInfo(String reportId) {
|
||||||
return extLoadTestReportMapper.getReportTestAndProInfo(reportId);
|
return extLoadTestReportMapper.getReportTestAndProInfo(reportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoadTestReport getReport(String id) {
|
||||||
|
return loadTestReportMapper.selectByPrimaryKey(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
package io.metersphere.service;
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
import io.metersphere.base.domain.TestResourcePool;
|
import io.metersphere.base.domain.TestResourcePool;
|
||||||
import io.metersphere.base.domain.TestResourcePoolExample;
|
import io.metersphere.base.domain.TestResourcePoolExample;
|
||||||
import io.metersphere.base.mapper.TestResourcePoolMapper;
|
import io.metersphere.base.mapper.TestResourcePoolMapper;
|
||||||
|
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
|
||||||
|
import io.metersphere.commons.utils.BeanUtils;
|
||||||
import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest;
|
import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest;
|
||||||
|
import io.metersphere.dto.KubernetesDTO;
|
||||||
|
import io.metersphere.dto.NodeDTO;
|
||||||
|
import io.metersphere.engine.kubernetes.provider.ClientCredential;
|
||||||
|
import io.metersphere.engine.kubernetes.provider.KubernetesProvider;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -19,6 +30,8 @@ import java.util.UUID;
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class TestResourcePoolService {
|
public class TestResourcePoolService {
|
||||||
|
|
||||||
|
private final static String nodeControllerUrl = "%s:%s/status";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TestResourcePoolMapper testResourcePoolMapper;
|
private TestResourcePoolMapper testResourcePoolMapper;
|
||||||
|
|
||||||
|
@ -27,6 +40,7 @@ public class TestResourcePoolService {
|
||||||
testResourcePool.setCreateTime(System.currentTimeMillis());
|
testResourcePool.setCreateTime(System.currentTimeMillis());
|
||||||
testResourcePool.setUpdateTime(System.currentTimeMillis());
|
testResourcePool.setUpdateTime(System.currentTimeMillis());
|
||||||
testResourcePool.setStatus("1");
|
testResourcePool.setStatus("1");
|
||||||
|
validateTestResourcePool(testResourcePool);
|
||||||
testResourcePoolMapper.insertSelective(testResourcePool);
|
testResourcePoolMapper.insertSelective(testResourcePool);
|
||||||
return testResourcePool;
|
return testResourcePool;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +51,7 @@ public class TestResourcePoolService {
|
||||||
|
|
||||||
public void updateTestResourcePool(TestResourcePool testResourcePool) {
|
public void updateTestResourcePool(TestResourcePool testResourcePool) {
|
||||||
testResourcePool.setUpdateTime(System.currentTimeMillis());
|
testResourcePool.setUpdateTime(System.currentTimeMillis());
|
||||||
|
validateTestResourcePool(testResourcePool);
|
||||||
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
|
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,4 +62,59 @@ public class TestResourcePoolService {
|
||||||
}
|
}
|
||||||
return testResourcePoolMapper.selectByExample(example);
|
return testResourcePoolMapper.selectByExample(example);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateTestResourcePool(TestResourcePool testResourcePool) {
|
||||||
|
if (StringUtils.equalsIgnoreCase(testResourcePool.getType(), ResourcePoolTypeEnum.K8S.name())) {
|
||||||
|
validateK8s(testResourcePool);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
validateNodes(testResourcePool);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateNodes(TestResourcePool testResourcePool) {
|
||||||
|
List<NodeDTO> nodes = JSON.parseArray(testResourcePool.getInfo(), NodeDTO.class);
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(nodes)) {
|
||||||
|
throw new RuntimeException("没有节点信息");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NodeDTO node : nodes) {
|
||||||
|
boolean isValidate = validateNode(node);
|
||||||
|
if (!isValidate) {
|
||||||
|
testResourcePool.setStatus("0");
|
||||||
|
}
|
||||||
|
node.setValidate(isValidate);
|
||||||
|
}
|
||||||
|
testResourcePool.setInfo(JSON.toJSONString(nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean validateNode(NodeDTO dto) {
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
ResponseEntity<String> entity = restTemplate.getForEntity(String.format(nodeControllerUrl, dto.getIp(), dto.getPort()), String.class);
|
||||||
|
return entity.getStatusCode().value() == HttpStatus.SC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateK8s(TestResourcePool testResourcePool) {
|
||||||
|
List<KubernetesDTO> dtos = JSON.parseArray(testResourcePool.getInfo(), KubernetesDTO.class);
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(dtos) || dtos.size() != 1) {
|
||||||
|
throw new RuntimeException("只能添加一个 K8s");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientCredential clientCredential = new ClientCredential();
|
||||||
|
BeanUtils.copyBean(clientCredential, dtos.get(0));
|
||||||
|
try {
|
||||||
|
KubernetesProvider provider = new KubernetesProvider(JSON.toJSONString(clientCredential));
|
||||||
|
provider.validateCredential();
|
||||||
|
dtos.get(0).setValidate(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
dtos.get(0).setValidate(false);
|
||||||
|
testResourcePool.setStatus("0");
|
||||||
|
}
|
||||||
|
testResourcePool.setInfo(JSON.toJSONString(dtos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestResourcePool getResourcePool(String resourcePoolId) {
|
||||||
|
return testResourcePoolMapper.selectByPrimaryKey(resourcePoolId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ CREATE TABLE IF NOT EXISTS `file_metadata` (
|
||||||
`id` varchar(64) NOT NULL COMMENT 'File ID',
|
`id` varchar(64) NOT NULL COMMENT 'File ID',
|
||||||
`name` varchar(64) NOT NULL COMMENT 'File name',
|
`name` varchar(64) NOT NULL COMMENT 'File name',
|
||||||
`type` varchar(64) DEFAULT NULL COMMENT 'File type',
|
`type` varchar(64) DEFAULT NULL COMMENT 'File type',
|
||||||
`engine` varchar(64) DEFAULT 'DOCKER' COMMENT 'engine type',
|
|
||||||
`size` bigint(13) NOT NULL COMMENT 'File size',
|
`size` bigint(13) NOT NULL COMMENT 'File size',
|
||||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
`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',
|
||||||
|
|
|
@ -45,10 +45,20 @@
|
||||||
</javaClientGenerator>
|
</javaClientGenerator>
|
||||||
|
|
||||||
<!--要生成的数据库表 -->
|
<!--要生成的数据库表 -->
|
||||||
<table tableName="test_plan"/>
|
|
||||||
<table tableName="test_case_node"/>
|
|
||||||
<table tableName="test_case"/>
|
|
||||||
<table tableName="test_plan_test_case"/>
|
|
||||||
|
|
||||||
|
<!-- <table tableName="user"/>-->
|
||||||
|
<!-- <table tableName="user_role"/>-->
|
||||||
|
<!-- <table tableName="workspace"/>-->
|
||||||
|
<!-- <table tableName="test_resource_pool"/>-->
|
||||||
|
<!-- <table tableName="test_resource"/>-->
|
||||||
|
<!-- <table tableName="system_parameter"/>-->
|
||||||
|
<!-- <table tableName="role"/>-->
|
||||||
|
<!-- <table tableName="project"/>-->
|
||||||
|
<!-- <table tableName="organization"/>-->
|
||||||
|
<!-- <table tableName="load_test_report"/>-->
|
||||||
|
<!-- <table tableName="load_test"/>-->
|
||||||
|
<!-- <table tableName="file_content"/>-->
|
||||||
|
<table tableName="file_metadata"/>
|
||||||
|
<!-- <table tableName="load_test_file"/>-->
|
||||||
</context>
|
</context>
|
||||||
</generatorConfiguration>
|
</generatorConfiguration>
|
|
@ -1,41 +1,45 @@
|
||||||
package io.metersphere;
|
package io.metersphere;
|
||||||
|
|
||||||
import io.metersphere.commons.constants.JmeterReportType;
|
import com.opencsv.bean.CsvToBean;
|
||||||
import kg.apc.jmeter.PluginsCMDWorker;
|
import com.opencsv.bean.CsvToBeanBuilder;
|
||||||
import org.apache.jmeter.util.JMeterUtils;
|
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
|
||||||
|
import com.opencsv.bean.MappingStrategy;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class GenerateGraphTest {
|
public class GenerateGraphTest {
|
||||||
|
|
||||||
/*
|
|
||||||
AggregateReport = JMeter's native Aggregate Report, can be saved only as CSV
|
|
||||||
SynthesisReport = mix between JMeter's native Summary Report and Aggregate Report, can be saved only as CSV
|
|
||||||
ThreadsStateOverTime = Active Threads Over Time
|
|
||||||
BytesThroughputOverTime
|
|
||||||
HitsPerSecond
|
|
||||||
LatenciesOverTime
|
|
||||||
PerfMon = PerfMon Metrics Collector
|
|
||||||
DbMon = DbMon Metrics Collector, DataBase, get performance counters via sql
|
|
||||||
JMXMon = JMXMon Metrics Collector, Java Management Extensions counters
|
|
||||||
ResponseCodesPerSecond
|
|
||||||
ResponseTimesDistribution
|
|
||||||
ResponseTimesOverTime
|
|
||||||
ResponseTimesPercentiles
|
|
||||||
ThroughputVsThreads
|
|
||||||
TimesVsThreads = Response Times VS Threads
|
|
||||||
TransactionsPerSecond
|
|
||||||
PageDataExtractorOverTime
|
|
||||||
MergeResults = MergeResults Command Line Merge Tool to simplify the comparison of two or more load tests, need properties file (like merge-results.properties)
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void test1() {
|
public void test1() {
|
||||||
JMeterUtils.setJMeterHome("/opt/fit2cloud/apache-jmeter-5.2.1");
|
File csvFile = new File("/Users/liuruibin/Desktop/0316.jtl");
|
||||||
JMeterUtils.loadJMeterProperties("/opt/fit2cloud/apache-jmeter-5.2.1/bin/jmeter.properties");
|
HeaderColumnNameMappingStrategy<Metric> ms = new HeaderColumnNameMappingStrategy<>();
|
||||||
PluginsCMDWorker worker = new PluginsCMDWorker();
|
ms.setType(Metric.class);
|
||||||
worker.setPluginType(JmeterReportType.AggregateReport.name());
|
List<Metric> metrics = beanBuilderExample(csvFile.toPath(), ms);
|
||||||
worker.addExportMode(2);
|
metrics.forEach(c -> {
|
||||||
worker.setOutputCSVFile("/tmp/test0320.csv");
|
System.out.println(c.getTimestamp());
|
||||||
worker.setInputFile("/Users/liuruibin/Desktop/0316.jtl");
|
});
|
||||||
worker.doJob();
|
}
|
||||||
|
|
||||||
|
public static List<Metric> beanBuilderExample(Path path, MappingStrategy<Metric> ms) {
|
||||||
|
try (Reader reader = Files.newBufferedReader(path)) {
|
||||||
|
|
||||||
|
CsvToBean<Metric> cb = new CsvToBeanBuilder<Metric>(reader)
|
||||||
|
.withType(Metric.class)
|
||||||
|
.withSkipLines(0)
|
||||||
|
.withMappingStrategy(ms)
|
||||||
|
.withIgnoreLeadingWhiteSpace(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return cb.parse();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,271 @@
|
||||||
|
package io.metersphere;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.opencsv.bean.CsvToBean;
|
||||||
|
import com.opencsv.bean.CsvToBeanBuilder;
|
||||||
|
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
|
||||||
|
import io.metersphere.report.base.RequestStatistics;
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
public class JtlTest {
|
||||||
|
|
||||||
|
public static List<Metric> beanBuilderExample(String content) {
|
||||||
|
HeaderColumnNameMappingStrategy<io.metersphere.Metric> ms = new HeaderColumnNameMappingStrategy<>();
|
||||||
|
ms.setType(io.metersphere.Metric.class);
|
||||||
|
try (Reader reader = new StringReader(content)) {
|
||||||
|
|
||||||
|
CsvToBean<io.metersphere.Metric> cb = new CsvToBeanBuilder<Metric>(reader)
|
||||||
|
.withType(Metric.class)
|
||||||
|
.withSkipLines(0)
|
||||||
|
.withMappingStrategy(ms)
|
||||||
|
.withIgnoreLeadingWhiteSpace(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return cb.parse();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getRequestStatistics() {
|
||||||
|
String jtlString = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect\n" +
|
||||||
|
"1584602493891,1107,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-3,text,true,,1473653,6950,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=c81989f3-27d5-4b1a-a2db-03ddb06475d5&login=true&scope=openid,232,0,26\n" +
|
||||||
|
"1584602493891,235,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-3,,true,,214,567,3,3,https://rddev2.fit2cloud.com/,232,0,26\n" +
|
||||||
|
"1584602494128,11,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-3,,true,,615,577,3,3,https://rddev2.fit2cloud.com/dashboard/,11,0,0\n" +
|
||||||
|
"1584602494142,33,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-3,text,true,,8068,851,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=c81989f3-27d5-4b1a-a2db-03ddb06475d5&login=true&scope=openid,32,0,0\n" +
|
||||||
|
"1584602494242,756,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-3,text,true,,1464756,4955,3,3,https://rddev2.fit2cloud.com/login,46,0,0\n" +
|
||||||
|
"1584602493891,1154,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-2,text,true,,1473685,6950,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=374d02c0-6e1f-4937-b457-27d6e6ccf264&login=true&scope=openid,232,0,25\n" +
|
||||||
|
"1584602493891,235,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-2,,true,,214,567,3,3,https://rddev2.fit2cloud.com/,232,0,25\n" +
|
||||||
|
"1584602494128,11,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-2,,true,,615,577,3,3,https://rddev2.fit2cloud.com/dashboard/,11,0,0\n" +
|
||||||
|
"1584602494142,35,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-2,text,true,,8068,851,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=374d02c0-6e1f-4937-b457-27d6e6ccf264&login=true&scope=openid,35,0,0\n" +
|
||||||
|
"1584602494242,803,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-2,text,true,,1464788,4955,3,3,https://rddev2.fit2cloud.com/login,45,0,0\n" +
|
||||||
|
"1584602493891,1316,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-1,text,true,,1473686,6942,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=515530c4-0f36-454a-b536-9a11c7d2c47a&login=true&scope=openid,232,0,25\n" +
|
||||||
|
"1584602493891,235,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-1,,true,,214,567,3,3,https://rddev2.fit2cloud.com/,232,0,25\n" +
|
||||||
|
"1584602494128,12,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-1,,true,,614,577,3,3,https://rddev2.fit2cloud.com/dashboard/,12,0,0\n" +
|
||||||
|
"1584602494142,36,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-1,text,true,,8068,850,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=515530c4-0f36-454a-b536-9a11c7d2c47a&login=true&scope=openid,35,0,0\n" +
|
||||||
|
"1584602494242,965,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-1,text,true,,1464790,4948,3,3,https://rddev2.fit2cloud.com/login,48,0,0\n" +
|
||||||
|
"1584602496824,550,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-5,text,true,,1473644,6950,5,5,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=211a68fc-eb1e-482d-b5d2-636b411a133e&login=true&scope=openid,54,0,0\n" +
|
||||||
|
"1584602496824,54,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-5,,true,,214,567,5,5,https://rddev2.fit2cloud.com/,54,0,0\n" +
|
||||||
|
"1584602496878,12,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-5,,true,,615,577,5,5,https://rddev2.fit2cloud.com/dashboard/,12,0,0\n" +
|
||||||
|
"1584602496890,29,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-5,text,true,,8074,851,5,5,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=211a68fc-eb1e-482d-b5d2-636b411a133e&login=true&scope=openid,29,0,0\n" +
|
||||||
|
"1584602496922,452,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-5,text,true,,1464741,4955,5,5,https://rddev2.fit2cloud.com/login,20,0,0\n" +
|
||||||
|
"1584602496821,559,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-4,text,true,,1473633,6958,5,5,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=e6ebc175-e3dc-4c99-933b-f6610688dbfe&login=true&scope=openid,57,0,2\n" +
|
||||||
|
"1584602496821,57,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-4,,true,,214,567,5,5,https://rddev2.fit2cloud.com/,57,0,2\n" +
|
||||||
|
"1584602496878,11,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-4,,true,,616,577,5,5,https://rddev2.fit2cloud.com/dashboard/,11,0,0\n" +
|
||||||
|
"1584602496889,27,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-4,text,true,,8068,852,5,5,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=e6ebc175-e3dc-4c99-933b-f6610688dbfe&login=true&scope=openid,27,0,0\n" +
|
||||||
|
"1584602496919,461,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-4,text,true,,1464735,4962,5,5,https://rddev2.fit2cloud.com/login,20,0,0\n" +
|
||||||
|
"1584602499028,73,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-1,text,false,,4469,1745,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,73,0,6\n" +
|
||||||
|
"1584602499125,0,https://rddev2.fit2cloud.com/dashboard/?state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1&code=efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc,Non HTTP response code: java.net.URISyntaxException,\"Non HTTP response message: Illegal character in query at index 45: https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",Thread Group 1-1,text,false,,1392,0,8,8,\"https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",0,0,0\n" +
|
||||||
|
"1584602499126,21,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,12438,559,8,8,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,21,0,0\n" +
|
||||||
|
"1584602499251,18,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,1916,573,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,18,0,0\n" +
|
||||||
|
"1584602498833,509,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-7,text,true,,1473651,6942,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=1f8130d4-f1c4-44f5-8633-03cc4892f31c&login=true&scope=openid,39,0,1\n" +
|
||||||
|
"1584602498833,39,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-7,,true,,214,567,8,8,https://rddev2.fit2cloud.com/,39,0,1\n" +
|
||||||
|
"1584602498872,9,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-7,,true,,614,577,8,8,https://rddev2.fit2cloud.com/dashboard/,9,0,0\n" +
|
||||||
|
"1584602498881,18,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-7,text,true,,8074,850,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=1f8130d4-f1c4-44f5-8633-03cc4892f31c&login=true&scope=openid,18,0,0\n" +
|
||||||
|
"1584602498901,441,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-7,text,true,,1464749,4948,8,8,https://rddev2.fit2cloud.com/login,25,0,0\n" +
|
||||||
|
"1584602499325,71,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-2,text,false,,4469,1746,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,70,0,4\n" +
|
||||||
|
"1584602499445,16,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,1570,581,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,16,0,0\n" +
|
||||||
|
"1584602498832,637,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-6,text,true,,1473640,6958,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=ceda817a-6ac6-4516-9cd8-c1b25429bf94&login=true&scope=openid,50,0,1\n" +
|
||||||
|
"1584602498832,50,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-6,,true,,214,567,8,8,https://rddev2.fit2cloud.com/,50,0,1\n" +
|
||||||
|
"1584602498882,9,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-6,,true,,616,577,8,8,https://rddev2.fit2cloud.com/dashboard/,9,0,0\n" +
|
||||||
|
"1584602498891,35,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-6,text,true,,8068,852,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=ceda817a-6ac6-4516-9cd8-c1b25429bf94&login=true&scope=openid,35,0,0\n" +
|
||||||
|
"1584602498927,542,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-6,text,true,,1464742,4962,8,8,https://rddev2.fit2cloud.com/login,23,0,0\n" +
|
||||||
|
"1584602498836,635,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-8,text,true,,1473639,6950,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=1b42574e-756d-4157-9987-a8e1df496718&login=true&scope=openid,46,0,0\n" +
|
||||||
|
"1584602498836,46,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-8,,true,,214,567,8,8,https://rddev2.fit2cloud.com/,46,0,0\n" +
|
||||||
|
"1584602498883,12,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-8,,true,,615,577,8,8,https://rddev2.fit2cloud.com/dashboard/,12,0,0\n" +
|
||||||
|
"1584602498896,36,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-8,text,true,,8074,851,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=1b42574e-756d-4157-9987-a8e1df496718&login=true&scope=openid,36,0,0\n" +
|
||||||
|
"1584602498933,538,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-8,text,true,,1464736,4955,8,8,https://rddev2.fit2cloud.com/login,26,0,0\n" +
|
||||||
|
"1584602499605,0,https://rddev2.fit2cloud.com/dashboard/?state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1&code=efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc,Non HTTP response code: java.net.URISyntaxException,\"Non HTTP response message: Illegal character in query at index 45: https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",Thread Group 1-2,text,false,,1392,0,8,8,\"https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",0,0,0\n" +
|
||||||
|
"1584602499607,19,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,200,OK,Thread Group 1-2,text,true,,12424,560,8,8,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,19,0,0\n" +
|
||||||
|
"1584602499856,21,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-list.html?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,2516,572,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-list.html?_t=1577351137654,21,0,0\n" +
|
||||||
|
"1584602500034,27,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,200,OK,Thread Group 1-2,text,true,,1916,574,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,27,0,0\n" +
|
||||||
|
"1584602500182,23,https://rddev2.fit2cloud.com/dashboard/anonymous/license/validate?_nocache=1578039505321,200,OK,Thread Group 1-1,text,true,,288,566,8,8,https://rddev2.fit2cloud.com/dashboard/anonymous/license/validate?_nocache=1578039505321,23,0,0\n" +
|
||||||
|
"1584602500484,18,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,200,OK,Thread Group 1-2,text,true,,1570,582,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,18,0,0\n" +
|
||||||
|
"1584602500504,16,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-list.html?_t=1577351137654,200,OK,Thread Group 1-2,text,true,,2516,573,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-list.html?_t=1577351137654,16,0,0\n" +
|
||||||
|
"1584602500206,420,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321,200,OK,Thread Group 1-1,text,true,,1473342,5748,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fmodule%2Fall?_nocache%3D1578039505321&state=573519c4-a91b-4e46-b28d-f68231a8faf8&login=true&scope=openid,10,0,0\n" +
|
||||||
|
"1584602500206,10,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-0,302,Found,Thread Group 1-1,,true,,555,550,8,8,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321,10,0,0\n" +
|
||||||
|
"1584602500216,23,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-1,200,OK,Thread Group 1-1,text,true,,8038,1439,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fmodule%2Fall?_nocache%3D1578039505321&state=573519c4-a91b-4e46-b28d-f68231a8faf8&login=true&scope=openid,23,0,0\n" +
|
||||||
|
"1584602500243,383,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-2,200,OK,Thread Group 1-1,text,true,,1464749,3759,8,8,https://rddev2.fit2cloud.com/login,24,0,0\n" +
|
||||||
|
"1584602500622,18,https://rddev2.fit2cloud.com/dashboard/anonymous/license/validate?_nocache=1578039505321,200,OK,Thread Group 1-2,text,true,,288,567,8,8,https://rddev2.fit2cloud.com/dashboard/anonymous/license/validate?_nocache=1578039505321,18,0,0\n" +
|
||||||
|
"1584602500735,15,https://rddev2.fit2cloud.com/web-public/fit2cloud/html/loading/loading.html?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,503,506,8,8,https://rddev2.fit2cloud.com/web-public/fit2cloud/html/loading/loading.html?_t=1577351137654,15,0,0\n" +
|
||||||
|
"1584602501143,58,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-5,text,false,,4469,1746,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,58,0,4\n" +
|
||||||
|
"1584602501233,0,https://rddev2.fit2cloud.com/dashboard/?state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1&code=efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc,Non HTTP response code: java.net.URISyntaxException,\"Non HTTP response message: Illegal character in query at index 45: https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",Thread Group 1-5,text,false,,1392,0,8,8,\"https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",0,0,0\n" +
|
||||||
|
"1584602501234,19,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,200,OK,Thread Group 1-5,text,true,,12438,560,8,8,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,19,0,0\n" +
|
||||||
|
"1584602501253,17,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,200,OK,Thread Group 1-5,text,true,,1916,574,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,17,0,0\n" +
|
||||||
|
"1584602500841,509,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321,200,OK,Thread Group 1-2,text,true,,1473319,5757,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fmodule%2Fall?_nocache%3D1578039505321&state=c27f5334-b14f-43e8-ba3d-a31d6f385c32&login=true&scope=openid,13,0,0\n" +
|
||||||
|
"1584602500841,13,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-0,302,Found,Thread Group 1-2,,true,,555,551,8,8,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321,13,0,0\n" +
|
||||||
|
"1584602500855,29,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-1,200,OK,Thread Group 1-2,text,true,,8038,1440,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fmodule%2Fall?_nocache%3D1578039505321&state=c27f5334-b14f-43e8-ba3d-a31d6f385c32&login=true&scope=openid,29,0,0\n" +
|
||||||
|
"1584602500887,463,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-2,200,OK,Thread Group 1-2,text,true,,1464726,3766,8,8,https://rddev2.fit2cloud.com/login,26,0,0\n" +
|
||||||
|
"1584602501352,16,https://rddev2.fit2cloud.com/web-public/fit2cloud/html/loading/loading.html?_t=1577351137654,200,OK,Thread Group 1-2,text,true,,503,507,8,8,https://rddev2.fit2cloud.com/web-public/fit2cloud/html/loading/loading.html?_t=1577351137654,16,0,0\n" +
|
||||||
|
"1584602501458,13,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,200,OK,Thread Group 1-5,text,true,,1570,582,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,13,0,0\n" +
|
||||||
|
"1584602501663,17,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-list.html?_t=1577351137654,200,OK,Thread Group 1-5,text,true,,2516,573,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-list.html?_t=1577351137654,17,0,0\n" +
|
||||||
|
"1584602501435,359,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,200,OK,Thread Group 1-1,text,true,,1473387,6761,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=832af3d4-2ca4-4e23-bf2a-e14a01d27fc0&login=true&scope=openid,11,0,0\n" +
|
||||||
|
"1584602501435,11,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-0,302,Found,Thread Group 1-1,,true,,558,653,8,8,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,11,0,0\n" +
|
||||||
|
"1584602501446,22,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-1,200,OK,Thread Group 1-1,text,true,,8030,1614,8,8,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=832af3d4-2ca4-4e23-bf2a-e14a01d27fc0&login=true&scope=openid,22,0,0\n" +
|
||||||
|
"1584602501471,323,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-2,200,OK,Thread Group 1-1,text,true,,1464799,4494,8,8,https://rddev2.fit2cloud.com/login,23,0,0\n" +
|
||||||
|
"1584602501784,17,https://rddev2.fit2cloud.com/dashboard/anonymous/license/validate?_nocache=1578039505321,200,OK,Thread Group 1-5,text,true,,288,567,8,8,https://rddev2.fit2cloud.com/dashboard/anonymous/license/validate?_nocache=1578039505321,17,0,0\n" +
|
||||||
|
"1584602501907,304,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50,200,OK,Thread Group 1-1,text,true,,1473471,6749,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fnotification%2Flist%2Funread%2F1%2F50&state=1904f64b-a8f9-44d8-867e-359cfe46297f&login=true&scope=openid,10,0,0\n" +
|
||||||
|
"1584602501907,10,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-0,302,Found,Thread Group 1-1,,true,,555,652,10,10,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50,10,0,0\n" +
|
||||||
|
"1584602501917,24,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-1,200,OK,Thread Group 1-1,text,true,,8021,1603,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fnotification%2Flist%2Funread%2F1%2F50&state=1904f64b-a8f9-44d8-867e-359cfe46297f&login=true&scope=openid,24,0,0\n" +
|
||||||
|
"1584602501943,268,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-2,200,OK,Thread Group 1-1,text,true,,1464895,4494,10,10,https://rddev2.fit2cloud.com/login,23,0,0\n" +
|
||||||
|
"1584602502213,16,https://rddev2.fit2cloud.com/web-public/project/html/pagination.html?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,1162,499,10,10,https://rddev2.fit2cloud.com/web-public/project/html/pagination.html?_t=1577351137654,16,0,0\n" +
|
||||||
|
"1584602501802,513,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321,200,OK,Thread Group 1-5,text,true,,1473342,5757,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fmodule%2Fall?_nocache%3D1578039505321&state=7d3aea03-3217-44da-81be-35c41c1db2d7&login=true&scope=openid,15,0,0\n" +
|
||||||
|
"1584602501802,15,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-0,302,Found,Thread Group 1-5,,true,,555,551,10,10,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321,15,0,0\n" +
|
||||||
|
"1584602501817,23,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-1,200,OK,Thread Group 1-5,text,true,,8038,1440,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fmodule%2Fall?_nocache%3D1578039505321&state=7d3aea03-3217-44da-81be-35c41c1db2d7&login=true&scope=openid,23,0,0\n" +
|
||||||
|
"1584602501842,473,https://rddev2.fit2cloud.com/dashboard/module/all?_nocache=1578039505321-2,200,OK,Thread Group 1-5,text,true,,1464749,3766,10,10,https://rddev2.fit2cloud.com/login,18,0,0\n" +
|
||||||
|
"1584602502316,28,https://rddev2.fit2cloud.com/web-public/fit2cloud/html/loading/loading.html?_t=1577351137654,200,OK,Thread Group 1-5,text,true,,503,507,10,10,https://rddev2.fit2cloud.com/web-public/fit2cloud/html/loading/loading.html?_t=1577351137654,28,0,0\n" +
|
||||||
|
"1584602502110,631,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-10,text,true,,1473668,6950,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=26792af8-d8cd-4ed6-b0e0-68ad7220004f&login=true&scope=openid,63,0,1\n" +
|
||||||
|
"1584602502110,63,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-10,,true,,214,567,10,10,https://rddev2.fit2cloud.com/,63,0,1\n" +
|
||||||
|
"1584602502173,15,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-10,,true,,615,577,10,10,https://rddev2.fit2cloud.com/dashboard/,15,0,0\n" +
|
||||||
|
"1584602502189,39,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-10,text,true,,8074,851,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=26792af8-d8cd-4ed6-b0e0-68ad7220004f&login=true&scope=openid,39,0,0\n" +
|
||||||
|
"1584602502229,512,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-10,text,true,,1464765,4955,10,10,https://rddev2.fit2cloud.com/login,18,0,0\n" +
|
||||||
|
"1584602502169,625,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,200,OK,Thread Group 1-2,text,true,,1473329,6770,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=7bfdeacf-3f22-449d-88f9-f0d792bfe1bb&login=true&scope=openid,19,0,0\n" +
|
||||||
|
"1584602502169,19,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-0,302,Found,Thread Group 1-2,,true,,558,654,10,10,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,19,0,0\n" +
|
||||||
|
"1584602502189,32,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-1,200,OK,Thread Group 1-2,text,true,,8030,1615,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=7bfdeacf-3f22-449d-88f9-f0d792bfe1bb&login=true&scope=openid,32,0,0\n" +
|
||||||
|
"1584602502222,572,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-2,200,OK,Thread Group 1-2,text,true,,1464741,4501,10,10,https://rddev2.fit2cloud.com/login,21,0,0\n" +
|
||||||
|
"1584602502110,713,https://rddev2.fit2cloud.com/,200,OK,Thread Group 1-9,text,true,,1473667,6942,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=cb0aadfc-16eb-486b-b7f1-2c2df1c3231c&login=true&scope=openid,63,0,1\n" +
|
||||||
|
"1584602502110,63,https://rddev2.fit2cloud.com/-0,302,Found,Thread Group 1-9,,true,,214,567,10,10,https://rddev2.fit2cloud.com/,63,0,1\n" +
|
||||||
|
"1584602502174,21,https://rddev2.fit2cloud.com/-1,302,Found,Thread Group 1-9,,true,,614,577,10,10,https://rddev2.fit2cloud.com/dashboard/,21,0,0\n" +
|
||||||
|
"1584602502195,34,https://rddev2.fit2cloud.com/-2,200,OK,Thread Group 1-9,text,true,,8074,850,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2F&state=cb0aadfc-16eb-486b-b7f1-2c2df1c3231c&login=true&scope=openid,34,0,0\n" +
|
||||||
|
"1584602502231,592,https://rddev2.fit2cloud.com/-3,200,OK,Thread Group 1-9,text,true,,1464765,4948,10,10,https://rddev2.fit2cloud.com/login,21,0,0\n" +
|
||||||
|
"1584602502434,434,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,200,OK,Thread Group 1-1,text,true,,1473315,6926,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=b2a99afa-66a7-411d-bba9-239c9b20de82&login=true&scope=openid,18,0,0\n" +
|
||||||
|
"1584602502434,18,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-0,302,Found,Thread Group 1-1,,true,,558,731,10,10,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,18,0,0\n" +
|
||||||
|
"1584602502452,27,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-1,200,OK,Thread Group 1-1,text,true,,8024,1603,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=b2a99afa-66a7-411d-bba9-239c9b20de82&login=true&scope=openid,27,0,0\n" +
|
||||||
|
"1584602502481,387,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-2,200,OK,Thread Group 1-1,text,true,,1464733,4592,10,10,https://rddev2.fit2cloud.com/login,25,0,0\n" +
|
||||||
|
"1584602502839,65,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-3,text,false,,4462,1746,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,65,0,1\n" +
|
||||||
|
"1584602502961,0,https://rddev2.fit2cloud.com/dashboard/?state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1&code=efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc,Non HTTP response code: java.net.URISyntaxException,\"Non HTTP response message: Illegal character in query at index 45: https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",Thread Group 1-3,text,false,,1392,0,10,10,\"https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",0,0,0\n" +
|
||||||
|
"1584602503108,27,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,200,OK,Thread Group 1-3,text,true,,12438,560,10,10,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,27,0,0\n" +
|
||||||
|
"1584602503239,23,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,200,OK,Thread Group 1-3,text,true,,1916,574,10,10,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,23,0,0\n" +
|
||||||
|
"1584602503006,262,https://rddev2.fit2cloud.com/dashboard/user/current/info?_nocache=1578039505484,200,OK,Thread Group 1-1,text,true,,1473599,5844,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fuser%2Fcurrent%2Finfo?_nocache%3D1578039505484&state=10ff89f8-c521-42a3-99bd-d2929d4260cc&login=true&scope=openid,14,0,0\n" +
|
||||||
|
"1584602503006,14,https://rddev2.fit2cloud.com/dashboard/user/current/info?_nocache=1578039505484-0,302,Found,Thread Group 1-1,,true,,564,557,10,10,https://rddev2.fit2cloud.com/dashboard/user/current/info?_nocache=1578039505484,14,0,0\n" +
|
||||||
|
"1584602503021,22,https://rddev2.fit2cloud.com/dashboard/user/current/info?_nocache=1578039505484-1,200,OK,Thread Group 1-1,text,true,,8056,1528,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fuser%2Fcurrent%2Finfo?_nocache%3D1578039505484&state=10ff89f8-c521-42a3-99bd-d2929d4260cc&login=true&scope=openid,22,0,0\n" +
|
||||||
|
"1584602503047,221,https://rddev2.fit2cloud.com/dashboard/user/current/info?_nocache=1578039505484-2,200,OK,Thread Group 1-1,text,true,,1464979,3759,10,10,https://rddev2.fit2cloud.com/login,20,0,0\n" +
|
||||||
|
"1584602502806,506,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50,200,OK,Thread Group 1-2,text,true,,1473450,6758,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fnotification%2Flist%2Funread%2F1%2F50&state=f4ac4eb9-f92a-4bcc-8214-3eac6df6d1c9&login=true&scope=openid,12,0,0\n" +
|
||||||
|
"1584602502806,12,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-0,302,Found,Thread Group 1-2,,true,,555,653,10,10,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50,12,0,0\n" +
|
||||||
|
"1584602502819,26,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-1,200,OK,Thread Group 1-2,text,true,,8027,1604,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fnotification%2Flist%2Funread%2F1%2F50&state=f4ac4eb9-f92a-4bcc-8214-3eac6df6d1c9&login=true&scope=openid,26,0,0\n" +
|
||||||
|
"1584602502846,466,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-2,200,OK,Thread Group 1-2,text,true,,1464868,4501,10,10,https://rddev2.fit2cloud.com/login,15,0,0\n" +
|
||||||
|
"1584602503314,13,https://rddev2.fit2cloud.com/web-public/project/html/pagination.html?_t=1577351137654,200,OK,Thread Group 1-2,text,true,,1162,500,10,10,https://rddev2.fit2cloud.com/web-public/project/html/pagination.html?_t=1577351137654,13,0,0\n" +
|
||||||
|
"1584602503471,15,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/header-menu.html?_t=1577351137654,200,OK,Thread Group 1-1,text,true,,3117,574,10,10,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/header-menu.html?_t=1577351137654,15,0,0\n" +
|
||||||
|
"1584602503471,54,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-4,text,false,,4462,1747,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,54,0,4\n" +
|
||||||
|
"1584602503569,0,https://rddev2.fit2cloud.com/dashboard/?state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1&code=efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc,Non HTTP response code: java.net.URISyntaxException,\"Non HTTP response message: Illegal character in query at index 45: https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",Thread Group 1-4,text,false,,1392,0,10,10,\"https://rddev2.fit2cloud.com/dashboard/?code=\n" +
|
||||||
|
" efe49afa-7afb-4c38-8e0c-38323291938c.191d0330-dd9f-4bb0-8c24-0e3df46e2ff1.fd56cca3-6d54-44aa-b879-a35e79fc1bfc\n" +
|
||||||
|
" &state=3d31fe47-47bd-47f2-950d-9d135e0600ef&session_state=191d0330-dd9f-4bb0-8c24-0e3df46e2ff1\",0,0,0\n" +
|
||||||
|
"1584602503108,494,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,200,OK,Thread Group 1-5,text,true,,1473344,6770,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=bbc579c2-fce7-4f4c-a9e0-9e27c818248c&login=true&scope=openid,21,0,0\n" +
|
||||||
|
"1584602503108,21,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-0,302,Found,Thread Group 1-5,,true,,558,654,10,10,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,21,0,0\n" +
|
||||||
|
"1584602503129,39,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-1,200,OK,Thread Group 1-5,text,true,,8030,1615,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=bbc579c2-fce7-4f4c-a9e0-9e27c818248c&login=true&scope=openid,39,0,0\n" +
|
||||||
|
"1584602503170,432,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-2,200,OK,Thread Group 1-5,text,true,,1464756,4501,10,10,https://rddev2.fit2cloud.com/login,25,0,0\n" +
|
||||||
|
"1584602503607,363,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50,200,OK,Thread Group 1-5,text,true,,1473560,6758,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fnotification%2Flist%2Funread%2F1%2F50&state=db071ff5-a114-4a0d-b693-fd1d8e477e75&login=true&scope=openid,12,0,0\n" +
|
||||||
|
"1584602503607,12,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-0,302,Found,Thread Group 1-5,,true,,555,653,10,10,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50,12,0,0\n" +
|
||||||
|
"1584602503619,23,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-1,200,OK,Thread Group 1-5,text,true,,8027,1604,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fnotification%2Flist%2Funread%2F1%2F50&state=db071ff5-a114-4a0d-b693-fd1d8e477e75&login=true&scope=openid,23,0,0\n" +
|
||||||
|
"1584602503644,326,https://rddev2.fit2cloud.com/dashboard/notification/list/unread/1/50-2,200,OK,Thread Group 1-5,text,true,,1464978,4501,10,10,https://rddev2.fit2cloud.com/login,18,0,0\n" +
|
||||||
|
"1584602503971,15,https://rddev2.fit2cloud.com/web-public/project/html/pagination.html?_t=1577351137654,200,OK,Thread Group 1-5,text,true,,1162,500,10,10,https://rddev2.fit2cloud.com/web-public/project/html/pagination.html?_t=1577351137654,15,0,0\n" +
|
||||||
|
"1584602503971,19,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,200,OK,Thread Group 1-4,text,true,,12438,561,10,10,https://rddev2.fit2cloud.com/dashboard/anonymous/i18n/en_US.json?_t=1577351137654,19,0,0\n" +
|
||||||
|
"1584602503792,32,https://rddev2.fit2cloud.com/dashboard/user/source/list?_nocache=1578039505551,200,OK,Thread Group 1-1,text,true,,8617,2109,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fuser%2Fsource%2Flist?_nocache%3D1578039505551&state=2bc90b74-8d32-4217-a573-bfbd969b6b16&login=true&scope=openid,10,0,0\n" +
|
||||||
|
"1584602503792,10,https://rddev2.fit2cloud.com/dashboard/user/source/list?_nocache=1578039505551-0,302,Found,Thread Group 1-1,,true,,563,556,10,10,https://rddev2.fit2cloud.com/dashboard/user/source/list?_nocache=1578039505551,10,0,0\n" +
|
||||||
|
"1584602503803,21,https://rddev2.fit2cloud.com/dashboard/user/source/list?_nocache=1578039505551-1,200,OK,Thread Group 1-1,text,true,,8054,1553,10,10,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fuser%2Fsource%2Flist?_nocache%3D1578039505551&state=2bc90b74-8d32-4217-a573-bfbd969b6b16&login=true&scope=openid,21,0,0\n" +
|
||||||
|
"1584602504095,21,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-9,text,false,,4469,1745,9,9,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,21,0,0\n" +
|
||||||
|
"1584602504100,20,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,200,OK,Thread Group 1-4,text,true,,1916,575,8,8,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/task-menus.html?_t=1577351137654,20,0,0\n" +
|
||||||
|
"1584602504095,27,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-10,text,false,,4462,1746,7,7,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,27,0,0\n" +
|
||||||
|
"1584602504095,39,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,200,OK,Thread Group 1-2,text,true,,8588,2336,6,6,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=24c9d65b-0421-4732-8193-0bf5f70b3fa4&login=true&scope=openid,13,0,0\n" +
|
||||||
|
"1584602504095,13,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-0,302,Found,Thread Group 1-2,,true,,558,732,6,6,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50,13,0,0\n" +
|
||||||
|
"1584602504108,26,https://rddev2.fit2cloud.com/dashboard/flow/runtime/task/pending/1/50-1,200,OK,Thread Group 1-2,text,true,,8030,1604,6,6,https://rddev2.fit2cloud.com/auth/realms/cmp/protocol/openid-connect/auth?response_type=code&client_id=cmp-client&redirect_uri=https%3A%2F%2Frddev2.fit2cloud.com%2Fdashboard%2Fflow%2Fruntime%2Ftask%2Fpending%2F1%2F50&state=24c9d65b-0421-4732-8193-0bf5f70b3fa4&login=true&scope=openid,26,0,0\n" +
|
||||||
|
"1584602504095,55,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-8,text,false,,4469,1746,5,5,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,55,0,3\n" +
|
||||||
|
"1584602504095,59,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-6,text,false,,4462,1747,4,4,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,59,0,4\n" +
|
||||||
|
"1584602504095,65,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate?session_code=YWUneSay4qlQuHRZsD4kPaZDIIR50KJLaNpW7uhsD-Q&execution=c7620733-54ab-46b2-802b-66764e42682b&client_id=cmp-client&tab_id=S8xOQPgCmhQ,400,Bad Request,Thread Group 1-7,text,false,,4469,1745,3,3,https://rddev2.fit2cloud.com/auth/realms/cmp/login-actions/authenticate,65,0,4\n" +
|
||||||
|
"1584602504200,12,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,200,OK,Thread Group 1-3,text,true,,1570,582,2,2,https://rddev2.fit2cloud.com/dashboard/web-public/project/html/notification-menus.html?_t=1577351137654,12,0,0\n";
|
||||||
|
List<Metric> metrics = beanBuilderExample(jtlString);
|
||||||
|
Map<String, List<Metric>> map = metrics.stream().collect(Collectors.groupingBy(Metric::getLabel));
|
||||||
|
getOneRpsResult(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getOneRpsResult(Map<String, List<Metric>> map){
|
||||||
|
Iterator<Map.Entry<String, List<Metric>>> iterator = map.entrySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<String, List<Metric>> entry = iterator.next();
|
||||||
|
String label = entry.getKey();
|
||||||
|
List<Metric> list = entry.getValue();
|
||||||
|
List<String> timestampList = list.stream().map(Metric::getTimestamp).collect(Collectors.toList());
|
||||||
|
int index=0;
|
||||||
|
//总的响应时间
|
||||||
|
int sumElapsed=0;
|
||||||
|
Integer failSize = 0;
|
||||||
|
Integer totalBytes = 0;
|
||||||
|
List<Integer> elapsedList = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
try {
|
||||||
|
Metric row = list.get(i);
|
||||||
|
//响应时间
|
||||||
|
String elapsed = row.getElapsed();
|
||||||
|
sumElapsed += Integer.valueOf(elapsed);
|
||||||
|
elapsedList.add(Integer.valueOf(elapsed));
|
||||||
|
//成功与否
|
||||||
|
String success = row.getSuccess();
|
||||||
|
if (!"true".equals(success)){
|
||||||
|
failSize++;
|
||||||
|
}
|
||||||
|
//字节
|
||||||
|
String bytes = row.getBytes();
|
||||||
|
totalBytes += Integer.valueOf(bytes);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("exception i:"+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(elapsedList, new Comparator<Integer>() {
|
||||||
|
public int compare(Integer o1, Integer o2) {
|
||||||
|
return o1-o2;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Integer tp90 = elapsedList.size()*9/10;
|
||||||
|
Integer tp95 = elapsedList.size()*95/100;
|
||||||
|
Integer tp99 = elapsedList.size()*99/100;
|
||||||
|
|
||||||
|
Long l = Long.valueOf(timestampList.get(index-1)) - Long.valueOf(timestampList.get(0));
|
||||||
|
|
||||||
|
RequestStatistics sceneResult = new RequestStatistics();
|
||||||
|
sceneResult.setRequestLabel(label);
|
||||||
|
sceneResult.setSamples(index+"");
|
||||||
|
sceneResult.setAverage(sumElapsed/index+"");
|
||||||
|
sceneResult.setTp90(elapsedList.get(tp90)+"");
|
||||||
|
sceneResult.setTp95(elapsedList.get(tp95)+"");
|
||||||
|
sceneResult.setTp99(elapsedList.get(tp99)+"");
|
||||||
|
sceneResult.setMin(elapsedList.get(0)+"");
|
||||||
|
sceneResult.setMax(elapsedList.get(index-1)+"");
|
||||||
|
sceneResult.setErrors(String.format("%.2f",failSize*100.0/index)+"%");
|
||||||
|
sceneResult.setKbPerSec(String.format("%.2f",totalBytes*1.0/1024/(l*1.0/1000)));
|
||||||
|
System.out.println(JSONObject.toJSONString(sceneResult));
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
package io.metersphere;
|
||||||
|
|
||||||
|
import com.opencsv.bean.CsvBindByName;
|
||||||
|
|
||||||
|
public class Metric {
|
||||||
|
// timestamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect
|
||||||
|
|
||||||
|
@CsvBindByName(column = "timestamp")
|
||||||
|
private String timestamp;
|
||||||
|
@CsvBindByName(column = "elapsed")
|
||||||
|
private String elapsed;
|
||||||
|
@CsvBindByName(column = "label")
|
||||||
|
private String label;
|
||||||
|
@CsvBindByName(column = "responseCode")
|
||||||
|
private String responseCode;
|
||||||
|
@CsvBindByName(column = "responseMessage")
|
||||||
|
private String responseMessage;
|
||||||
|
@CsvBindByName(column = "threadName")
|
||||||
|
private String threadName;
|
||||||
|
@CsvBindByName(column = "dataType")
|
||||||
|
private String dataType;
|
||||||
|
@CsvBindByName(column = "success")
|
||||||
|
private String success;
|
||||||
|
@CsvBindByName(column = "failureMessage")
|
||||||
|
private String failureMessage;
|
||||||
|
@CsvBindByName(column = "bytes")
|
||||||
|
private String bytes;
|
||||||
|
@CsvBindByName(column = "sentBytes")
|
||||||
|
private String sentBytes;
|
||||||
|
@CsvBindByName(column = "grpThreads")
|
||||||
|
private String grpThreads;
|
||||||
|
@CsvBindByName(column = "allThreads")
|
||||||
|
private String allThreads;
|
||||||
|
@CsvBindByName(column = "URL")
|
||||||
|
private String url;
|
||||||
|
@CsvBindByName(column = "Latency")
|
||||||
|
private String latency;
|
||||||
|
@CsvBindByName(column = "IdleTime")
|
||||||
|
private String idleTime;
|
||||||
|
@CsvBindByName(column = "Connect")
|
||||||
|
private String connect;
|
||||||
|
|
||||||
|
|
||||||
|
public String getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(String timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElapsed() {
|
||||||
|
return elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElapsed(String elapsed) {
|
||||||
|
this.elapsed = elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabel(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseCode() {
|
||||||
|
return responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseCode(String responseCode) {
|
||||||
|
this.responseCode = responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseMessage() {
|
||||||
|
return responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseMessage(String responseMessage) {
|
||||||
|
this.responseMessage = responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getThreadName() {
|
||||||
|
return threadName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThreadName(String threadName) {
|
||||||
|
this.threadName = threadName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataType() {
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataType(String dataType) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSuccess(String success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFailureMessage() {
|
||||||
|
return failureMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFailureMessage(String failureMessage) {
|
||||||
|
this.failureMessage = failureMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBytes() {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBytes(String bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSentBytes() {
|
||||||
|
return sentBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSentBytes(String sentBytes) {
|
||||||
|
this.sentBytes = sentBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrpThreads() {
|
||||||
|
return grpThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrpThreads(String grpThreads) {
|
||||||
|
this.grpThreads = grpThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAllThreads() {
|
||||||
|
return allThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllThreads(String allThreads) {
|
||||||
|
this.allThreads = allThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLatency() {
|
||||||
|
return latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLatency(String latency) {
|
||||||
|
this.latency = latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdleTime() {
|
||||||
|
return idleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdleTime(String idleTime) {
|
||||||
|
this.idleTime = idleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConnect() {
|
||||||
|
return connect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnect(String connect) {
|
||||||
|
this.connect = connect;
|
||||||
|
}
|
||||||
|
}
|
|
@ -207,6 +207,10 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.$refs.pressureConfig.validConfig()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.$refs.advancedConfig.validConfig()) {
|
if (!this.$refs.advancedConfig.validConfig()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,21 @@
|
||||||
<div>{{$t('load_test.ramp_up_time_times')}}</div>
|
<div>{{$t('load_test.ramp_up_time_times')}}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
<el-form :inline="true" class="input-bottom-border">
|
||||||
|
<el-form-item>
|
||||||
|
<div>{{$t('load_test.select_resource_pool')}}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-select v-model="resourcePool" size="mini">
|
||||||
|
<el-option
|
||||||
|
v-for="item in resourcePools"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<chart class="chart-container" ref="chart1" :options="orgOptions" :autoresize="true"></chart>
|
<chart class="chart-container" ref="chart1" :options="orgOptions" :autoresize="true"></chart>
|
||||||
|
@ -89,6 +104,7 @@
|
||||||
const STEPS = "Steps";
|
const STEPS = "Steps";
|
||||||
const DURATION = "duration";
|
const DURATION = "duration";
|
||||||
const RPS_LIMIT = "rpsLimit";
|
const RPS_LIMIT = "rpsLimit";
|
||||||
|
const RESOURCE_POOL = "resourcePoolId";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PerformancePressureConfig",
|
name: "PerformancePressureConfig",
|
||||||
|
@ -101,6 +117,8 @@
|
||||||
step: 10,
|
step: 10,
|
||||||
rpsLimit: 10,
|
rpsLimit: 10,
|
||||||
orgOptions: {},
|
orgOptions: {},
|
||||||
|
resourcePool: null,
|
||||||
|
resourcePools: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -110,6 +128,8 @@
|
||||||
} else {
|
} else {
|
||||||
this.calculateChart();
|
this.calculateChart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.getResourcePools();
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route'(to, from) {
|
'$route'(to, from) {
|
||||||
|
@ -125,11 +145,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getResourcePools() {
|
||||||
|
this.$get('/testresourcepool/list/all', response => {
|
||||||
|
this.resourcePools = response.data;
|
||||||
|
})
|
||||||
|
},
|
||||||
getLoadConfig(testId) {
|
getLoadConfig(testId) {
|
||||||
if (testId) {
|
if (testId) {
|
||||||
|
|
||||||
this.$get('/testplan/get-load-config/' + testId, (response) => {
|
this.$get('/testplan/get-load-config/' + testId, (response) => {
|
||||||
if (response.data && response.data != "") {
|
if (response.data) {
|
||||||
let data = JSON.parse(response.data);
|
let data = JSON.parse(response.data);
|
||||||
|
|
||||||
data.forEach(d => {
|
data.forEach(d => {
|
||||||
|
@ -149,6 +174,9 @@
|
||||||
case RPS_LIMIT:
|
case RPS_LIMIT:
|
||||||
this.rpsLimit = d.value;
|
this.rpsLimit = d.value;
|
||||||
break;
|
break;
|
||||||
|
case RESOURCE_POOL:
|
||||||
|
this.resourcePool = d.value;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -252,6 +280,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
validConfig() {
|
||||||
|
if (!this.resourcePool) {
|
||||||
|
this.$message({
|
||||||
|
message: this.$t('load_test.resource_pool_is_null'),
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
convertProperty() {
|
convertProperty() {
|
||||||
/// todo:下面4个属性是jmeter ConcurrencyThreadGroup plugin的属性,这种硬编码不太好吧,在哪能转换这种属性?
|
/// todo:下面4个属性是jmeter ConcurrencyThreadGroup plugin的属性,这种硬编码不太好吧,在哪能转换这种属性?
|
||||||
return [
|
return [
|
||||||
|
@ -259,7 +298,8 @@
|
||||||
{key: RAMP_UP, value: this.rampUpTime},
|
{key: RAMP_UP, value: this.rampUpTime},
|
||||||
{key: STEPS, value: this.step},
|
{key: STEPS, value: this.step},
|
||||||
{key: DURATION, value: this.duration},
|
{key: DURATION, value: this.duration},
|
||||||
{key: RPS_LIMIT, value: this.rpsLimit}
|
{key: RPS_LIMIT, value: this.rpsLimit},
|
||||||
|
{key: RESOURCE_POOL, value: this.resourcePool},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog :title="title" :visible.sync="createVisible">
|
<el-dialog :title="title" :visible.sync="createVisible">
|
||||||
<el-form :model="form" :rules="rules" ref="form" label-position="left" label-width="100px" size="small">
|
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.name')">
|
<el-form-item :label="$t('commons.name')">
|
||||||
<el-input v-model="form.name" autocomplete="off"></el-input>
|
<el-input v-model="form.name" autocomplete="off"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" ref="form" :rules="rules" label-position="left" label-width="100px" size="small">
|
<el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||||
<el-select v-model="form.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
<el-select v-model="form.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog :title="$t('workspace.create')" :visible.sync="createVisible" width="30%">
|
<el-dialog :title="$t('workspace.create')" :visible.sync="createVisible" width="30%">
|
||||||
<el-form :model="form" :rules="rules" ref="form" label-position="left" label-width="100px" size="small">
|
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
|
|
||||||
<!-- add workspace member dialog -->
|
<!-- add workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="left" label-width="100px" size="small">
|
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||||
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -145,7 +145,7 @@
|
||||||
|
|
||||||
<!-- update workspace member dialog -->
|
<!-- update workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="memberForm" label-position="left" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-dialog :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule" ref="updateUserForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
|
|
||||||
<!-- add organization form -->
|
<!-- add organization form -->
|
||||||
<el-dialog :title="$t('organization.create')" :visible.sync="createVisible" width="30%" @closed="closeFunc" :destroy-on-close="true">
|
<el-dialog :title="$t('organization.create')" :visible.sync="createVisible" width="30%" @closed="closeFunc" :destroy-on-close="true">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule" ref="createOrganization">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" ref="createOrganization">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
|
|
||||||
<!-- update organization form -->
|
<!-- update organization form -->
|
||||||
<el-dialog :title="$t('organization.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('organization.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule" ref="updateOrganizationForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" ref="updateOrganizationForm">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
|
|
||||||
<!-- add organization member form -->
|
<!-- add organization member form -->
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="memberForm" ref="form" :rules="orgMemberRule" label-position="left" label-width="100px" size="small">
|
<el-form :model="memberForm" ref="form" :rules="orgMemberRule" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||||
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -162,7 +162,7 @@
|
||||||
|
|
||||||
<!-- update organization member form -->
|
<!-- update organization member form -->
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="memberForm" label-position="left" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
|
|
||||||
<!-- add workspace dialog -->
|
<!-- add workspace dialog -->
|
||||||
<el-dialog :title="$t('workspace.create')" :visible.sync="createVisible" width="30%">
|
<el-dialog :title="$t('workspace.create')" :visible.sync="createVisible" width="30%">
|
||||||
<el-form :model="form" :rules="rules" ref="form" label-position="left" label-width="100px" size="small">
|
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
|
|
||||||
<!-- update workspace dialog -->
|
<!-- update workspace dialog -->
|
||||||
<el-dialog :title="$t('workspace.update')" :visible.sync="updateVisible" width="30%">
|
<el-dialog :title="$t('workspace.update')" :visible.sync="updateVisible" width="30%">
|
||||||
<el-form :model="form" :rules="rules" ref="updateForm" label-position="left" label-width="100px" size="small">
|
<el-form :model="form" :rules="rules" ref="updateForm" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -154,7 +154,7 @@
|
||||||
|
|
||||||
<!-- add workspace member dialog -->
|
<!-- add workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="left" label-width="100px" size="small">
|
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||||
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -185,7 +185,7 @@
|
||||||
|
|
||||||
<!-- update workspace member dialog -->
|
<!-- update workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="memberForm" label-position="left" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -69,8 +69,9 @@
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog title="创建资源池" :visible.sync="createVisible" width="70%" @closed="closeFunc" :destroy-on-close="true">
|
<el-dialog v-loading="testLoading" title="创建资源池" :visible.sync="createVisible" width="70%" @closed="closeFunc"
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule"
|
:destroy-on-close="true">
|
||||||
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
|
||||||
ref="createTestResourcePoolForm">
|
ref="createTestResourcePoolForm">
|
||||||
<el-form-item label="名称" prop="name">
|
<el-form-item label="名称" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
|
@ -85,46 +86,41 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-for="(item,index) in infoList " :key="index">
|
<div v-for="(item,index) in infoList " :key="index">
|
||||||
<div class="current-row" v-if="form.type === 'K8S'">
|
<div class="node-line" v-if="form.type === 'K8S'">
|
||||||
<div style="width: 35%;float: left">
|
<div class="k8s-master">
|
||||||
<label class="el-form-item__label">Master URL</label>
|
<el-col :span="11">
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
|
||||||
<input v-model="item.masterUrl" autocomplete="off" class="el-input__inner form-input"/>
|
</el-col>
|
||||||
</div>
|
<el-form-item prop="masterUrl" label="Master URL">
|
||||||
</div>
|
<el-input v-model="item.masterUrl" autocomplete="off"/>
|
||||||
<div style="width: 35%;float: left">
|
</el-form-item>
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">Token</label>
|
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
|
||||||
<input v-model="item.token" autocomplete="off" class="el-input__inner form-input"/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="k8s-token">
|
||||||
|
<el-form-item prop="token" label="Token">
|
||||||
|
<el-input v-model="item.token" show-password autocomplete="off"/>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 30%;float: left">
|
<div style="width: 30%;float: left">
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">最大并发数</label>
|
<el-form-item prop="maxConcurrency" label="最大并发数">
|
||||||
<div class="el-form-item__content" style="margin-left: 102px">
|
<el-input-number v-model="item.maxConcurrency" :min="1" :max="9999"></el-input-number>
|
||||||
<input v-model="item.maxConcurrency" autocomplete="off" type="number"
|
</el-form-item>
|
||||||
class="el-input__inner form-input"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="node-line" v-if="form.type === 'NODE'">
|
||||||
|
<div style="width: 30%;float: left">
|
||||||
|
<el-form-item prop="ip" label="IP">
|
||||||
|
<el-input v-model="item.ip" autocomplete="off"/>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="current-row" v-if="form.type === 'NODE'">
|
<div style="width: 30%;float: left">
|
||||||
<div style="width: 42%;float: left">
|
<el-form-item prop="port" label="Port">
|
||||||
<label class="el-form-item__label">IP</label>
|
<el-input-number v-model="item.port" :min="1" :max="9999"></el-input-number>
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
</el-form-item>
|
||||||
<input v-model="item.ip" autocomplete="off" class="el-input__inner form-input"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 20%;float: left">
|
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">port</label>
|
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
|
||||||
<input v-model="item.port" autocomplete="off" type="number" class="el-input__inner form-input"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 20%;float: left">
|
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">最大并发数</label>
|
|
||||||
<div class="el-form-item__content" style="margin-left: 102px">
|
|
||||||
<input v-model="item.maxConcurrency" autocomplete="off" type="number"
|
|
||||||
class="el-input__inner form-input"/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="width: 30%;float: left">
|
||||||
|
<el-form-item prop="maxConcurrency" label="最大并发数">
|
||||||
|
<el-input-number v-model="item.maxConcurrency" :min="1" :max="9999"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="op">
|
<div class="op">
|
||||||
<span class="box">
|
<span class="box">
|
||||||
|
@ -148,8 +144,9 @@
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog title="修改资源池" :visible.sync="updateVisible" width="70%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog v-loading="testLoading" title="修改资源池" :visible.sync="updateVisible" width="70%" :destroy-on-close="true"
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule"
|
@close="closeFunc">
|
||||||
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
|
||||||
ref="updateTestResourcePoolForm">
|
ref="updateTestResourcePoolForm">
|
||||||
<el-form-item label="名称" prop="name">
|
<el-form-item label="名称" prop="name">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
|
@ -158,52 +155,44 @@
|
||||||
<el-input v-model="form.description" autocomplete="off"/>
|
<el-input v-model="form.description" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="资源类型" prop="type">
|
<el-form-item label="资源类型" prop="type">
|
||||||
<el-select v-model="form.type" placeholder="选择资源类型">
|
<el-select v-model="form.type" placeholder="选择资源类型" @change="changeResourceType()">
|
||||||
<el-option key="K8S" value="K8S" label="Kubernetes">Kubernetes</el-option>
|
<el-option key="K8S" value="K8S" label="Kubernetes">Kubernetes</el-option>
|
||||||
<el-option key="NODE" value="NODE" label="独立节点">独立节点</el-option>
|
<el-option key="NODE" value="NODE" label="独立节点">独立节点</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-for="(item,index) in infoList " :key="index">
|
<div v-for="(item,index) in infoList " :key="index">
|
||||||
<div class="current-row" v-if="form.type === 'K8S'">
|
<div class="node-line" v-if="form.type === 'K8S'">
|
||||||
<div style="width: 35%;float: left">
|
<div class="k8s-master">
|
||||||
<label class="el-form-item__label">Master URL</label>
|
<el-form-item prop="masterUrl" label="Master URL">
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
<el-input v-model="item.masterUrl" autocomplete="off"/>
|
||||||
<input v-model="item.masterUrl" autocomplete="off" class="el-input__inner form-input"/>
|
</el-form-item>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 35%;float: left">
|
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">Token</label>
|
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
|
||||||
<input v-model="item.token" autocomplete="off" class="el-input__inner form-input"/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="k8s-token">
|
||||||
|
<el-form-item prop="password" label="Token" style="padding-left: 20px">
|
||||||
|
<el-input v-model="item.token" show-password autocomplete="off"/>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 30%;float: left">
|
<div style="width: 30%;float: left">
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">最大并发数</label>
|
<el-form-item prop="maxConcurrency" label="最大并发数" style="padding-left: 20px">
|
||||||
<div class="el-form-item__content" style="margin-left: 102px">
|
<el-input-number v-model="item.maxConcurrency" :min="1" :max="9999"></el-input-number>
|
||||||
<input v-model="item.maxConcurrency" autocomplete="off" type="number"
|
</el-form-item>
|
||||||
class="el-input__inner form-input"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="node-line" v-if="form.type === 'NODE'">
|
||||||
|
<div style="width: 30%;float: left">
|
||||||
|
<el-form-item prop="ip" label="IP">
|
||||||
|
<el-input v-model="item.ip" autocomplete="off"/>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="current-row" v-if="form.type === 'NODE'">
|
<div style="width: 30%;float: left">
|
||||||
<div style="width: 42%;float: left">
|
<el-form-item prop="port" label="Port" style="padding-left: 20px">
|
||||||
<label class="el-form-item__label">IP</label>
|
<el-input-number v-model="item.port" :min="1" :max="9999"></el-input-number>
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
</el-form-item>
|
||||||
<input v-model="item.ip" autocomplete="off" class="el-input__inner form-input"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 20%;float: left">
|
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">port</label>
|
|
||||||
<div class="el-form-item__content" style="margin-left: 100px">
|
|
||||||
<input v-model="item.port" autocomplete="off" type="number" class="el-input__inner form-input"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 20%;float: left">
|
|
||||||
<label class="el-form-item__label" style="padding-left: 20px">最大并发数</label>
|
|
||||||
<div class="el-form-item__content" style="margin-left: 102px">
|
|
||||||
<input v-model="item.maxConcurrency" autocomplete="off" type="number"
|
|
||||||
class="el-input__inner form-input"/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="width: 30%;float: left">
|
||||||
|
<el-form-item prop="maxConcurrency" label="最大并发数" style="padding-left: 20px">
|
||||||
|
<el-input-number v-model="item.maxConcurrency" :min="1" :max="9999"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="op">
|
<div class="op">
|
||||||
<span class="box">
|
<span class="box">
|
||||||
|
@ -238,6 +227,7 @@
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
testLoading: false,
|
||||||
createVisible: false,
|
createVisible: false,
|
||||||
infoList: [],
|
infoList: [],
|
||||||
updateVisible: false,
|
updateVisible: false,
|
||||||
|
@ -264,6 +254,9 @@
|
||||||
],
|
],
|
||||||
description: [
|
description: [
|
||||||
{max: 60, message: '最大长度 60 个字符', trigger: 'blur'}
|
{max: 60, message: '最大长度 60 个字符', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
type: [
|
||||||
|
{required: true, message: '请选择资源类型', trigger: 'blur'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,6 +296,28 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
validateResourceInfo() {
|
||||||
|
if (this.infoList.length <= 0) {
|
||||||
|
return {validate: false, msg: "资源池不能为空"}
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultValidate = {validate: true, msg: "请完善数据"}
|
||||||
|
this.infoList.forEach(function (info) {
|
||||||
|
for (let key in info) {
|
||||||
|
if (info[key] != '0' && !info[key]) {
|
||||||
|
resultValidate.validate = false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.maxConcurrency) {
|
||||||
|
resultValidate.validate = false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return resultValidate;
|
||||||
|
},
|
||||||
buildPagePath(path) {
|
buildPagePath(path) {
|
||||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||||
},
|
},
|
||||||
|
@ -349,6 +364,9 @@
|
||||||
createTestResourcePool(createTestResourcePoolForm) {
|
createTestResourcePool(createTestResourcePoolForm) {
|
||||||
this.$refs[createTestResourcePoolForm].validate(valide => {
|
this.$refs[createTestResourcePoolForm].validate(valide => {
|
||||||
if (valide) {
|
if (valide) {
|
||||||
|
let vri = this.validateResourceInfo();
|
||||||
|
if (vri.validate) {
|
||||||
|
this.testLoading = true;
|
||||||
this.form.info = JSON.stringify(this.infoList);
|
this.form.info = JSON.stringify(this.infoList);
|
||||||
this.$post("/testresourcepool/add", this.form)
|
this.$post("/testresourcepool/add", this.form)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -357,8 +375,18 @@
|
||||||
message: '添加成功!'
|
message: '添加成功!'
|
||||||
},
|
},
|
||||||
this.createVisible = false,
|
this.createVisible = false,
|
||||||
this.initTableData())
|
this.initTableData());
|
||||||
|
this.testLoading = false;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.$message({
|
||||||
|
type: 'warning',
|
||||||
|
message: vri.msg
|
||||||
|
});
|
||||||
|
this.testLoading = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -367,6 +395,9 @@
|
||||||
updateTestResourcePool(updateTestResourcePoolForm) {
|
updateTestResourcePool(updateTestResourcePoolForm) {
|
||||||
this.$refs[updateTestResourcePoolForm].validate(valide => {
|
this.$refs[updateTestResourcePoolForm].validate(valide => {
|
||||||
if (valide) {
|
if (valide) {
|
||||||
|
this.testLoading = true;
|
||||||
|
let vri = this.validateResourceInfo();
|
||||||
|
if (vri.validate) {
|
||||||
this.form.info = JSON.stringify(this.infoList);
|
this.form.info = JSON.stringify(this.infoList);
|
||||||
this.$post("/testresourcepool/update", this.form)
|
this.$post("/testresourcepool/update", this.form)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -376,8 +407,17 @@
|
||||||
},
|
},
|
||||||
this.updateVisible = false,
|
this.updateVisible = false,
|
||||||
this.initTableData(),
|
this.initTableData(),
|
||||||
self.loading = false)
|
self.loading = false);
|
||||||
|
this.testLoading = false;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.$message({
|
||||||
|
type: 'warning',
|
||||||
|
message: vri.msg
|
||||||
|
});
|
||||||
|
this.testLoading = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -414,12 +454,29 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.op {
|
.op {
|
||||||
line-height: 40px;
|
|
||||||
float: left;
|
float: left;
|
||||||
width: 16%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.k8s-master {
|
||||||
|
width: 34%;
|
||||||
|
float: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.k8s-token {
|
||||||
|
width: 36%;
|
||||||
|
float: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.k8s-token .el-form-item__label {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-line {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog :title="$t('user.create')" :visible.sync="createVisible" width="30%" @closed="closeFunc" :destroy-on-close="true">
|
<el-dialog :title="$t('user.create')" :visible.sync="createVisible" width="30%" @closed="closeFunc" :destroy-on-close="true">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule" ref="createUserForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" ref="createUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off"/>
|
<el-input v-model="form.id" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog :title="$t('user.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('user.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" :rules="rule" ref="updateUserForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog title="添加成员" :visible.sync="createVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog title="添加成员" :visible.sync="createVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" ref="form" :rules="rules" label-position="left" label-width="100px" size="small">
|
<el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item label="成员" prop="userIds">
|
<el-form-item label="成员" prop="userIds">
|
||||||
<el-select v-model="form.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
<el-select v-model="form.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog title="修改成员" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog title="修改成员" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
||||||
<el-form :model="form" label-position="left" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -158,6 +158,8 @@ export default {
|
||||||
'custom_http_code': 'Custom HTTP response success status code',
|
'custom_http_code': 'Custom HTTP response success status code',
|
||||||
'separated_by_commas': 'Separated by commas',
|
'separated_by_commas': 'Separated by commas',
|
||||||
'create': 'Create Test',
|
'create': 'Create Test',
|
||||||
|
'select_resource_pool': 'Please Select Resource Pool',
|
||||||
|
'resource_pool_is_null': 'Resource Pool is empty',
|
||||||
},
|
},
|
||||||
fuc_test: {
|
fuc_test: {
|
||||||
'select_resource_pool': 'Please select resource pool'
|
'select_resource_pool': 'Please select resource pool'
|
||||||
|
|
|
@ -158,6 +158,8 @@ export default {
|
||||||
'custom_http_code': '自定义 HTTP 响应成功状态码',
|
'custom_http_code': '自定义 HTTP 响应成功状态码',
|
||||||
'separated_by_commas': '按逗号分隔',
|
'separated_by_commas': '按逗号分隔',
|
||||||
'create': '创建测试',
|
'create': '创建测试',
|
||||||
|
'select_resource_pool': '请选择资源池',
|
||||||
|
'resource_pool_is_null': '资源池为空',
|
||||||
},
|
},
|
||||||
fuc_test: {
|
fuc_test: {
|
||||||
'select_resource_pool': '请选择资源池'
|
'select_resource_pool': '请选择资源池'
|
||||||
|
|
Loading…
Reference in New Issue