From 45d58895cff8e8b6e7ce6989e7a52082da3efc78 Mon Sep 17 00:00:00 2001 From: easonzhu Date: Mon, 28 Apr 2025 16:18:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84monitor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- html/monitor.html | 147 +++++++++++------- .../com/syzb/monitor/query/MonitorQuery.java | 20 +++ .../syzb/monitor/service/MonitorService.java | 66 ++++++-- 3 files changed, 171 insertions(+), 62 deletions(-) diff --git a/html/monitor.html b/html/monitor.html index 8235ea9..c1bcc86 100644 --- a/html/monitor.html +++ b/html/monitor.html @@ -1,9 +1,9 @@ - + - - + + Interface Monitor @@ -28,17 +28,17 @@ } .el-form-item__content { - margin-left: 20px !important; + margin-left: 6px !important; } .resu { - margin-left: 30%; - width: 70%; - min-height: 1080px; + margin-left: 360px; + width: 1160px; + min-height: 700px; } .line { - width: 1000px; + width: 1100px; height: 300px; } @@ -46,51 +46,70 @@
-
+
- - + +
- + - + - - + + - - + + - {{ item }} + {{ item }}
- 查询曲线 - 查询分组 + 查询曲线 + 查询分组
-
-
-
-
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + +
@@ -176,20 +195,19 @@ total: 0 }); } - current = current.add(5, 'minute'); } return result; } - function drawLine(data, div, field, filter) { + function drawLine(data, title, div, field, filter) { if (data && data.length) { const xyData = data.map(v => [v.time, v[field]]); - const myChart = echarts.init(document.getElementById(div)); - myChart.setOption({ + const chart = echarts.init(document.getElementById(div)); + chart.setOption({ title: { - text: field + text: title }, xAxis: { type: 'time', @@ -206,6 +224,9 @@ type: 'line', data: xyData, showSymbol: false, + lineStyle: { + color: '#409eff' // 设置折线的颜色为红色 + }, } ] }) @@ -232,38 +253,44 @@ data() { return { query: { - host: "http://8.138.144.54:8080", + host: "https://do.tgsys.sztg.com", // startTime: dayjs().format('YYYY-MM-DD 00:00:00'), // endTime: dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'), - startTime: dayjs().subtract(1, 'day').format('YYYY-MM-DD 00:00:00'), - endTime: dayjs().format('YYYY-MM-DD 00:00:00'), + startTime: dayjs().format('YYYY-MM-DD 00:00:00'), + endTime: dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'), ip: "", name: "", groupBy: "name", + orderBy: "", }, data: { - host: ["http://8.138.144.54:8080"], + host: ["https://do.tgsys.sztg.com", "http://8.138.144.54:8080", "http://127.0.0.1:8080"], ip: [], name: [], groupBy: ["name", "ip"], + groupData: [], + showLine: false, + showTable: false, }, monitor: [], interval: null, }; }, methods: { - async init() { + async init(loadName = true) { const ip = await API.listIP(this.query.host, this.query) - if(ip){ + if (ip) { ip.unshift("全部") this.data.ip = ip; this.query.ip = ip[0]; } - const name = await API.listInterface(this.query.host, this.query) - if(name){ - name.unshift("全部") - this.data.name = name; - this.query.name = name[0]; + if (loadName) { + const name = await API.listInterface(this.query.host, this.query) + if(name){ + name.unshift("全部") + this.data.name = name; + this.query.name = name[0]; + } } }, async listData() { @@ -271,24 +298,40 @@ // console.log('before', data); data = fillTimeData(this.query.startTime, this.query.endTime, data); // console.log('after', data); - drawLine(data, 'total', 'total'); - drawLine(data, 'average', 'averageTime'); - drawLine(data, 'failure', 'failure'); - drawLine(data, 'timeout', 'over5000ms'); + drawLine(data, '总流量', 'total', 'total'); + drawLine(data, '平均耗时', 'average', 'averageTime'); + drawLine(data, '失败流量', 'failure', 'failure'); + drawLine(data, '超时流量', 'timeout', 'over5000ms'); + this.data.showLine = true; + this.data.showTable = false; }, + async groupData() { + let groupData = await API.groupData(this.query.host, this.query); + // groupData = groupData.filter(data => data.interfaceName && data.interfaceName.indexOf('/admin/monitor') === -1); + this.data.groupData = groupData; + this.data.showLine = false; + this.data.showTable = true; + }, + async sortChange({column, prop, order}) { + console.log('sortChange', column, prop, order); + this.query.orderBy = prop; + this.query.order = order; + console.log(this.query); + this.groupData(); + } }, async mounted() { this.init(); }, watch: { - 'query.host': async function (newVal) { - if (this.interval) { - clearTimeout(this.interval) - } - this.interval = setTimeout(async () => { - this.init(); - }, 100); - }, + // 'query.host': async function (newVal) { + // if (this.interval) { + // clearTimeout(this.interval) + // } + // this.interval = setTimeout(async () => { + // this.init(); + // }, 100); + // }, }, }); diff --git a/src/main/java/com/syzb/monitor/query/MonitorQuery.java b/src/main/java/com/syzb/monitor/query/MonitorQuery.java index a949a06..ad2f60a 100644 --- a/src/main/java/com/syzb/monitor/query/MonitorQuery.java +++ b/src/main/java/com/syzb/monitor/query/MonitorQuery.java @@ -19,6 +19,10 @@ public class MonitorQuery { private String groupBy; + private String orderBy; + + private String order; + public LocalDateTime getStartTime() { return startTime; } @@ -66,4 +70,20 @@ public class MonitorQuery { public void setGroupBy(String groupBy) { this.groupBy = groupBy; } + + public String getOrderBy() { + return orderBy; + } + + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + public String getOrder() { + return order; + } + + public void setOrder(String order) { + this.order = order; + } } diff --git a/src/main/java/com/syzb/monitor/service/MonitorService.java b/src/main/java/com/syzb/monitor/service/MonitorService.java index 479b55c..7e82f12 100644 --- a/src/main/java/com/syzb/monitor/service/MonitorService.java +++ b/src/main/java/com/syzb/monitor/service/MonitorService.java @@ -1,11 +1,14 @@ package com.syzb.monitor.service; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DatePattern; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.hazelcast.core.HazelcastInstance; import com.syzb.common.handler.BizException; import com.syzb.common.result.ResponseStatus; @@ -13,16 +16,16 @@ import com.syzb.monitor.entity.InterfaceMonitor; import com.syzb.monitor.mapper.InterfaceMonitorMapper; import com.syzb.monitor.query.MonitorQuery; import com.syzb.monitor.vo.MonitorResult; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Service @@ -39,6 +42,23 @@ public class MonitorService { // 记录保存天数 private static final int SAVE_DAY = 15; + // 固定排序字段和列关系,防止SQL注入 + private static Map ORDER_BY_MAP = new HashMap<>(); + + static { + ORDER_BY_MAP.put("total", "total"); + ORDER_BY_MAP.put("averageTime", "average_time"); + ORDER_BY_MAP.put("maxTime", "max_time"); + ORDER_BY_MAP.put("minTime", "min_time"); + ORDER_BY_MAP.put("failure", "failure"); + ORDER_BY_MAP.put("over10ms", "over_10ms"); + ORDER_BY_MAP.put("over50ms", "over_50ms"); + ORDER_BY_MAP.put("over100ms", "over_100ms"); + ORDER_BY_MAP.put("over500ms", "over_500ms"); + ORDER_BY_MAP.put("over1000ms", "over_1000ms"); + ORDER_BY_MAP.put("over5000ms", "over_5000ms"); + } + @PostConstruct private void loadHost() { host = hazelcastInstance.getCluster().getLocalMember().getAddress().getHost(); @@ -54,13 +74,32 @@ public class MonitorService { this.results.add(new MonitorResult(name, time, code)); } - @Scheduled(cron = "0 * * * * ?") - public void save() { - List list = this.statistic(); - interfaceMonitorMapper.insertBatchSomeColumn(list); + // 使用自定义线程池+任务实现定时器,避免scheduledEnable条件,只跑admin服务 + @PostConstruct + public void init() { + // 创建一个调度线程池 + ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); + + // 每分钟 保存日志 + scheduler.scheduleAtFixedRate(() -> save(), 1, 1, TimeUnit.MINUTES); + + // 每天 清理日子 + scheduler.scheduleAtFixedRate(() -> clear(), 0, 1, TimeUnit.DAYS); } - @Scheduled(cron = "0 1 2 * * ?") +// @Scheduled(cron = "0 * * * * ?") + public void save() { + // 5分钟执行一次 + if (LocalDateTime.now().getMinute() % 5 != 0) { + return; + } + List list = this.statistic(); + if (CollUtil.isNotEmpty(list)) { + interfaceMonitorMapper.insertBatchSomeColumn(list); + } + } + +// @Scheduled(cron = "0 1 2 * * ?") public void clear() { LocalDateTime time = LocalDate.now().minusDays(SAVE_DAY).atStartOfDay(); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() @@ -126,6 +165,11 @@ public class MonitorService { } else { throw new BizException(ResponseStatus.OUTSYS_ERROR); } + String orderBy = query.getOrderBy(); + if (StrUtil.isNotEmpty(orderBy)) { + orderBy = ORDER_BY_MAP.get(orderBy); + } + String order = query.getOrder(); QueryWrapper wrapper = Wrappers.query() .select(groupColumn, "sum(total) as total", "avg(average_time) as average_time", "max(max_time) as max_time", "min(min_time) as min_time", @@ -134,7 +178,9 @@ public class MonitorService { .ge("time", startTime) .lt("time", endTime) .groupBy(groupColumn) - .orderByAsc(groupColumn); + .orderByAsc(StrUtil.isEmpty(orderBy) || (!"ascending".equals(order) && !"descending".equals(order)), groupColumn) + .orderByAsc(StrUtil.isNotEmpty(orderBy) && "ascending".equals(order), orderBy) + .orderByDesc(StrUtil.isNotEmpty(orderBy) && "descending".equals(order), orderBy); return interfaceMonitorMapper.selectList(wrapper); }