diff --git a/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java b/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java index 9656ff0451..b3d806ef85 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java @@ -20,9 +20,8 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - import javax.annotation.Resource; +import java.util.List; @RestController @RequestMapping(value = "performance/report") @@ -63,7 +62,7 @@ public class PerformanceReportController { @GetMapping("/content/{reportId}") public List getReportContent(@PathVariable String reportId) { - return reportService.getReport(reportId); + return reportService.getReportStatistics(reportId); } @GetMapping("/content/errors/{reportId}") diff --git a/backend/src/main/java/io/metersphere/performance/service/ReportService.java b/backend/src/main/java/io/metersphere/performance/service/ReportService.java index b88ba8e864..5f3e3a66ad 100644 --- a/backend/src/main/java/io/metersphere/performance/service/ReportService.java +++ b/backend/src/main/java/io/metersphere/performance/service/ReportService.java @@ -108,7 +108,7 @@ public class ReportService { return loadTestReportResults.get(0).getReportValue(); } - public List getReport(String id) { + public List getReportStatistics(String id) { checkReportStatus(id); String reportValue = getContent(id, ReportKeys.RequestStatistics); return JSON.parseArray(reportValue, Statistics.class); @@ -209,4 +209,8 @@ public class ReportService { String content = loadTestReportLogs.stream().map(LoadTestReportLog::getContent).reduce("", (a, b) -> a + b); return content.getBytes(); } + + public LoadTestReport getReport(String reportId) { + return loadTestReportMapper.selectByPrimaryKey(reportId); + } } diff --git a/backend/src/main/java/io/metersphere/websocket/ReportWebSocket.java b/backend/src/main/java/io/metersphere/websocket/ReportWebSocket.java new file mode 100644 index 0000000000..39aaf3b6e2 --- /dev/null +++ b/backend/src/main/java/io/metersphere/websocket/ReportWebSocket.java @@ -0,0 +1,97 @@ +package io.metersphere.websocket; + +import io.metersphere.base.domain.LoadTestReport; +import io.metersphere.commons.constants.PerformanceTestStatus; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.performance.service.ReportService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; + +@ServerEndpoint("/performance/report/{reportId}") +@Component +public class ReportWebSocket { + + private static ReportService reportService; + + @Resource + public void setReportService(ReportService reportService) { + ReportWebSocket.reportService = reportService; + } + + /** + * 开启连接的操作 + */ + @OnOpen + public void onOpen(@PathParam("reportId") String reportId, Session session) throws IOException { + //开启一个线程对数据库中的数据进行轮询 + ReportThread reportThread = new ReportThread(session, reportId); + Thread thread = new Thread(reportThread); + thread.start(); + } + + /** + * 连接关闭的操作 + */ + @OnClose + public void onClose(Session session) { + + } + + /** + * 给服务器发送消息告知数据库发生变化 + */ + @OnMessage + public void onMessage(Session session, String message) { + } + + /** + * 出错的操作 + */ + @OnError + public void onError(Throwable error) { + System.out.println(error); + error.printStackTrace(); + } + + public static class ReportThread implements Runnable { + private boolean stopMe = true; + private final String reportId; + private final Session session; + private int refresh; + + public ReportThread(Session session, String reportId) { + this.session = session; + this.reportId = reportId; + this.refresh = 0; + } + + public void stopMe() { + stopMe = false; + } + + public void run() { + while (stopMe) { + try { + LoadTestReport report = reportService.getReport(reportId); + if (StringUtils.equalsAny(report.getStatus(), PerformanceTestStatus.Completed.name(), PerformanceTestStatus.Error.name())) { + this.stopMe(); + session.close(); + break; + } + if (PerformanceTestStatus.Running.name().equals(report.getStatus())) { + session.getBasicRemote().sendText("refresh-" + this.refresh++); + } + Thread.sleep(10 * 1000L); + } catch (Exception e) { + LogUtil.error(e); + } + } + } + } +} \ No newline at end of file diff --git a/frontend/src/business/components/performance/report/PerformanceReportView.vue b/frontend/src/business/components/performance/report/PerformanceReportView.vue index c48d8264a9..c386006ec5 100644 --- a/frontend/src/business/components/performance/report/PerformanceReportView.vue +++ b/frontend/src/business/components/performance/report/PerformanceReportView.vue @@ -101,7 +101,8 @@ seconds: '0', title: 'Logging', report: {}, - isReadOnly: false + isReadOnly: false, + websocket: null } }, methods: { @@ -136,6 +137,14 @@ }) } }, + initWebSocket() { + const uri = "ws://" + window.location.host + "/performance/report/" + this.reportId; + this.websocket = new WebSocket(uri); + this.websocket.onmessage = this.onMessage; + this.websocket.onopen = this.onOpen; + this.websocket.onerror = this.onError; + this.websocket.onclose = this.onClose; + }, checkReportStatus(status) { switch (status) { case 'Error': @@ -170,6 +179,20 @@ }).catch(() => { }); }, + onOpen() { + window.console.log("open WebSocket"); + }, + onError(e) { + window.console.error(e) + }, + onMessage(e) { + this.$set(this.report, "refresh", e.data); // 触发刷新 + this.initReportTimeInfo(); + }, + onClose(e) { + this.$set(this.report, "refresh", e.data); // 触发刷新 + this.initReportTimeInfo(); + } }, created() { this.isReadOnly = false; @@ -188,7 +211,10 @@ } }) this.initBreadcrumb(); - + this.initWebSocket(); + }, + beforeDestroy() { + this.websocket.close() //离开路由之后断开websocket连接 }, watch: { '$route'(to) {