fix: 导出html报告性能测试报告为空

This commit is contained in:
chenjianxing 2021-08-26 14:12:10 +08:00 committed by jianxing
parent f6c58e9a99
commit 31baaaf34e
15 changed files with 233 additions and 66 deletions

View File

@ -242,4 +242,10 @@ public class ShareController {
public List<String> queryReportResource(@PathVariable String shareId, @PathVariable("id") String reportId) {
return metricService.queryReportResource(reportId);
}
@GetMapping("/performance/report/get-load-config/{shareId}/{testId}")
public String getLoadConfiguration(@PathVariable String shareId, @PathVariable String testId) {
//checkPermissionService.checkPerformanceTestOwner(testId);
return performanceTestService.getLoadConfiguration(testId);
}
}

View File

@ -213,6 +213,11 @@ public class TestPlanController {
testPlanService.exportPlanReport(planId, response);
}
@GetMapping("/get/report/export/{planId}")
public TestPlanSimpleReportDTO getExportHtmlReport(@PathVariable String planId, HttpServletResponse response) throws UnsupportedEncodingException {
return testPlanService.buildPlanReport(planId, true);
}
@GetMapping("/report/db/export/{reportId}")
public void exportHtmlDbReport(@PathVariable String reportId, HttpServletResponse response) throws UnsupportedEncodingException {
testPlanService.exportPlanDbReport(reportId, response);

View File

@ -2,9 +2,16 @@ package io.metersphere.track.dto;
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
import io.metersphere.base.domain.TestPlanLoadCase;
import io.metersphere.dto.LogDetailDTO;
import io.metersphere.performance.base.*;
import io.metersphere.performance.dto.LoadTestExportJmx;
import io.metersphere.performance.dto.MetricData;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
@Getter
@Setter
public class TestPlanLoadCaseDTO extends TestPlanLoadCase {
@ -14,13 +21,28 @@ public class TestPlanLoadCaseDTO extends TestPlanLoadCase {
private String caseStatus;
private String num;
private String name;
private ReportDTO response;
private ResponseDTO response;
@Getter
@Setter
public static class ReportDTO extends LoadTestReportWithBLOBs {
public static class ResponseDTO extends LoadTestReportWithBLOBs {
private long duration;
private long startTime;
private long endTime;
private String fixLoadConfiguration;
// private LoadTestExportJmx jmxContent;
private List<LoadTestExportJmx> fixJmxContent;
private TestOverview testOverview;
private List<ChartsData> loadChartData;
private List<ChartsData> responseTimeChartData;
private List<ChartsData> errorChartData;
private List<ChartsData> responseCodeChartData;
private Map<String, List<ChartsData>> checkOptions;
private List<Statistics> reportStatistics;
private List<Errors> reportErrors;
private List<ErrorsTop5> reportErrorsTop5;
private List<LogDetailDTO> reportLogResource;
private List<String> reportResource;
private List<MetricData> metricData;
}
}

View File

@ -30,6 +30,7 @@ import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.*;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.dto.IssueTemplateDao;
import io.metersphere.dto.LogDetailDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn;
@ -37,8 +38,11 @@ import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.track.TestPlanReference;
import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.performance.base.ReportTimeInfo;
import io.metersphere.performance.base.*;
import io.metersphere.performance.dto.LoadTestExportJmx;
import io.metersphere.performance.dto.MetricData;
import io.metersphere.performance.request.RunTestPlanRequest;
import io.metersphere.performance.service.MetricQueryService;
import io.metersphere.performance.service.PerformanceReportService;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.service.IssueTemplateService;
@ -175,6 +179,8 @@ public class TestPlanService {
private IssueTemplateService issueTemplateService;
@Resource
private PerformanceReportService performanceReportService;
@Resource
private MetricQueryService metricQueryService;
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
@ -1470,17 +1476,83 @@ public class TestPlanService {
request.setReportId(reportId);
Boolean existReport = testPlanLoadCaseService.isExistReport(request);
if (existReport) {
LoadTestReportWithBLOBs loadTestReport = performanceReportService.getLoadTestReport(reportId);
ReportTimeInfo reportTimeInfo = performanceReportService.getReportTimeInfo(reportId);
TestPlanLoadCaseDTO.ReportDTO reportDTO = new TestPlanLoadCaseDTO.ReportDTO();
if (loadTestReport != null) {
BeanUtils.copyBean(reportDTO, loadTestReport);
try {
LoadTestReportWithBLOBs loadTestReport = performanceReportService.getLoadTestReport(reportId);
ReportTimeInfo reportTimeInfo = performanceReportService.getReportTimeInfo(reportId);
TestPlanLoadCaseDTO.ResponseDTO response = new TestPlanLoadCaseDTO.ResponseDTO();
if (loadTestReport != null) {
BeanUtils.copyBean(response, loadTestReport);
}
if (reportTimeInfo != null) {
BeanUtils.copyBean(response, reportTimeInfo);
}
// 压力配置
if (StringUtils.isBlank(loadTestReport.getLoadConfiguration())) {
String loadConfiguration = performanceTestService.getLoadConfiguration(item.getId());
response.setFixLoadConfiguration(loadConfiguration);
}
LoadTestExportJmx jmxContent = performanceReportService.getJmxContent(reportId);
if (jmxContent != null) {
response.setJmxContent(JSONObject.toJSONString(jmxContent));
}
List<LoadTestExportJmx> fixJmxContent = performanceTestService.getJmxContent(item.getId());
response.setFixJmxContent(fixJmxContent);
// 概览
TestOverview testOverview = performanceReportService.getTestOverview(reportId);
response.setTestOverview(testOverview);
List<ChartsData> loadChartData = performanceReportService.getLoadChartData(reportId);
response.setLoadChartData(loadChartData);
List<ChartsData> responseTimeChartData = performanceReportService.getResponseTimeChartData(reportId);
response.setResponseTimeChartData(responseTimeChartData);
List<ChartsData> errorChartData = performanceReportService.getErrorChartData(reportId);
response.setErrorChartData(errorChartData);
List<ChartsData> responseCodeChartData = performanceReportService.getResponseCodeChartData(reportId);
response.setResponseCodeChartData(responseCodeChartData);
// 报告详情
List<String> reportKeys = Arrays.asList(
"ALL",
"ActiveThreadsChart",
"TransactionsChart",
"ResponseTimeChart",
"ResponseTimePercentilesChart",
"ResponseCodeChart",
"ErrorsChart",
"LatencyChart",
"BytesThroughputChart");
Map<String, List<ChartsData>> checkOptions = new HashMap<>();
reportKeys.forEach(reportKey -> {
List<ChartsData> reportChart = performanceReportService.getReportChart(reportKey, reportId);
checkOptions.put(reportKey, reportChart);
});
response.setCheckOptions(checkOptions);
// 统计分析
List<Statistics> reportStatistics = performanceReportService.getReportStatistics(reportId);
response.setReportStatistics(reportStatistics);
// 错误分析
List<Errors> reportErrors = performanceReportService.getReportErrors(reportId);
response.setReportErrors(reportErrors);
List<ErrorsTop5> reportErrorsTop5 = performanceReportService.getReportErrorsTOP5(reportId);
response.setReportErrorsTop5(reportErrorsTop5);
// 日志详情
List<LogDetailDTO> reportLogResource = performanceReportService.getReportLogResource(reportId);
response.setReportLogResource(reportLogResource);
// performanceReportService.getReportLogs(reportId, resourceId);
List<String> reportResource = metricQueryService.queryReportResource(reportId);
response.setReportResource(reportResource);
List<MetricData> metricData = metricQueryService.queryMetric(reportId);
response.setMetricData(metricData);
item.setResponse(response);
} catch (Exception e) {
LogUtil.error(e);
}
if (reportTimeInfo != null) {
BeanUtils.copyBean(reportDTO, reportTimeInfo);
}
item.setResponse(reportDTO);
// todo 报告详情
}
}
});
@ -1596,28 +1668,7 @@ public class TestPlanService {
if (checkReportConfig(config, "load", "all")) {
allCases = testPlanLoadCaseService.getAllCases(executeInfo.getLoadCaseExecInfo().keySet(),planId,null);
if (saveResponse) {
allCases.forEach(item -> {
String reportId = executeInfo.getLoadCaseReportIdMap().get(item.getId());
if(StringUtils.isNotEmpty(reportId)){
LoadCaseReportRequest request = new LoadCaseReportRequest();
request.setTestPlanLoadCaseId(item.getId());
request.setReportId(reportId);
Boolean existReport = testPlanLoadCaseService.isExistReport(request);
if (existReport) {
LoadTestReportWithBLOBs loadTestReport = performanceReportService.getLoadTestReport(reportId);
ReportTimeInfo reportTimeInfo = performanceReportService.getReportTimeInfo(reportId);
TestPlanLoadCaseDTO.ReportDTO reportDTO = new TestPlanLoadCaseDTO.ReportDTO();
if (loadTestReport != null) {
BeanUtils.copyBean(reportDTO, loadTestReport);
}
if (reportTimeInfo != null) {
BeanUtils.copyBean(reportDTO, reportTimeInfo);
}
item.setResponse(reportDTO);
// todo 报告详情
}
}
});
buildLoadResponse(allCases);
}
report.setLoadAllCases(allCases);
}

View File

@ -176,8 +176,8 @@ export default {
methods: {
initTableData() {
if (this.planReportTemplate) {
this.dataData = this.planReportTemplate.errorsContent;
this.handleGetTop5(this.planReportTemplate.errorTop5);
this.tableData = this.planReportTemplate.reportErrors;
this.handleGetTop5(this.planReportTemplate.reportErrorsTop5);
} else if (this.isShare){
getSharePerformanceReportErrorsContent(this.shareId, this.id).then(res => {
this.tableData = res.data.data;
@ -250,6 +250,14 @@ export default {
}
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.initTableData();
}
},
deep: true
}
},
};

View File

@ -47,7 +47,7 @@ export default {
this.init = true;
this.active = '0';
if (this.planReportTemplate) {
this.handleGetLogResource(this.planReportTemplate.logResource);
this.handleGetLogResource(this.planReportTemplate.reportLogResource);
} else if (this.isShare){
getSharePerformanceReportLogResource(this.shareId, this.id, (data) => {
this.handleGetLogResource(data);
@ -79,7 +79,7 @@ export default {
this.logStatus[resourceId] = true;
this.loading = true;
if (this.planReportTemplate) {
this.handleGetLogResourceDetail(this.planReportTemplate.logResourceDetail, resourceId);
// this.handleGetLogResourceDetail(this.planReportTemplate.logResourceDetail, resourceId);
} else if (this.isShare){
getSharePerformanceReportLogResourceDetail(this.shareId, this.id, resourceId, this.page[resourceId], data => {
this.handleGetLogResourceDetail(data, resourceId);
@ -160,6 +160,14 @@ export default {
}
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.getResource();
}
},
deep: true
}
},
};

View File

@ -109,7 +109,9 @@ export default {
getResource() {
// this.init = true;
if (this.planReportTemplate) {
this.totalOption = this.getOption(this.planReportTemplate.metricResource);
this.instances = this.planReportTemplate.reportResource;
this.data = this.planReportTemplate.metricData;
this.totalOption = this.getOption(this.instances[0]);
} else if (this.isShare){
getSharePerformanceMetricQueryResource(this.shareId, this.id).then(response => {
this.instances = response.data.data;
@ -205,6 +207,14 @@ export default {
}
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.getResource();
}
},
deep: true
}
},
};

View File

@ -281,7 +281,7 @@ export default {
}
},
getLoadConfig() {
if (!this.report.id) {
if (!this.report.id && !this.planReportTemplate) {
return;
}
if (this.planReportTemplate) {
@ -303,9 +303,8 @@ export default {
this.calculateLoadConfiguration(d);
} else {
if (this.planReportTemplate) {
//todo
if (this.planReportTemplate.loadConfig) {
let data = JSON.parse(this.planReportTemplate.loadConfig);
let data = JSON.parse(this.planReportTemplate.fixLoadConfiguration);
this.calculateLoadConfiguration(data);
}
} else if (this.isShare){
@ -330,13 +329,12 @@ export default {
},
getJmxContent() {
// console.log(this.report.testId);
if (!this.report.testId) {
if (!this.report.testId && !this.planReportTemplate) {
return;
}
if (this.planReportTemplate) {
//todo
if (this.planReportTemplate.jmxContent) {
this.calculateLoadConfiguration(this.planReportTemplate.jmxContent);
this.handleGetJmxContent(JSON.parse(this.planReportTemplate.jmxContent));
}
} else if (this.isShare){
this.result = getSharePerformanceJmxContent(this.shareId, this.report.id, data => {
@ -360,10 +358,7 @@ export default {
//
if (!threadGroups || threadGroups.length === 0) {
if (this.planReportTemplate) {
//todo
if (this.planReportTemplate.oldJmxContent) {
this.calculateLoadConfiguration(this.planReportTemplate.oldJmxContent);
}
this.planReportTemplate.fixJmxContent.forEach(d => this.handleGetOldJmxContent(d, threadGroups));
} else if (this.isShare){
this.result = getShareOldPerformanceJmxContent(this.shareId, this.report.testId, data => {
data.forEach(d => this.handleGetOldJmxContent(d, threadGroups));
@ -647,6 +642,14 @@ export default {
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.getJmxContent();
}
},
deep: true
}
}
};
</script>

View File

@ -150,8 +150,9 @@ export default {
methods: {
initTableData() {
if (this.planReportTemplate) {
let data = this.planReportTemplate.content;
this.buildInfo(data);
let data = this.planReportTemplate.reportStatistics;
this.tableData = data;
this.originalData = data;
} else if (this.isShare){
getSharePerformanceReportContent(this.shareId, this.id).then(res => {
this.tableData = res.data.data;
@ -197,8 +198,16 @@ export default {
}
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.initTableData();
}
},
deep: true
}
},
}
}
</script>

View File

@ -460,7 +460,7 @@ export default {
},
getCheckOptions(reportKey) {
if (this.planReportTemplate) {
let data = this.planReportTemplate.detailContent;
let data = this.planReportTemplate.checkOptions[reportKey];
this.handleGetCheckOptions(data, reportKey);
} else if (this.isShare){
return getSharePerformanceReportDetailContent(this.shareId, reportKey, this.id).then(res => {
@ -490,8 +490,12 @@ export default {
this.legend = [];
let promises = [];
if (this.planReportTemplate) {
let data = this.planReportTemplate.detailContent;
this.buildInfo(data);
let chars = [];
for (let name in this.checkList) {
let data = this.planReportTemplate.checkOptions[name];
chars.push({data, 'reportKey' : name});
}
this.handleGetTotalChart(chars);
} else {
for (let name in this.checkList) {
promises.push(this.getChart(name, this.checkList[name]));
@ -502,6 +506,9 @@ export default {
this.result.loading = false;
});
}
},
handleTemplateGetTotalChart() {
},
handleGetTotalChart(res) {
res = res.filter(v => !!v);
@ -622,7 +629,10 @@ export default {
this.legend.push(name);
series[name] = [];
}
series[name].splice(xAxis.indexOf(item.xAxis), 0, [item.xAxis, item.yAxis.toFixed(2)]);
if (series[name]) {
series[name].splice(xAxis.indexOf(item.xAxis), 0, [item.xAxis, item.yAxis.toFixed(2)]);
}
});
this.$set(option.legend, "data", this.legend);
this.$set(option.legend, "type", "scroll");
@ -731,6 +741,16 @@ export default {
}
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.initTableData();
// todo
// this.getTotalChart();
}
},
deep: true
}
},

View File

@ -123,7 +123,7 @@ export default {
methods: {
initTableData() {
if (this.planReportTemplate) {
let data = this.planReportTemplate.loadOverview;
let data = this.planReportTemplate.testOverview;
this.buildInfo(data);
} else if (this.isShare) {
getSharePerformanceReportOverview(this.shareId, this.id, (data) => {
@ -150,7 +150,7 @@ export default {
},
getLoadChart() {
if (this.planReportTemplate) {
let data = this.planReportTemplate.loadOverviewLoadChart;
let data = this.planReportTemplate.loadChartData;
this.handleGetLoadChart(data);
} else if (this.isShare) {
getSharePerformanceReportLoadChart(this.shareId, this.id, data => {
@ -231,7 +231,7 @@ export default {
},
getResChart() {
if (this.planReportTemplate) {
let data = this.planReportTemplate.loadOverviewResChart;
let data = this.planReportTemplate.responseTimeChartData;
this.handleGetResChart(data);
} else if (this.isShare) {
getSharePerformanceReportResChart(this.shareId, this.id, data => {
@ -396,7 +396,7 @@ export default {
},
getResponseCodeChart() {
if (this.planReportTemplate) {
let data = this.planReportTemplate.loadOverviewResponseCodeChart;
let data = this.planReportTemplate.responseCodeChartData;
this.handleGetResponseCodeChart(data);
} else if (this.isShare) {
getSharePerformanceReportResponseCodeChart(this.shareId, this.id, data => {
@ -549,6 +549,14 @@ export default {
}
},
deep: true
},
planReportTemplate: {
handler() {
if (this.planReportTemplate) {
this.initTableData();
}
},
deep: true
}
},
};

View File

@ -166,7 +166,7 @@ export default {
isPlanReport: Boolean,
isShare: Boolean,
shareId: String,
planReportTemplate: {}
planReportTemplate: Object
},
watch: {
reportId() {

View File

@ -19,6 +19,7 @@
import TestPlanFunctionalReport
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanFunctionalReport";
import {
getExportReport,
getShareTestPlanReport,
getShareTestPlanReportContent,
getTestPlanReport,
@ -67,6 +68,11 @@ export default {
},
reportId() {
this.getReport();
},
planReportTemplate() {
if (this.planReportTemplate) {
this.init();
}
}
},
created() {
@ -98,6 +104,13 @@ export default {
getReport() {
if (this.isTemplate) {
this.report = "#report";
// this.report = {};
// this.result = getExportReport(this.planId, (data) => {
// data.config = JSON.parse(data.config);
// this.report = data;
// });
this.report.config = this.getDefaultConfig(this.report.config);
} else if (this.isDb) {
if (this.isShare) {

View File

@ -6,11 +6,11 @@
:report="report" :plan-id="planId" @setSize="setAllSize"/>
</el-col>
<el-col :span="17" >
<el-card v-if="showResponse">
<el-card v-show="showResponse">
<load-case-report-view :is-plan-report="true" :share-id="shareId" :is-share="isShare"
:plan-report-template="response" :report-id="reportId" ref="loadCaseReportView"/>
</el-card>
<div class="empty" v-else>内容为空</div>
<div class="empty" v-show="!showResponse">内容为空</div>
</el-col>
</el-row>
</div>
@ -44,8 +44,6 @@ export default {
response: null
}
},
mounted() {
},
methods: {
getReport(row) {
this.showResponse = false;
@ -53,6 +51,8 @@ export default {
if (row.response) {
this.showResponse = true;
this.response = row.response;
} else {
this.response = null;
}
} else {
let param = {

View File

@ -38,6 +38,10 @@ export function editPlanReportConfig(param, callback) {
});
}
export function getExportReport(planId, callback) {
return planId ? baseGet('/test/plan/get/report/export/' + planId, callback) : {};
}
export function getTestPlanReportContent(reportId, callback) {
return reportId ? baseGet('/test/plan/report/db/' + reportId, callback) : {};
}