This commit is contained in:
chenjianxing 2020-04-29 19:01:16 +08:00
commit e370620c97
15 changed files with 276 additions and 70 deletions

View File

@ -3,12 +3,24 @@ package io.metersphere.base.domain;
import java.io.Serializable;
public class LoadTestReportLog implements Serializable {
private Long id;
private String reportId;
private String resourceId;
private String content;
private static final long serialVersionUID = 1L;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getReportId() {
return reportId;
}
@ -17,6 +29,14 @@ public class LoadTestReportLog implements Serializable {
this.reportId = reportId == null ? null : reportId.trim();
}
public String getResourceId() {
return resourceId;
}
public void setResourceId(String resourceId) {
this.resourceId = resourceId == null ? null : resourceId.trim();
}
public String getContent() {
return content;
}

View File

@ -104,6 +104,66 @@ public class LoadTestReportLogExample {
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(Long value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(Long value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(Long value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(Long value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(Long value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(Long value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<Long> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<Long> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(Long value1, Long value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(Long value1, Long value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andReportIdIsNull() {
addCriterion("report_id is null");
return (Criteria) this;
@ -173,6 +233,76 @@ public class LoadTestReportLogExample {
addCriterion("report_id not between", value1, value2, "reportId");
return (Criteria) this;
}
public Criteria andResourceIdIsNull() {
addCriterion("resource_id is null");
return (Criteria) this;
}
public Criteria andResourceIdIsNotNull() {
addCriterion("resource_id is not null");
return (Criteria) this;
}
public Criteria andResourceIdEqualTo(String value) {
addCriterion("resource_id =", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdNotEqualTo(String value) {
addCriterion("resource_id <>", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdGreaterThan(String value) {
addCriterion("resource_id >", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdGreaterThanOrEqualTo(String value) {
addCriterion("resource_id >=", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdLessThan(String value) {
addCriterion("resource_id <", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdLessThanOrEqualTo(String value) {
addCriterion("resource_id <=", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdLike(String value) {
addCriterion("resource_id like", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdNotLike(String value) {
addCriterion("resource_id not like", value, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdIn(List<String> values) {
addCriterion("resource_id in", values, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdNotIn(List<String> values) {
addCriterion("resource_id not in", values, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdBetween(String value1, String value2) {
addCriterion("resource_id between", value1, value2, "resourceId");
return (Criteria) this;
}
public Criteria andResourceIdNotBetween(String value1, String value2) {
addCriterion("resource_id not between", value1, value2, "resourceId");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -11,7 +11,7 @@ public interface LoadTestReportLogMapper {
int deleteByExample(LoadTestReportLogExample example);
int deleteByPrimaryKey(String reportId);
int deleteByPrimaryKey(Long id);
int insert(LoadTestReportLog record);
@ -21,7 +21,7 @@ public interface LoadTestReportLogMapper {
List<LoadTestReportLog> selectByExample(LoadTestReportLogExample example);
LoadTestReportLog selectByPrimaryKey(String reportId);
LoadTestReportLog selectByPrimaryKey(Long id);
int updateByExampleSelective(@Param("record") LoadTestReportLog record, @Param("example") LoadTestReportLogExample example);
@ -32,4 +32,6 @@ public interface LoadTestReportLogMapper {
int updateByPrimaryKeySelective(LoadTestReportLog record);
int updateByPrimaryKeyWithBLOBs(LoadTestReportLog record);
int updateByPrimaryKey(LoadTestReportLog record);
}

View File

@ -2,7 +2,9 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.base.mapper.LoadTestReportLogMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.LoadTestReportLog">
<id column="report_id" jdbcType="VARCHAR" property="reportId" />
<id column="id" jdbcType="BIGINT" property="id" />
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
<result column="resource_id" jdbcType="VARCHAR" property="resourceId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.LoadTestReportLog">
<result column="content" jdbcType="LONGVARCHAR" property="content" />
@ -66,7 +68,7 @@
</where>
</sql>
<sql id="Base_Column_List">
report_id
id, report_id, resource_id
</sql>
<sql id="Blob_Column_List">
content
@ -101,17 +103,17 @@
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from load_test_report_log
where report_id = #{reportId,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from load_test_report_log
where report_id = #{reportId,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.LoadTestReportLogExample">
delete from load_test_report_log
@ -120,23 +122,37 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.LoadTestReportLog">
insert into load_test_report_log (report_id, content)
values (#{reportId,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR})
insert into load_test_report_log (id, report_id, resource_id,
content)
values (#{id,jdbcType=BIGINT}, #{reportId,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
#{content,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestReportLog">
insert into load_test_report_log
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="reportId != null">
report_id,
</if>
<if test="resourceId != null">
resource_id,
</if>
<if test="content != null">
content,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
</if>
<if test="reportId != null">
#{reportId,jdbcType=VARCHAR},
</if>
<if test="resourceId != null">
#{resourceId,jdbcType=VARCHAR},
</if>
<if test="content != null">
#{content,jdbcType=LONGVARCHAR},
</if>
@ -151,9 +167,15 @@
<update id="updateByExampleSelective" parameterType="map">
update load_test_report_log
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=BIGINT},
</if>
<if test="record.reportId != null">
report_id = #{record.reportId,jdbcType=VARCHAR},
</if>
<if test="record.resourceId != null">
resource_id = #{record.resourceId,jdbcType=VARCHAR},
</if>
<if test="record.content != null">
content = #{record.content,jdbcType=LONGVARCHAR},
</if>
@ -164,7 +186,9 @@
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update load_test_report_log
set report_id = #{record.reportId,jdbcType=VARCHAR},
set id = #{record.id,jdbcType=BIGINT},
report_id = #{record.reportId,jdbcType=VARCHAR},
resource_id = #{record.resourceId,jdbcType=VARCHAR},
content = #{record.content,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -172,7 +196,9 @@
</update>
<update id="updateByExample" parameterType="map">
update load_test_report_log
set report_id = #{record.reportId,jdbcType=VARCHAR}
set id = #{record.id,jdbcType=BIGINT},
report_id = #{record.reportId,jdbcType=VARCHAR},
resource_id = #{record.resourceId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -180,15 +206,29 @@
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.LoadTestReportLog">
update load_test_report_log
<set>
<if test="reportId != null">
report_id = #{reportId,jdbcType=VARCHAR},
</if>
<if test="resourceId != null">
resource_id = #{resourceId,jdbcType=VARCHAR},
</if>
<if test="content != null">
content = #{content,jdbcType=LONGVARCHAR},
</if>
</set>
where report_id = #{reportId,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.LoadTestReportLog">
update load_test_report_log
set content = #{content,jdbcType=LONGVARCHAR}
where report_id = #{reportId,jdbcType=VARCHAR}
set report_id = #{reportId,jdbcType=VARCHAR},
resource_id = #{resourceId,jdbcType=VARCHAR},
content = #{content,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.LoadTestReportLog">
update load_test_report_log
set report_id = #{reportId,jdbcType=VARCHAR},
resource_id = #{resourceId,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>

View File

@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping(value = "performance/report")
@ -95,4 +96,8 @@ public class PerformanceReportController {
return reportService.getLoadTestReport(reportId);
}
@GetMapping("log/{reportId}")
public Map<String, String> stop(@PathVariable String reportId) {
return reportService.log(reportId);
}
}

View File

@ -21,7 +21,6 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping(value = "performance")
@ -89,11 +88,6 @@ public class PerformanceTestController {
performanceTestService.run(request);
}
@GetMapping("/log/{testId}")
public Map<String, String> stop(@PathVariable String testId) {
return performanceTestService.log(testId);
}
@GetMapping("/file/metadata/{testId}")
public List<FileMetadata> getFileMetadata(@PathVariable String testId) {
return fileService.getFileMetadataByTestId(testId);

View File

@ -56,7 +56,7 @@ public class EngineFactory {
return null;
}
public static EngineContext createContext(LoadTestWithBLOBs loadTest, long threadNum, long startTime, String reportId) throws Exception {
public static EngineContext createContext(LoadTestWithBLOBs loadTest, String resourceId, long threadNum, long startTime, String reportId) throws Exception {
final List<FileMetadata> fileMetadataList = fileService.getFileMetadataByTestId(loadTest.getId());
if (org.springframework.util.CollectionUtils.isEmpty(fileMetadataList)) {
MSException.throwException(Translator.get("run_load_test_file_not_found") + loadTest.getId());
@ -84,6 +84,7 @@ public class EngineFactory {
put("BOOTSTRAP_SERVERS", kafkaProperties.getBootstrapServers());
put("LOG_TOPIC", kafkaProperties.getLog().getTopic());
put("REPORT_ID", reportId);
put("RESOURCE_ID", resourceId);
}};
engineContext.setEnv(env);

View File

@ -62,7 +62,7 @@ public class DockerTestEngine extends AbstractEngine {
// todo 运行测试
EngineContext context = null;
try {
context = EngineFactory.createContext(loadTest, realThreadNum, this.getStartTime(), this.getReportId());
context = EngineFactory.createContext(loadTest, resource.getId(), realThreadNum, this.getStartTime(), this.getReportId());
} catch (Exception e) {
MSException.throwException(e);
}

View File

@ -48,7 +48,7 @@ public class KubernetesTestEngine extends AbstractEngine {
MSException.throwException(Translator.get("max_thread_insufficient"));
}
try {
EngineContext context = EngineFactory.createContext(loadTest, threadNum, this.getStartTime(), this.getReportId());
EngineContext context = EngineFactory.createContext(loadTest, r.getId(), threadNum, this.getStartTime(), this.getReportId());
runTest(context, clientCredential);
} catch (Exception e) {
MSException.throwException(e);
@ -90,6 +90,7 @@ public class KubernetesTestEngine extends AbstractEngine {
jmeter.setSpec(new JmeterSpec() {{
setReplicas(1);
setImage(JMETER_IMAGE);
setEnv(context.getEnv());
}});
LogUtil.info("Load test started. " + context.getTestId());
kubernetesProvider.applyCustomResource(jmeter);

View File

@ -4,11 +4,15 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.fabric8.kubernetes.api.model.KubernetesResource;
import java.util.HashMap;
import java.util.Map;
@JsonDeserialize
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class JmeterSpec implements KubernetesResource {
private int replicas = 1;
private String image;
private Map<String, String> env = new HashMap<>();
public int getReplicas() {
return replicas;
@ -25,4 +29,12 @@ public class JmeterSpec implements KubernetesResource {
public void setImage(String image) {
this.image = image;
}
public Map<String, String> getEnv() {
return env;
}
public void setEnv(Map<String, String> env) {
this.env = env;
}
}

View File

@ -22,7 +22,6 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@ -50,6 +49,8 @@ public class PerformanceTestService {
private ExtLoadTestReportDetailMapper extLoadTestReportDetailMapper;
@Resource
private LoadTestReportLogMapper loadTestReportLogMapper;
@Resource
private TestResourceService testResourceService;
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
return extLoadTestMapper.list(request);
@ -201,10 +202,15 @@ public class PerformanceTestService {
// append \n
extLoadTestReportDetailMapper.appendLine(testReport.getId(), "\n");
// 保存 load_test_report_log
LoadTestReportLog record = new LoadTestReportLog();
record.setReportId(testReport.getId());
record.setContent(StringUtils.EMPTY);
loadTestReportLogMapper.insert(record);
String resourcePoolId = loadTest.getTestResourcePoolId();
List<TestResource> testResourceList = testResourceService.getResourcesByPoolId(resourcePoolId);
testResourceList.forEach(r -> {
LoadTestReportLog record = new LoadTestReportLog();
record.setReportId(testReport.getId());
record.setResourceId(r.getId());
record.setContent(StringUtils.EMPTY);
loadTestReportLogMapper.insert(record);
});
} catch (MSException e) {
LogUtil.error(e);
loadTest.setStatus(PerformanceTestStatus.Error.name());
@ -214,23 +220,6 @@ public class PerformanceTestService {
}
}
public Map<String, String> log(String testId) {
final LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(testId);
if (loadTest == null) {
MSException.throwException(Translator.get("test_not_found") + testId);
}
if (!StringUtils.equals(loadTest.getStatus(), PerformanceTestStatus.Running.name())) {
MSException.throwException(Translator.get("test_not_running"));
}
Engine engine = EngineFactory.createEngine(loadTest);
if (engine == null) {
MSException.throwException(String.format("Engine is nulltest ID%s", testId));
}
return engine.log();
}
public List<LoadTestDTO> recentTestPlans(QueryTestPlanRequest request) {
// 查询最近的测试计划
request.setRecent(true);

View File

@ -21,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Service
@Transactional(rollbackFor = Exception.class)
@ -147,4 +148,9 @@ public class ReportService {
public LoadTestReport getLoadTestReport(String id) {
return extLoadTestReportMapper.selectByPrimaryKey(id);
}
public Map<String, String> log(String reportId) {
// todo 查询日志
return null;
}
}

View File

@ -83,9 +83,12 @@ CREATE TABLE IF NOT EXISTS `load_test_report_result` (
COLLATE=utf8mb4_bin;
CREATE TABLE IF NOT EXISTS `load_test_report_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`report_id` varchar(50) NOT NULL,
`resource_id` varchar(50) DEFAULT NULL,
`content` longtext,
PRIMARY KEY (`report_id`)
PRIMARY KEY (`id`),
KEY `load_test_report_log_report_id_resource_name_index` (`report_id`,`resource_id`)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4

View File

@ -49,13 +49,6 @@
</el-tabs>
</el-card>
<el-dialog :title="title" :visible.sync="showTestLogging">
<el-tabs type="border-card" :stretch="true">
<el-tab-pane v-for="(item, key) in testLogging" :key="key" :label="key" class="logging-content">
{{item}}
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>
</div>
</template>
@ -88,8 +81,6 @@
minutes: '0',
seconds: '0',
title: 'Logging',
testLogging: null,
showTestLogging: false,
}
},
methods: {
@ -119,11 +110,6 @@
})
}
},
getLog(testId) {
this.result = this.$get('/performance/log/' + testId, response => {
this.testLogging = response.data;
})
}
},
mounted() {
this.reportId = this.$route.path.split('/')[4];
@ -139,8 +125,6 @@
this.$info("报告生成中....");
break;
case 'Running':
this.showTestLogging = true;
this.getLog(data.testId);
break;
default:
break;
@ -190,9 +174,4 @@
color: #5C7878;
}
.logging-content {
white-space: pre-line;
height: calc(100vh - 450px);
overflow: auto;
}
</style>

View File

@ -1,15 +1,39 @@
<template>
<div>
LogDetails
{{logContent}}
</div>
</template>
<script>
export default {
name: "LogDetails"
name: "LogDetails",
props: ['id', 'status'],
data() {
return {
logContent: null
}
},
methods: {
initTableData() {
this.$get("/performance/report/log/" + this.id, res => {
this.logContent = res.data;
})
}
},
watch: {
status() {
if ("Completed" === this.status) {
this.initTableData()
}
}
},
}
</script>
<style scoped>
.logging-content {
white-space: pre-line;
overflow: auto;
}
</style>