diff --git a/backend/src/main/java/io/metersphere/controller/ReportController.java b/backend/src/main/java/io/metersphere/controller/ReportController.java index ddc44ba139..6167c9b8d4 100644 --- a/backend/src/main/java/io/metersphere/controller/ReportController.java +++ b/backend/src/main/java/io/metersphere/controller/ReportController.java @@ -8,6 +8,7 @@ import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.controller.request.ReportRequest; import io.metersphere.dto.ReportDTO; +import io.metersphere.report.base.Errors; import io.metersphere.report.base.RequestStatistics; import io.metersphere.report.base.RequestStatisticsDTO; import io.metersphere.service.ReportService; @@ -59,5 +60,10 @@ public class ReportController { return reportService.getReport(reportId); } + @GetMapping("/content/errors/{reportId}") + public List getReportErrors(@PathVariable String reportId) { + return reportService.getReportErrors(reportId); + } + } diff --git a/backend/src/main/java/io/metersphere/report/JtlResolver.java b/backend/src/main/java/io/metersphere/report/JtlResolver.java index 290d4bba04..b5e07fa585 100644 --- a/backend/src/main/java/io/metersphere/report/JtlResolver.java +++ b/backend/src/main/java/io/metersphere/report/JtlResolver.java @@ -3,9 +3,11 @@ package io.metersphere.report; import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; import com.opencsv.bean.HeaderColumnNameMappingStrategy; +import io.metersphere.report.base.Errors; import io.metersphere.report.base.Metric; import io.metersphere.report.base.RequestStatistics; import io.metersphere.report.base.RequestStatisticsDTO; +import org.apache.commons.lang3.StringUtils; import java.io.Reader; import java.io.StringReader; @@ -79,7 +81,7 @@ public class JtlResolver { Integer tp90 = elapsedList.size()*90/100; 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)); + Long l = Long.valueOf(timestampList.get(timestampList.size()-1)) - Long.valueOf(timestampList.get(0)); RequestStatistics requestStatistics = new RequestStatistics(); requestStatistics.setRequestLabel(label); @@ -104,7 +106,7 @@ public class JtlResolver { /** * 所有的相同请求的bytes总和 / 1024 / 请求持续运行的时间=sum(bytes)/1024/total time */ - // todo Avg Bandwidth(KBytes/s) + // todo Avg Bandwidth(KBytes/s) 请求之间时间戳间隔l 可能为0 requestStatistics.setKbPerSec(String.format("%.2f",totalBytes*1.0/1024/(l*1.0/1000))); requestStatisticsList.add(requestStatistics); } @@ -140,10 +142,40 @@ public class JtlResolver { return statisticsDTO; } + // Aggregate Report public static RequestStatisticsDTO getRequestStatistics(String jtlString) { List totalLines = resolver(jtlString); Map> map = totalLines.stream().collect(Collectors.groupingBy(Metric::getLabel)); return getOneRpsResult(map); } + // Errors + public static List getErrorsList(String jtlString) { + List totalLines = resolver(jtlString); + List falseList = totalLines.stream().filter(metric -> StringUtils.equals("false", metric.getSuccess())).collect(Collectors.toList()); + List errorsList = new ArrayList<>(); + Map> collect = falseList.stream().collect(Collectors.groupingBy(JtlResolver::getResponseCodeAndFailureMessage)); + Iterator>> iterator = collect.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry> next = iterator.next(); + String key = next.getKey(); + List value = next.getValue(); + Errors errors = new Errors(); + errors.setErrorType(key); + errors.setErrorNumber(String.valueOf(value.size())); + Integer errorSize = value.size(); + Integer errorAllSize = falseList.size(); + Integer allSamples = totalLines.size(); + DecimalFormat df = new DecimalFormat("0.00"); + errors.setPrecentOfErrors(df.format((double)errorSize / errorAllSize * 100) + "%"); + errors.setPrecentOfAllSamples(df.format((double)errorSize / allSamples * 100) + "%"); + errorsList.add(errors); + } + return errorsList; + } + + private static String getResponseCodeAndFailureMessage(Metric metric) { + return metric.getResponseCode() + "/" + metric.getResponseMessage(); + } + } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/report/base/Errors.java b/backend/src/main/java/io/metersphere/report/base/Errors.java new file mode 100644 index 0000000000..1476036a8c --- /dev/null +++ b/backend/src/main/java/io/metersphere/report/base/Errors.java @@ -0,0 +1,41 @@ +package io.metersphere.report.base; + +public class Errors { + + private String errorType; + private String errorNumber; + private String precentOfErrors; + private String precentOfAllSamples; + + public String getErrorType() { + return errorType; + } + + public void setErrorType(String errorType) { + this.errorType = errorType; + } + + public String getErrorNumber() { + return errorNumber; + } + + public void setErrorNumber(String errorNumber) { + this.errorNumber = errorNumber; + } + + public String getPrecentOfErrors() { + return precentOfErrors; + } + + public void setPrecentOfErrors(String precentOfErrors) { + this.precentOfErrors = precentOfErrors; + } + + public String getPrecentOfAllSamples() { + return precentOfAllSamples; + } + + public void setPrecentOfAllSamples(String precentOfAllSamples) { + this.precentOfAllSamples = precentOfAllSamples; + } +} diff --git a/backend/src/main/java/io/metersphere/service/ReportService.java b/backend/src/main/java/io/metersphere/service/ReportService.java index b1a2e59ac5..a918b34516 100644 --- a/backend/src/main/java/io/metersphere/service/ReportService.java +++ b/backend/src/main/java/io/metersphere/service/ReportService.java @@ -7,6 +7,7 @@ import io.metersphere.base.mapper.ext.ExtLoadTestReportMapper; import io.metersphere.controller.request.ReportRequest; import io.metersphere.dto.ReportDTO; import io.metersphere.report.JtlResolver; +import io.metersphere.report.base.Errors; import io.metersphere.report.base.RequestStatistics; import io.metersphere.report.base.RequestStatisticsDTO; import org.springframework.stereotype.Service; @@ -51,4 +52,11 @@ public class ReportService { RequestStatisticsDTO requestStatistics = JtlResolver.getRequestStatistics(content); return requestStatistics; } + + public List getReportErrors(String id) { + LoadTestReport loadTestReport = loadTestReportMapper.selectByPrimaryKey(id); + String content = loadTestReport.getContent(); + List errors = JtlResolver.getErrorsList(content); + return errors; + } } diff --git a/frontend/src/business/components/performance/report/PerformanceReportView.vue b/frontend/src/business/components/performance/report/PerformanceReportView.vue index cdfbb3e034..522f861dce 100644 --- a/frontend/src/business/components/performance/report/PerformanceReportView.vue +++ b/frontend/src/business/components/performance/report/PerformanceReportView.vue @@ -41,7 +41,7 @@ - + diff --git a/frontend/src/business/components/performance/report/components/ErrorLog.vue b/frontend/src/business/components/performance/report/components/ErrorLog.vue index 51e8166f4b..eb13535c5b 100644 --- a/frontend/src/business/components/performance/report/components/ErrorLog.vue +++ b/frontend/src/business/components/performance/report/components/ErrorLog.vue @@ -1,32 +1,123 @@ @@ -39,11 +130,36 @@ } }, methods: { - + initTableData() { + this.$get("/report/content/errors/" + this.id, res => { + this.tableData = res.data; + }) + } + }, + created() { + this.initTableData(); + }, + props: ['id'], + watch: { + '$route'(to) { + if (to.name === "perReportView") { + let reportId = to.path.split('/')[4]; + if(reportId){ + this.$get("/report/content/errors/" + this.id, res => { + this.tableData = res.data; + }) + } + } + } } }