diff --git a/kernel-o-monitor/monitor-api/src/main/java/cn/stylefeng/roses/kernel/monitor/api/constants/MonitorConstants.java b/kernel-o-monitor/monitor-api/src/main/java/cn/stylefeng/roses/kernel/monitor/api/constants/MonitorConstants.java index c3ed1a490..cfcb28d9f 100644 --- a/kernel-o-monitor/monitor-api/src/main/java/cn/stylefeng/roses/kernel/monitor/api/constants/MonitorConstants.java +++ b/kernel-o-monitor/monitor-api/src/main/java/cn/stylefeng/roses/kernel/monitor/api/constants/MonitorConstants.java @@ -23,11 +23,6 @@ public interface MonitorConstants { */ String MONITOR_PROMETHEUS_QUERY = "query"; - /** - * prometheus查询区间向量命令 - */ - String MONITOR_PROMETHEUS_QUERY_RANGE = "query_range"; - /** * prometheus查询开始时间 */ @@ -42,4 +37,10 @@ public interface MonitorConstants { * prometheus查询步长 */ String MONITOR_PROMETHEUS_STEP = "step"; + + /** + * prometheus查询区间向量命令 + */ + String PROMETHEUS_QUERY_RANGE = "query_range"; + } diff --git a/kernel-o-monitor/monitor-integration-beetl/README.md b/kernel-o-monitor/monitor-integration-beetl/README.md new file mode 100644 index 000000000..a48bf3446 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/README.md @@ -0,0 +1 @@ +监控模块的集成,针对于beetl模板引擎单体不分离项目 diff --git a/kernel-o-monitor/monitor-integration-beetl/pom.xml b/kernel-o-monitor/monitor-integration-beetl/pom.xml new file mode 100644 index 000000000..9674b9a86 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + + cn.stylefeng.roses + kernel-o-monitor + 7.0.1 + ../pom.xml + + + monitor-integration-beetl + + jar + + + + + + cn.stylefeng.roses + monitor-spring-boot-starter + 7.0.1 + + + + + + cn.stylefeng.roses + scanner-api + 7.0.1 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/monitor/integration/config/PrometheusConfiguration.java b/kernel-o-monitor/monitor-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/monitor/integration/config/PrometheusConfiguration.java new file mode 100644 index 000000000..dab964bfb --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/monitor/integration/config/PrometheusConfiguration.java @@ -0,0 +1,42 @@ +package cn.stylefeng.roses.kernel.monitor.integration.config; + +import cn.stylefeng.roses.kernel.monitor.api.PrometheusApi; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.Resource; + +/** + * 是否显示prometheus菜单 + * + * @author chenli + * @date 2021/3/3 17:14 + */ +@Configuration +@Slf4j +public class PrometheusConfiguration { + + @Value("${prometheus.enabled}") + private boolean prometheusEnabled; + + @Resource + private PrometheusApi prometheusApi; + + /*** + * 配置是否开启prometheus相关菜单 + * + * @author chenli + * @date 2021/3/3 17:14 + */ + @Bean + public void configPrometheusMenu() { + if (prometheusEnabled) { + prometheusApi.displayPrometheusMenu(); + } else { + prometheusApi.closePrometheusMenu(); + } + } + +} diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/monitor/integration/controller/MonitorController.java b/kernel-o-monitor/monitor-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/monitor/integration/controller/MonitorController.java new file mode 100644 index 000000000..87784bab7 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/java/cn/stylefeng/roses/kernel/monitor/integration/controller/MonitorController.java @@ -0,0 +1,297 @@ +package cn.stylefeng.roses.kernel.monitor.integration.controller; + +import cn.hutool.core.util.StrUtil; +import cn.stylefeng.roses.kernel.monitor.api.PrometheusApi; +import cn.stylefeng.roses.kernel.monitor.api.constants.MonitorConstants; +import cn.stylefeng.roses.kernel.monitor.api.pojo.prometheus.PromResultInfo; +import cn.stylefeng.roses.kernel.monitor.system.holder.SystemHardwareInfoHolder; +import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource; +import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 项目监控 + * + * @author chenli + * @date 2020/12/30 16:40 + */ +@Controller +@ApiResource(name = "项目监控") +public class MonitorController { + + @Resource + private SystemHardwareInfoHolder systemHardwareInfoHolder; + + @Value("${spring.application.name}") + private String name; + + @Value("${prometheus.url}") + private String prometheusUrl; + + @Value("${prometheus.instance}") + private String prometheusInstance; + + @Resource + private PrometheusApi service; + + /** + * 系统硬件信息页面 + * + * @author fengshuonan + * @date 2018/12/24 22:43 + */ + @GetResource(name = "服务器监控", path = "/view/monitor/systemInfo") + public String systemInfo(Model model) { + model.addAttribute("server", systemHardwareInfoHolder.getSystemHardwareInfo()); + return "/modular/system/monitor/systemInfo.html"; + } + + /** + * druid sql监控页面 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "SQL监控", path = "/view/monitor/druid") + public String druidInfo() { + return "/modular/system/monitor/druid.html"; + } + + /** + * tomcat监控页面 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "tomcat监控首页", path = "/view/monitor/tomcatInfo") + public String tomcatIndex() { + return "/modular/system/monitor/tomcatInfo.html"; + } + + /** + * tomcat监控数据 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "tomcat监控数据", path = "/view/monitor/getTomcatInfo") + @ResponseBody + public String tomcatInfo() { + Map metricMap = getMetricInfos(getPromQl(), "tomcat_", "", ""); + return JSON.toJSONString(metricMap); + } + + /** + * jvm监控页面 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "jvm监控页面", path = "/view/monitor/jvmInfo") + public String jvmIndex() { + return "/modular/system/monitor/jvmInfo.html"; + } + + /** + * jvm监控数据 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "jvm监控数据", path = "/view/monitor/getJvmInfo") + @ResponseBody + public String jvmInfo(@RequestParam("id") String id, @RequestParam("area") String area) { + Map metricMap = getMetricInfos(getPromQl(id, area), "jvm_", "", ""); + return JSON.toJSONString(metricMap); + } + + /** + * 性能监控页面 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "性能监控页面", path = "/view/monitor/performanceInfo") + public String performanceIndex() { + return "/modular/system/monitor/performanceInfo.html"; + } + + /** + * 性能监控数据 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "CPU监控数据", path = "/view/monitor/getCpuInfo") + @ResponseBody + public String cpuInfo() { + Map metricMap = getMetricInfos(getPromQl(), "cpu_", "", ""); + return JSON.toJSONString(metricMap); + } + + /** + * 服务器负载监控数据 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "服务器负载监控数据", path = "/view/monitor/getLoadInfo") + @ResponseBody + public String loadInfo() { + Map metricMap = getMetricInfos(getPromQl(), "system_", "", ""); + return JSON.toJSONString(metricMap); + } + + /** + * 进程监控数据 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "进程监控数据", path = "/view/monitor/getProcessInfo") + @ResponseBody + public String processInfo() { + Map metricMap = getMetricInfos(getPromQl(), "process_", "", ""); + return JSON.toJSONString(metricMap); + } + + /** + * 日志监控页面 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "日志监控页面", path = "/view/monitor/logbackInfo") + public String logbackIndex() { + return "/modular/system/monitor/logbackInfo.html"; + } + + /** + * 日志监控数据 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + @GetResource(name = "日志监控数据", path = "/view/monitor/getLogbackInfo") + @ResponseBody + public String logbackInfo(@RequestParam("level") String level, @RequestParam("timeInterval") String timeInterval, @RequestParam("isRate") String isRate, @RequestParam("rateMetric") String rateMetric) { + if (StrUtil.isEmpty(timeInterval)) { + timeInterval = "[5m]"; + } + Map metricMap = getMetricInfos(getIratePromQl(level, timeInterval), "logback_", isRate, rateMetric); + return JSON.toJSONString(metricMap); + } + + /** + * 组装prometheus查询sql + * + * @param id 同一指标不同分类的id号 + * @param area 查询区域jvm常用 + * @author chenli + * @date 2021/1/4 16:32 + */ + private String getPromQl(String id, String area) { + StringBuilder promql = new StringBuilder("{application=\""); + promql.append(name); + if (!StrUtil.isEmpty(id)) { + promql.append("\",id=\""); + promql.append(id); + } + if (!StrUtil.isEmpty(area)) { + promql.append("\",area=\""); + promql.append(area); + } + if (!StrUtil.isEmpty(prometheusInstance)) { + promql.append("\",instance=\""); + promql.append(prometheusInstance); + } + promql.append("\"}"); + return promql.toString(); + } + + /** + * 组装prometheus查询sql方法重写不带参数 + * + * @author chenli + * @date 2021/1/4 16:32 + */ + private String getPromQl() { + StringBuilder promql = new StringBuilder("{application=\""); + promql.append(name); + if (!StrUtil.isEmpty(prometheusInstance)) { + promql.append("\",instance=\""); + promql.append(prometheusInstance); + } + promql.append("\"}"); + return promql.toString(); + } + + /** + * 组装prometheus平均值查询sql方法重写不带参数 + * + * @param level 日志统计查询参数,info、warn、error、trace、debug + * @param timeInterval 统计时间区间单位通常为分钟(m) + * @author chenli + * @date 2021/1/4 16:32 + */ + private String getIratePromQl(String level, String timeInterval) { + StringBuilder promql = new StringBuilder("{application=\""); + promql.append(name); + if (!StrUtil.isEmpty(prometheusInstance)) { + promql.append("\",instance=\""); + promql.append(prometheusInstance); + } + if (!StrUtil.isEmpty(level)) { + promql.append("\",level=\""); + promql.append(level); + } + promql.append("\"}"); + promql.append(timeInterval); + return promql.toString(); + } + + /** + * 分别输出监控名称以及对应的值 + * + * @param promQL prometheus查询sql + * @param metric prometheus指标前缀,比如:"jvm_" + * @param isRate prometheus计算函数,不需要计算周期内值就直接为"",需要计算则写计算函数以及对应的指标 + * @author chenli + * @date 2021/1/4 16:32 + */ + private Map getMetricInfos(String promQL, String metric, String isRate, String rateMetric) { + Map metricMap = new HashMap<>(); + if (!StrUtil.isEmpty(prometheusUrl)) { + List promResultInfos = service.getMetricInfo(prometheusUrl.concat(MonitorConstants.PROMETHEUS_QUERY_RANGE), promQL, isRate, rateMetric); + if (Objects.isNull(promResultInfos)) { + return metricMap; + } + for (PromResultInfo promResultInfo : promResultInfos) { + String metricName = promResultInfo.getMetric().get__name__(); + JSONArray valueArray = JSONArray.parseArray(JSON.toJSONString(promResultInfo.getValues()).replaceAll("\\\\", "").replace("\"", "")); + if (!StrUtil.isEmpty(metricName)) { + if (metricName.contains(metric)) { + // 得到的数据为数组,需要转为json字符串去除双引号再转化为JSONArray,JSONArray是echarts时间序列图需要的数据格式 + metricMap.put(metricName, valueArray); + } + } else { + // 查询指定的指标 + metricMap.put(rateMetric, valueArray); + } + } + } + return metricMap; + } +} diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/resources/META-INF/spring.factories b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..3a9994383 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + cn.stylefeng.roses.kernel.monitor.integration.config.PrometheusConfiguration diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/resources/assets/common/js/echartInit.js b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/assets/common/js/echartInit.js new file mode 100644 index 000000000..6eb5e7e3b --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/assets/common/js/echartInit.js @@ -0,0 +1,171 @@ +function initGraph(params){ + const paramsId = echarts.init(document.getElementById(params.id), myEchartsTheme); + let metricData = params.metric; + const option = { + title: { + text: params.id, + x: 'center' + }, + tooltip: { + trigger: 'axis', + formatter: function (datas){ + let res; + datas.map(function (e,i) { + if (res == undefined){ + let datetime = new Date(e.value[0]*1000); + res = datetime.getUTCFullYear().toString()+'-'+datetime.getUTCMonth().toString()+'-'+datetime.getUTCDate().toString()+' '+datetime.getHours().toString()+':'+ datetime.getMinutes().toString() + ':' + datetime.getSeconds().toString() + '
' + } + if (params.unit === 'MB' && e.value[1]>0){ + res += e.marker +" " + e.seriesName + ' : ' + (e.value[1]/1000/1000).toFixed(2) + params.unit + '
' + } else { + res += e.marker +" " + e.seriesName + ' : ' + e.value[1] + '
' + } + }) + return res; + } + }, + xAxis: { + type: 'time', + axisLabel: { + formatter: function(value,index){ + let datetime = new Date(value*1000) + return datetime.getHours().toString()+':'+ datetime.getMinutes().toString() + } + } + }, + yAxis: { + name: params.unit, + type: 'value', + scale: true, + axisLabel: { + formatter: function(value,index){ + if (params.unit == 'MB' && value>0){ + return value/1000/1000 + } else { + return value + } + } + } + }, + series: [{type : 'line', + smooth: true, + animationDuration: 2000, + animationEasing: 'quadraticOut', + name : params.id, + data: metricData, + areaStyle: { // 折现下是否填充 + color: this.color, + opacity: 0.6 + }, + showSymbol: false}], + }; + paramsId.setOption(option); +} + +// 初始化三个数据指标 +function initMultiGraph(multiParams){ + const multiParamsId = echarts.init(document.getElementById(multiParams.id), myEchartsTheme); + let metricData = multiParams.metric; + const option = { + title: { text: multiParams.title, x: 'center' }, + tooltip: { + trigger: 'axis', + formatter: function (datas){ + let res; + datas.map(function (e,i) { + if (res == undefined){ + let datetime = new Date(e.value[0]*1000); + res = datetime.getUTCFullYear().toString()+'-'+datetime.getUTCMonth().toString()+'-'+datetime.getUTCDate().toString()+' '+datetime.getHours().toString()+':'+ datetime.getMinutes().toString() + ':' + datetime.getSeconds().toString() + '
' + } + if (multiParams.unit === 'MB' && e.value[1]>0){ + res += e.marker +" " + e.seriesName + ' : ' + (e.value[1]/1000/1000).toFixed(2) + multiParams.unit + '
' + } else { + res += e.marker +" " + e.seriesName + ' : ' + e.value[1] + '
' + } + }) + return res; + } + }, + legend: { + top:"8%", + formatter: function (name) { + return name; + } + }, + xAxis: { + type: 'time', + axisLabel: { + formatter: function(value,index){ + let datetime = new Date(value*1000) + return datetime.getHours().toString()+':'+ datetime.getMinutes().toString() + } + } + }, + yAxis: { + name: multiParams.unit, + type: 'value', + scale: true, + axisLabel: { + formatter: function(value,index){ + if (multiParams.unit == 'MB' && value>0){ + return value/1000/1000 + } else { + return value + } + } + } + }, + series: [{type : 'line', + smooth: true, + lineStyle : { + color: '#63BAC9', + width : 2, + type : 'solid', + }, + animationDuration: 2000, + animationEasing: 'quadraticOut', + name: metricData.metric1.name, + data: metricData.metric1.value, + areaStyle: { + color: '#1D292D', + opacity: 0.2 + }, + smoothMonotone: 'x', + showSymbol: false}, + {type : 'line', + smooth: true, + lineStyle : { + color: '#B29943', + width : 2, + type : 'solid', + }, + animationDuration: 2000, + animationEasing: 'quadraticOut', + name: metricData.metric2.name, + data: metricData.metric2.value, + areaStyle: { + color: '#313830', + opacity: 0.2 + }, + smoothMonotone: 'x', + showSymbol: false}, + {type : 'line', + smooth: true, + lineStyle : { + color: '#7CA76D', + width : 2, + type : 'solid', + }, + animationDuration: 2000, + animationEasing: 'quadraticOut', + name: metricData.metric3.name, + data: metricData.metric3.value, + areaStyle: { + color: '#394437', + opacity: 0.2 + }, + smoothMonotone: 'x', + showSymbol: false}] + }; + multiParamsId.setOption(option); +} \ No newline at end of file diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/jvmInfo.html b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/jvmInfo.html new file mode 100644 index 000000000..b4897d42f --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/jvmInfo.html @@ -0,0 +1,223 @@ + + + + + + + ${constants.getSystemName()} + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +@/* 加入contextPath属性和session超时的配置 */ + + + + + + + + + \ No newline at end of file diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/logbackInfo.html b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/logbackInfo.html new file mode 100644 index 000000000..f1904efe5 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/logbackInfo.html @@ -0,0 +1,94 @@ + + + + + + + ${constants.getSystemName()} + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +@/* 加入contextPath属性和session超时的配置 */ + + + + + + + + + \ No newline at end of file diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/performanceInfo.html b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/performanceInfo.html new file mode 100644 index 000000000..8bf2fe826 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/performanceInfo.html @@ -0,0 +1,134 @@ + + + + + + + ${constants.getSystemName()} + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +@/* 加入contextPath属性和session超时的配置 */ + + + + + + + + + \ No newline at end of file diff --git a/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/tomcatInfo.html b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/tomcatInfo.html new file mode 100644 index 000000000..b45d0cc25 --- /dev/null +++ b/kernel-o-monitor/monitor-integration-beetl/src/main/resources/pages/modular/system/monitor/tomcatInfo.html @@ -0,0 +1,187 @@ + + + + + + + ${constants.getSystemName()} + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + @/* 加入contextPath属性和session超时的配置 */ + + + + + + + + + \ No newline at end of file diff --git a/kernel-o-monitor/pom.xml b/kernel-o-monitor/pom.xml index acf4fb0e4..1abded52f 100644 --- a/kernel-o-monitor/pom.xml +++ b/kernel-o-monitor/pom.xml @@ -17,6 +17,7 @@ monitor-api + monitor-integration-beetl monitor-sdk-system-info monitor-spring-boot-starter monitor-sdk-prometheus