增加获取客户端资源监控页面

This commit is contained in:
seagull 2019-05-06 14:48:33 +08:00
parent 93ea27aea5
commit 5136a2db37
13 changed files with 890 additions and 5 deletions

View File

@ -27,7 +27,7 @@
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version> <thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
<mybatis.spring.boot.starter.version>1.3.2</mybatis.spring.boot.starter.version> <mybatis.spring.boot.starter.version>1.3.2</mybatis.spring.boot.starter.version>
<pagehelper.spring.boot.starter.version>1.2.5</pagehelper.spring.boot.starter.version> <pagehelper.spring.boot.starter.version>1.2.5</pagehelper.spring.boot.starter.version>
<fastjson.version>1.2.47</fastjson.version> <fastjson.version>1.2.58</fastjson.version>
<druid.version>1.1.10</druid.version> <druid.version>1.1.10</druid.version>
<commons.io.version>2.5</commons.io.version> <commons.io.version>2.5</commons.io.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version> <commons.fileupload.version>1.3.3</commons.fileupload.version>

View File

@ -77,7 +77,6 @@ public class RunAutomationTestTask
log.error("测试任务执行,远程链接客户端出现异常..."); log.error("测试任务执行,远程链接客户端出现异常...");
taskExecute.setTaskStatus(4); taskExecute.setTaskStatus(4);
taskExecuteService.updateTaskExecute(taskExecute); taskExecuteService.updateTaskExecute(taskExecute);
throw new ConnectException();
} catch (KeyManagementException e) { } catch (KeyManagementException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@ -0,0 +1,101 @@
package com.luckyframe.project.monitor.server.domain.set;
import java.math.BigDecimal;
/**
* CPU相关信息
*
* @author ruoyi
*/
public class SetCpu
{
/**
* 核心数
*/
private int cpuNum;
/**
* CPU总的使用率
*/
private BigDecimal total;
/**
* CPU系统使用率
*/
private BigDecimal sys;
/**
* CPU用户使用率
*/
private BigDecimal used;
/**
* CPU当前等待率
*/
private BigDecimal wait;
/**
* CPU当前空闲率
*/
private BigDecimal free;
public int getCpuNum()
{
return cpuNum;
}
public void setCpuNum(int cpuNum)
{
this.cpuNum = cpuNum;
}
public BigDecimal getTotal()
{
return total;
}
public void setTotal(BigDecimal total)
{
this.total = total;
}
public BigDecimal getSys()
{
return sys;
}
public void setSys(BigDecimal sys)
{
this.sys = sys;
}
public BigDecimal getUsed()
{
return used;
}
public void setUsed(BigDecimal used)
{
this.used = used;
}
public BigDecimal getWait()
{
return wait;
}
public void setWait(BigDecimal wait)
{
this.wait = wait;
}
public BigDecimal getFree()
{
return free;
}
public void setFree(BigDecimal free)
{
this.free = free;
}
}

View File

@ -0,0 +1,133 @@
package com.luckyframe.project.monitor.server.domain.set;
import java.lang.management.ManagementFactory;
import java.math.BigDecimal;
import com.luckyframe.common.utils.DateUtils;
/**
* JVM相关信息
*
* @author ruoyi
*/
public class SetJvm
{
/**
* 当前JVM占用的内存总数(M)
*/
private BigDecimal total;
/**
* JVM最大可用内存总数(M)
*/
private BigDecimal max;
/**
* JVM空闲内存(M)
*/
private BigDecimal free;
/**
* JDK版本
*/
private String version;
/**
* JDK路径
*/
private String home;
private BigDecimal used;
private BigDecimal usage;
public BigDecimal getTotal()
{
return total;
}
public void setTotal(BigDecimal total)
{
this.total = total;
}
public BigDecimal getMax()
{
return max;
}
public void setMax(BigDecimal max)
{
this.max = max;
}
public BigDecimal getFree()
{
return free;
}
public void setFree(BigDecimal free)
{
this.free = free;
}
public BigDecimal getUsed() {
return used;
}
public void setUsed(BigDecimal used) {
this.used = used;
}
public BigDecimal getUsage() {
return usage;
}
public void setUsage(BigDecimal usage) {
this.usage = usage;
}
/**
* 获取JDK名称
*/
public String getName()
{
return ManagementFactory.getRuntimeMXBean().getVmName();
}
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getHome()
{
return home;
}
public void setHome(String home)
{
this.home = home;
}
/**
* JDK启动时间
*/
public String getStartTime()
{
return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
}
/**
* JDK运行时间
*/
public String getRunTime()
{
return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
}
}

View File

@ -0,0 +1,67 @@
package com.luckyframe.project.monitor.server.domain.set;
import java.math.BigDecimal;
/**
* 內存相关信息
*
* @author ruoyi
*/
public class SetMem
{
/**
* 内存总量
*/
private BigDecimal total;
/**
* 已用内存
*/
private BigDecimal used;
/**
* 剩余内存
*/
private BigDecimal free;
private BigDecimal usage;
public BigDecimal getTotal()
{
return total;
}
public void setTotal(BigDecimal total)
{
this.total = total;
}
public BigDecimal getUsed()
{
return used;
}
public void setUsed(BigDecimal used)
{
this.used = used;
}
public BigDecimal getFree()
{
return free;
}
public void setFree(BigDecimal free)
{
this.free = free;
}
public BigDecimal getUsage() {
return usage;
}
public void setUsage(BigDecimal usage) {
this.usage = usage;
}
}

View File

@ -0,0 +1,88 @@
package com.luckyframe.project.monitor.server.domain.set;
import java.util.LinkedList;
import java.util.List;
/**
* 服务器相关信息
*
* @author ruoyi
*/
public class SetServer
{
/**
* CPU相关信息
*/
private SetCpu cpu = new SetCpu();
/**
* 內存相关信息
*/
private SetMem mem = new SetMem();
/**
* JVM相关信息
*/
private SetJvm jvm = new SetJvm();
/**
* 服务器相关信息
*/
private SetSys sys = new SetSys();
/**
* 磁盘相关信息
*/
private List<SetSysFile> sysFiles = new LinkedList<SetSysFile>();
public SetCpu getCpu()
{
return cpu;
}
public void setCpu(SetCpu cpu)
{
this.cpu = cpu;
}
public SetMem getMem()
{
return mem;
}
public void setMem(SetMem mem)
{
this.mem = mem;
}
public SetJvm getJvm()
{
return jvm;
}
public void setJvm(SetJvm jvm)
{
this.jvm = jvm;
}
public SetSys getSys()
{
return sys;
}
public void setSys(SetSys sys)
{
this.sys = sys;
}
public List<SetSysFile> getSysFiles()
{
return sysFiles;
}
public void setSysFiles(List<SetSysFile> sysFiles)
{
this.sysFiles = sysFiles;
}
}

View File

@ -0,0 +1,84 @@
package com.luckyframe.project.monitor.server.domain.set;
/**
* 系统相关信息
*
* @author ruoyi
*/
public class SetSys
{
/**
* 服务器名称
*/
private String computerName;
/**
* 服务器Ip
*/
private String computerIp;
/**
* 项目路径
*/
private String userDir;
/**
* 操作系统
*/
private String osName;
/**
* 系统架构
*/
private String osArch;
public String getComputerName()
{
return computerName;
}
public void setComputerName(String computerName)
{
this.computerName = computerName;
}
public String getComputerIp()
{
return computerIp;
}
public void setComputerIp(String computerIp)
{
this.computerIp = computerIp;
}
public String getUserDir()
{
return userDir;
}
public void setUserDir(String userDir)
{
this.userDir = userDir;
}
public String getOsName()
{
return osName;
}
public void setOsName(String osName)
{
this.osName = osName;
}
public String getOsArch()
{
return osArch;
}
public void setOsArch(String osArch)
{
this.osArch = osArch;
}
}

View File

@ -0,0 +1,116 @@
package com.luckyframe.project.monitor.server.domain.set;
import java.math.BigDecimal;
/**
* 系统文件相关信息
*
* @author ruoyi
*/
public class SetSysFile
{
/**
* 盘符路径
*/
private String dirName;
/**
* 盘符类型
*/
private String sysTypeName;
/**
* 文件类型
*/
private String typeName;
/**
* 总大小
*/
private String total;
/**
* 剩余大小
*/
private String free;
/**
* 已经使用量
*/
private String used;
/**
* 资源的使用率
*/
private BigDecimal usage;
public String getDirName()
{
return dirName;
}
public void setDirName(String dirName)
{
this.dirName = dirName;
}
public String getSysTypeName()
{
return sysTypeName;
}
public void setSysTypeName(String sysTypeName)
{
this.sysTypeName = sysTypeName;
}
public String getTypeName()
{
return typeName;
}
public void setTypeName(String typeName)
{
this.typeName = typeName;
}
public String getTotal()
{
return total;
}
public void setTotal(String total)
{
this.total = total;
}
public String getFree()
{
return free;
}
public void setFree(String free)
{
this.free = free;
}
public String getUsed()
{
return used;
}
public void setUsed(String used)
{
this.used = used;
}
public BigDecimal getUsage()
{
return usage;
}
public void setUsage(BigDecimal usage)
{
this.usage = usage;
}
}

View File

@ -1,5 +1,6 @@
package com.luckyframe.project.system.client.controller; package com.luckyframe.project.system.client.controller;
import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -15,9 +16,12 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.luckyframe.common.constant.ClientConstants;
import com.luckyframe.common.constant.JobConstants; import com.luckyframe.common.constant.JobConstants;
import com.luckyframe.common.constant.ScheduleConstants; import com.luckyframe.common.constant.ScheduleConstants;
import com.luckyframe.common.exception.BusinessException; import com.luckyframe.common.exception.BusinessException;
import com.luckyframe.common.utils.client.HttpRequest;
import com.luckyframe.common.utils.poi.ExcelUtil; import com.luckyframe.common.utils.poi.ExcelUtil;
import com.luckyframe.common.utils.security.PermissionUtils; import com.luckyframe.common.utils.security.PermissionUtils;
import com.luckyframe.framework.aspectj.lang.annotation.Log; import com.luckyframe.framework.aspectj.lang.annotation.Log;
@ -27,6 +31,7 @@ import com.luckyframe.framework.web.domain.AjaxResult;
import com.luckyframe.framework.web.page.TableDataInfo; import com.luckyframe.framework.web.page.TableDataInfo;
import com.luckyframe.project.monitor.job.domain.Job; import com.luckyframe.project.monitor.job.domain.Job;
import com.luckyframe.project.monitor.job.service.IJobService; import com.luckyframe.project.monitor.job.service.IJobService;
import com.luckyframe.project.monitor.server.domain.set.SetServer;
import com.luckyframe.project.system.client.domain.Client; import com.luckyframe.project.system.client.domain.Client;
import com.luckyframe.project.system.client.service.IClientService; import com.luckyframe.project.system.client.service.IClientService;
import com.luckyframe.project.system.project.service.IProjectService; import com.luckyframe.project.system.project.service.IProjectService;
@ -72,6 +77,23 @@ public class ClientController extends BaseController
return getDataTable(list); return getDataTable(list);
} }
@RequiresPermissions("system:client:view")
@GetMapping("/showMonitor/{clientId}")
public String showMonitor(@PathVariable("clientId") Integer clientId, ModelMap mmap) throws Exception
{
Client client = clientService.selectClientById(clientId);
String result = HttpRequest.httpClientGet(
"http://" + client.getClientIp() + ":" + ClientConstants.CLIENT_MONITOR_PORT + "/getClientMonitorData",
new HashMap<String, Object>(0));
System.out.println(result);
JSONObject jSONObject = JSONObject.parseObject(result);
System.out.println(jSONObject.toJSONString());
SetServer server = JSONObject.parseObject(jSONObject.toJSONString(),SetServer.class);
System.out.println(JSONObject.toJSONString(server));
mmap.put("server", server);
return prefix + "/showMonitor";
}
/** /**
* 导出客户端管理列表 * 导出客户端管理列表

View File

@ -18,7 +18,7 @@ $(document).ready(function(){
},"请填写正确的座机号码"); },"请填写正确的座机号码");
// IP地址验证 // IP地址验证
jQuery.validator.addMethod("isIp", function(value, element) { jQuery.validator.addMethod("isIp", function(value, element) {
return this.optional(element) || /^(([1-9]|([1-9]\d)|(1\d\d)|(2([0-4]\d|5[0-5])))\.)(([1-9]|([1-9]\d)|(1\d\d)|(2([0-4]\d|5[0-5])))\.){2}([1-9]|([1-9]\d)|(1\d\d)|(2([0-4]\d|5[0-5])))$/.test(value); return this.optional(element) || /^(([1-9]|([1-9]\d)|(1\d\d)|(2([0-4]\d|5[0-5])))\.)(([0-9]|([1-9]\d)|(1\d\d)|(2([0-4]\d|5[0-5])))\.){2}([1-9]|([1-9]\d)|(1\d\d)|(2([0-4]\d|5[0-5])))$/.test(value);
}, "请填写正确的IP地址。"); }, "请填写正确的IP地址。");
//姓名校验 //姓名校验
jQuery.validator.addMethod("isName",function(value,element){ jQuery.validator.addMethod("isName",function(value,element){

View File

@ -140,7 +140,7 @@
<div class="col-sm-4"> <div class="col-sm-4">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>扫一扫加入QQ交流</h5> <h5>扫一扫加入QQ群</h5>
</div> </div>
<div class="ibox-content no-padding"> <div class="ibox-content no-padding">
<div class="panel-body" style="text-align:center;"> <div class="panel-body" style="text-align:center;">

View File

@ -38,6 +38,9 @@
<a class="btn btn-primary btn-edit disabled" onclick="$.operate.edit()" shiro:hasPermission="system:client:edit"> <a class="btn btn-primary btn-edit disabled" onclick="$.operate.edit()" shiro:hasPermission="system:client:edit">
<i class="fa fa-edit"></i> 修改 <i class="fa fa-edit"></i> 修改
</a> </a>
<a class="btn btn-info btn-edit disabled" onclick="showMonitor()" shiro:hasPermission="system:client:view">
<i class="fa fa-edit"></i> 监控资源
</a>
<a class="btn btn-danger btn-del btn-del disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:client:remove"> <a class="btn btn-danger btn-del btn-del disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:client:remove">
<i class="fa fa-remove"></i> 删除 <i class="fa fa-remove"></i> 删除
</a> </a>
@ -60,6 +63,7 @@
updateUrl: prefix + "/edit/{id}", updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove", removeUrl: prefix + "/remove",
exportUrl: prefix + "/export", exportUrl: prefix + "/export",
customUrl: prefix + "/showMonitor/{id}",
modalName: "客户端", modalName: "客户端",
search: false, search: false,
showExport: true, showExport: true,
@ -81,7 +85,7 @@
}, },
{ {
field : 'status', field : 'status',
title : '客户端超时', title : '客户端状态',
formatter : function(value, formatter : function(value,
row, index) { row, index) {
if(value==0){ if(value==0){
@ -122,6 +126,23 @@
}; };
$.table.init(options); $.table.init(options);
}); });
function showMonitor() {
var row= $.map($('#bootstrap-table').bootstrapTable('getSelections'), function (row) {
return row;
});
if(0!=row[0].status){
$.modal.msgWarning("客户端非正常状态,不能查询");
return true;
}
var url = "/404.html";
if ($.common.isNotEmpty(row)) {
url = $.table._option.customUrl.replace("{id}", row[0].clientId);
}
$.modal.openViewFull("客户端资源监控 "+row[0].clientName+" ["+row[0].clientIp+"]", url, null, null);
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,254 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg" id="test">
<div class="wrapper wrapper-content">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-6">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>CPU</h5>
<div class="ibox-tools">
<a class="collapse-link"><i class="fa fa-chevron-up"></i>
</a>
<a class="close-link"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="ibox-content">
<table class="table table-hover no-margins">
<thead>
<tr>
<th>属性</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>核心数</td>
<td th:text="${server.cpu.cpuNum}">0个</td>
</tr>
<tr>
<td>用户使用率</td>
<td th:text="${server.cpu.used + '%'}">0%</td>
</tr>
<tr>
<td>系统使用率</td>
<td th:text="${server.cpu.sys + '%'}">0%</td>
</tr>
<tr>
<td>当前空闲率</td>
<td th:text="${server.cpu.free + '%'}">0%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>内存</h5>
<div class="ibox-tools">
<a class="collapse-link"><i class="fa fa-chevron-up"></i></a>
<a class="close-link"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="ibox-content">
<table class="table table-hover no-margins">
<thead>
<tr>
<th>属性</th>
<th>内存</th>
<th>JVM</th>
</tr>
</thead>
<tbody>
<tr>
<td>总内存</td>
<td th:text="${server.mem.total + 'G'}">0GB</td>
<td th:text="${server.jvm.total + 'M'}">0MB</td>
</tr>
<tr>
<td>已用内存</td>
<td th:text="${server.mem.used + 'G'}">0GB</td>
<td th:text="${server.jvm.used + 'M'}">0MB</td>
</tr>
<tr>
<td>剩余内存</td>
<td th:text="${server.mem.free + 'G'}">0GB</td>
<td th:text="${server.jvm.free + 'M'}">0MB</td>
</tr>
<tr>
<td>使用率</td>
<td th:class="${server.mem.usage gt 80} ? 'text-danger'">[[${server.mem.usage}]]%</td>
<td th:class="${server.jvm.usage gt 80} ? 'text-danger'">[[${server.jvm.usage}]]%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>服务器信息</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="row">
<div class="col-sm-12">
<table class="table table-hover margin bottom">
<tbody>
<tr>
<td>服务器名称</td>
<td th:text="${server.sys.computerName}">RuoYi</td>
<td>操作系统</td>
<td th:text="${server.sys.osName}">Linux</td>
</tr>
<tr>
<td>服务器IP</td>
<td th:text="${server.sys.computerIp}">127.0.0.1</td>
<td>系统架构</td>
<td th:text="${server.sys.osArch}">amd64</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>Java虚拟机信息</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="row">
<div class="col-sm-12">
<table class="table table-hover margin bottom">
<tbody>
<tr>
<td>Java名称</td>
<td th:text="${server.jvm.name}">Java</td>
<td>Java版本</td>
<td th:text="${server.jvm.version}">1.8.0</td>
</tr>
<tr>
<td>启动时间</td>
<td th:text="${server.jvm.startTime}">2018-12-31 00:00:00</td>
<td>运行时长</td>
<td th:text="${server.jvm.runTime}">0天0时0分0秒</td>
</tr>
<tr>
<td colspan="1">安装路径</td>
<td colspan="3" th:text="${server.jvm.home}"></td>
</tr>
<tr>
<td colspan="1">项目路径</td>
<td colspan="3" th:text="${server.sys.userDir}"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>磁盘状态</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="row">
<div class="col-sm-12">
<table class="table table-hover margin bottom">
<thead>
<tr>
<th>盘符路径</th>
<th>文件系统</th>
<th>盘符类型</th>
<th>总大小</th>
<th>可用大小</th>
<th>已用大小</th>
<th>已用百分比</th>
</tr>
</thead>
<tbody>
<tr th:each="sysFile : ${server.sysFiles}">
<td th:text="${sysFile.dirName}">C:\</td>
<td th:text="${sysFile.sysTypeName}">NTFS</td>
<td th:text="${sysFile.typeName}">local</td>
<td th:text="${sysFile.total}">0GB</td>
<td th:text="${sysFile.free}">0GB</td>
<td th:text="${sysFile.used}">0GB</td>
<td th:class="${sysFile.usage gt 80} ? 'text-danger'">[[${sysFile.usage}]]%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<div th:include="include :: footer"></div>
<script>
$(".modal").appendTo("body"), $("[data-toggle=popover]").popover(), $(".collapse-link").click(function() {
var div_ibox = $(this).closest("div.ibox"),
e = $(this).find("i"),
i = div_ibox.find("div.ibox-content");
i.slideToggle(200),
e.toggleClass("fa-chevron-up").toggleClass("fa-chevron-down"),
div_ibox.toggleClass("").toggleClass("border-bottom"),
setTimeout(function() {
div_ibox.resize();
}, 50);
}), $(".close-link").click(function () {
var div_ibox = $(this).closest("div.ibox");
div_ibox.remove()
});
</script>
</html>