Browse Source

机器模块和 JVM 状态页面

reghao 4 years ago
parent
commit
b390399af8
19 changed files with 220 additions and 155 deletions
  1. 4 4
      common/src/main/java/cn/reghao/autodop/common/jvm/JVM.java
  2. 7 5
      common/src/main/java/cn/reghao/autodop/common/jvm/pojo/MemoryStat.java
  3. 7 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/MachinePageController.java
  4. 11 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/query/MachineQuery.java
  5. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/MachineHost.java
  6. 3 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/MachineStatus.java
  7. 0 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/info/MachineInfo.java
  8. 11 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/vo/MachineAddress.java
  9. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/vo/MachineHostVO.java
  10. 3 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/repository/MachineHostRepository.java
  11. 0 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/DagentOpsService.java
  12. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/job/MachineStatCheckJob.java
  13. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/processor/DagentOpsProcessor.java
  14. 9 21
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysController.java
  15. 16 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysPageController.java
  16. 10 15
      dmaster/src/main/resources/templates/app/config/app/index.html
  17. 8 8
      dmaster/src/main/resources/templates/machine/host.html
  18. 38 36
      dmaster/src/main/resources/templates/machine/status.html
  19. 85 44
      dmaster/src/main/resources/templates/sys/jvmstatus.html

+ 4 - 4
common/src/main/java/cn/reghao/autodop/common/jvm/JVM.java

@@ -81,13 +81,13 @@ public class JVM {
         return jvmStat;
     }
 
-    public List<BufferPoolStat> bufferPoolStat() {
+    private List<BufferPoolStat> bufferPoolStat() {
         List<BufferPoolStat> list = new ArrayList<>();
         bufferPoolBeans.forEach(bufferPoolBean -> list.add(new BufferPoolStat(bufferPoolBean)));
         return list;
     }
 
-    public Map<String, MemoryPoolStat> memoryPoolStat() {
+    private Map<String, MemoryPoolStat> memoryPoolStat() {
         Map<String, MemoryPoolStat> map = new HashMap<>();
         memoryPoolBeans.forEach(
                 // TODO name 是否唯一?
@@ -95,13 +95,13 @@ public class JVM {
         return map;
     }
 
-    public List<GarbageCollectorStat> gcStat() {
+    private List<GarbageCollectorStat> gcStat() {
         List<GarbageCollectorStat> list = new ArrayList<>();
         gcBeans.forEach(gcBean -> list.add(new GarbageCollectorStat(gcBean)));
         return list;
     }
 
-    public List<ThreadStat> threadStat() {
+    private List<ThreadStat> threadStat() {
         List<ThreadStat> list = new ArrayList<>();
         Arrays.stream(threadBean.getThreadInfo(threadBean.getAllThreadIds()))
                 .forEach(threadInfo -> list.add(new ThreadStat(threadInfo)));

+ 7 - 5
common/src/main/java/cn/reghao/autodop/common/jvm/pojo/MemoryStat.java

@@ -1,5 +1,7 @@
 package cn.reghao.autodop.common.jvm.pojo;
 
+import cn.reghao.autodop.common.utils.ByteConverter;
+import cn.reghao.autodop.common.utils.ByteType;
 import lombok.Data;
 
 import java.lang.management.MemoryUsage;
@@ -16,10 +18,10 @@ public class MemoryStat {
     private String committed;
 
     public MemoryStat(MemoryUsage memoryUsage) {
-        /*ByteConverter convert = new ByteConverter();
-        this.init = convert.convert(memoryUsage.getInit(), ByteType.Byte);
-        this.max = convert.convert(memoryUsage.getMax(), ByteType.Byte);
-        this.used = convert.convert(memoryUsage.getUsed(), ByteType.Byte);
-        this.committed = convert.convert(memoryUsage.getCommitted(), ByteType.Byte);*/
+        ByteConverter convert = new ByteConverter();
+        this.init = convert.convertStr(ByteType.Bytes, ByteType.MiB, memoryUsage.getInit());
+        this.max = convert.convertStr(ByteType.Bytes, ByteType.MiB, memoryUsage.getMax());
+        this.used = convert.convertStr(ByteType.Bytes, ByteType.MiB, memoryUsage.getUsed());
+        this.committed = convert.convertStr(ByteType.Bytes, ByteType.MiB, memoryUsage.getCommitted());
     }
 }

+ 7 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/MachinePageController.java

@@ -11,7 +11,7 @@ import cn.reghao.autodop.dmaster.machine.entity.po.MachineHost;
 import cn.reghao.autodop.dmaster.machine.entity.po.MachineStat;
 import cn.reghao.autodop.dmaster.machine.entity.po.SshAuth;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.MachineInfo;
-import cn.reghao.autodop.dmaster.machine.entity.vo.HostInfo;
+import cn.reghao.autodop.dmaster.machine.entity.vo.MachineHostVO;
 import cn.reghao.autodop.dmaster.machine.service.ssh.Keys;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
 import cn.reghao.autodop.dmaster.notification.repository.NotifyGroupRepository;
@@ -75,8 +75,8 @@ public class MachinePageController {
         queryMap.put("env", env);
         PageRequest pageRequest = PageSort.pageRequest();
         Page<MachineHost> page = machineQuery.queryByMatchAll(queryMap, pageRequest);
-        Page<HostInfo> hostInfos = page.map(HostInfo::new);
-        PageList<HostInfo> pageList = PageList.pageList(hostInfos);
+        Page<MachineHostVO> hostInfos = page.map(MachineHostVO::new);
+        PageList<MachineHostVO> pageList = PageList.pageList(hostInfos);
 
         model.addAttribute("env", env);
         model.addAttribute("page", page);
@@ -87,8 +87,8 @@ public class MachinePageController {
     private void searchByMachineIpv4(String env, String machineIpv4, Model model) {
         List<MachineHost> list = machineQuery.queryByMachineIpv4(machineIpv4);
         Page<MachineHost> page = new PageImpl<>(list);
-        Page<HostInfo> hostInfos = page.map(HostInfo::new);
-        PageList<HostInfo> pageList = PageList.pageList(hostInfos);
+        Page<MachineHostVO> hostInfos = page.map(MachineHostVO::new);
+        PageList<MachineHostVO> pageList = PageList.pageList(hostInfos);
 
         model.addAttribute("env", env);
         model.addAttribute("page", page);
@@ -181,8 +181,8 @@ public class MachinePageController {
         queryMap.put("env", env);
         PageRequest pageRequest = PageSort.pageRequest();
         Page<MachineHost> page = machineQuery.queryByMatchAll(queryMap, pageRequest);
-        Page<HostInfo> hostInfos = page.map(HostInfo::new);
-        PageList<HostInfo> pageList = PageList.pageList(hostInfos);
+        Page<MachineHostVO> hostInfos = page.map(MachineHostVO::new);
+        PageList<MachineHostVO> pageList = PageList.pageList(hostInfos);
 
         model.addAttribute("env", env);
         model.addAttribute("page", page);

+ 11 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/query/MachineQuery.java

@@ -3,6 +3,7 @@ package cn.reghao.autodop.dmaster.machine.db.query;
 import cn.reghao.autodop.dmaster.machine.entity.po.MachineHost;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.NetworkInfo;
+import cn.reghao.autodop.dmaster.machine.entity.vo.MachineAddress;
 import cn.reghao.autodop.dmaster.machine.repository.MachineHostRepository;
 import cn.reghao.autodop.dmaster.machine.repository.MachineInfoRepository;
 import org.springframework.data.domain.Page;
@@ -14,6 +15,7 @@ import javax.persistence.criteria.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -40,6 +42,15 @@ public class MachineQuery {
         return list.isEmpty() ? null : list.get(0);
     }
 
+    public List<MachineAddress> queryMachineByEnv(String env) {
+        return hostRepository.findByEnv(env).stream()
+                .map(machineHost -> {
+                    MachineInfo machineInfo = machineHost.getMachineInfo();
+                    return new MachineAddress(machineInfo.getMachineId(), machineInfo.machineIpv4());
+                })
+                .collect(Collectors.toList());
+    }
+
     public List<MachineHost> queryByMatchAll(Map<String, String> kv) {
         Specification<MachineHost> specification = matchSpec(kv);
         return hostRepository.findAll(specification);

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/MachineHost.java

@@ -39,7 +39,7 @@ public class MachineHost extends BaseEntity<Integer> {
     public MachineHost(MachineInfo machineInfo) {
         this.machineInfo = machineInfo;
         this.env = EnvType.test.name();
-        this.status = StatusType.UP.name();
+        this.status = MachineStatus.UP.name();
         this.lastCheck = LocalDateTime.now();
     }
 }

+ 3 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/MachineStatus.java

@@ -1,9 +1,11 @@
 package cn.reghao.autodop.dmaster.machine.entity.po;
 
 /**
+ * 机器状态,可用/不可用
+ *
  * @author reghao
  * @date 2021-06-16 15:18:17
  */
-public enum StatusType {
+public enum MachineStatus {
     UP, DOWN
 }

+ 0 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/info/MachineInfo.java

@@ -2,9 +2,7 @@ package cn.reghao.autodop.dmaster.machine.entity.po.info;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
-
 import java.util.List;
-
 import cn.reghao.autodop.dmaster.common.orm.BaseEntity;
 import org.hibernate.annotations.LazyCollection;
 import org.hibernate.annotations.LazyCollectionOption;

+ 11 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/vo/MachineAddress.java

@@ -1,7 +1,15 @@
 package cn.reghao.autodop.dmaster.machine.entity.vo;
-/**     
- * @author          reghao
- * @date            2021-07-09 17:10:47
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-07-09 17:10:47
  */
+@AllArgsConstructor
+@Data
 public class MachineAddress {
+    private String machineId;
+    private String machineIpv4;
 }

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/vo/MachineHostVO.java

@@ -12,7 +12,7 @@ import java.util.List;
  * @date 2020-10-19 15:02:59
  */
 @Data
-public class HostInfo {
+public class MachineHostVO {
     private String machineId;
     private String machineIpv4;
     private String bootTime;
@@ -22,7 +22,7 @@ public class HostInfo {
     private String status;
     private String lastCheck;
 
-    public HostInfo(MachineHost machineHost) {
+    public MachineHostVO(MachineHost machineHost) {
         this.machineId = machineHost.getMachineInfo().getMachineId();
         List<NetworkInfo> list = machineHost.getMachineInfo().getNetworkInfos();
         if (!list.isEmpty()) {

+ 3 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/repository/MachineHostRepository.java

@@ -7,6 +7,8 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
+import java.util.List;
+
 /**
  * @author reghao
  * @date 2020-01-21 14:53:03
@@ -14,5 +16,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 public interface MachineHostRepository
         extends JpaRepository<MachineHost, Integer>, JpaSpecificationExecutor<MachineHost> {
     MachineHost findByMachineInfo(MachineInfo machineInfo);
+    List<MachineHost> findByEnv(String env);
     Page<MachineHost> findByIsDeleteFalse(Pageable pageable);
 }

+ 0 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/DagentOpsService.java

@@ -99,7 +99,6 @@ public class DagentOpsService {
             machineHost.setLastCheck(LocalDateTime.now());
             hostCrudService.insertOrUpdate(machineHost);
         }
-
         statCrudService.insertOrUpdate(machineStat);
     }
 

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/job/MachineStatCheckJob.java

@@ -11,7 +11,7 @@ import cn.reghao.autodop.dmaster.machine.db.query.MachineQuery;
 import cn.reghao.autodop.dmaster.machine.db.query.MachineStatQuery;
 import cn.reghao.autodop.dmaster.machine.entity.po.MachineHost;
 import cn.reghao.autodop.dmaster.machine.entity.po.MachineStat;
-import cn.reghao.autodop.dmaster.machine.entity.po.StatusType;
+import cn.reghao.autodop.dmaster.machine.entity.po.MachineStatus;
 import cn.reghao.autodop.dmaster.monitor.db.MonitorJobCrudService;
 import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
@@ -73,7 +73,7 @@ public class MachineStatCheckJob implements Job {
                 return;
             }
 
-            machineStat.setStatus(StatusType.DOWN.name());
+            machineStat.setStatus(MachineStatus.DOWN.name());
             statCrudService.insertOrUpdate(machineStat);
             // TODO 检测 IP 是否能 ping 通
             // TODO 检测 MQTT 服务器是否正常连接

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/processor/DagentOpsProcessor.java

@@ -4,7 +4,7 @@ import cn.reghao.autodop.common.message.ops.DagentOps;
 import cn.reghao.autodop.common.utils.serializer.JsonConverter;
 import cn.reghao.autodop.common.message.ops.OpsProcessor;
 import cn.reghao.autodop.dmaster.machine.entity.po.MachineStat;
-import cn.reghao.autodop.dmaster.machine.entity.po.StatusType;
+import cn.reghao.autodop.dmaster.machine.entity.po.MachineStatus;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.service.DagentOpsService;
 import cn.reghao.autodop.dmaster.sys.entity.AppRuntimeLog;
@@ -56,14 +56,14 @@ public class DagentOpsProcessor implements OpsProcessor {
 
     private void processDagentHeartbeat(String payload) {
         MachineStat machineStat = JsonConverter.jsonToObject(payload, MachineStat.class);
-        machineStat.setStatus(StatusType.UP.name());
+        machineStat.setStatus(MachineStatus.UP.name());
         machineStat.setLastCheck(LocalDateTime.now());
         dagentOpsService.heartbeat(machineStat);
     }
 
     private void processDagentShutdown(String payload) {
         MachineStat machineStat = JsonConverter.jsonToObject(payload, MachineStat.class);
-        machineStat.setStatus(StatusType.DOWN.name());
+        machineStat.setStatus(MachineStatus.DOWN.name());
         machineStat.setLastCheck(LocalDateTime.now());
         dagentOpsService.shutdown(machineStat);
     }

+ 9 - 21
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysController.java

@@ -19,7 +19,9 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
-import java.io.*;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
 /**
@@ -27,36 +29,23 @@ import java.nio.charset.StandardCharsets;
  * @date 2021-04-04 21:24:18
  */
 @Api(tags = "用户页面")
-@RequestMapping("/sys")
-@Controller
-public class SysPageController {
+@RequestMapping("/api/sys")
+@RestController
+public class SysController {
     private BakService bakService;
     private UploadDownload uploadDownload;
     private RoleRepository roleRepository;
 
-    public SysPageController(BakService bakService,
-                             UploadDownload uploadDownload,
-                             RoleRepository roleRepository) {
+    public SysController(BakService bakService,
+                         UploadDownload uploadDownload,
+                         RoleRepository roleRepository) {
         this.bakService = bakService;
         this.uploadDownload = uploadDownload;
         this.roleRepository = roleRepository;
     }
 
-    @ApiOperation(value = "系统备份还原页面")
-    @GetMapping("/bak")
-    public String sysBakPage(Model model) {
-        PageRequest pageRequest = PageSort.pageRequest();
-        Page<Role> rolePage = roleRepository.findAll(pageRequest);
-        PageList<Role> pageList = PageList.pageList(rolePage);
-
-        model.addAttribute("page", rolePage);
-        model.addAttribute("list", pageList.getList());
-        return "/sys/bak";
-    }
-
     @ApiOperation(value = "数据备份")
     @GetMapping("/bak/export")
-    @ResponseBody
     public void dataBackup(HttpServletResponse response) throws IOException {
         String json = bakService.bakSysConfig();
         ByteArrayInputStream bytesIn = new ByteArrayInputStream(json.getBytes());
@@ -66,7 +55,6 @@ public class SysPageController {
 
     @ApiOperation(value = "数据还原")
     @PostMapping("/bak/import")
-    @ResponseBody
     public String dataRestore(@RequestParam("file") MultipartFile file) throws IOException {
         byte[] bytes = file.getBytes();
         String json = new String(bytes, StandardCharsets.UTF_8);

+ 16 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysPageController.java

@@ -1,5 +1,8 @@
 package cn.reghao.autodop.dmaster.sys.controller;
 
+import cn.reghao.autodop.common.jvm.JVM;
+import cn.reghao.autodop.common.jvm.pojo.JvmInfo;
+import cn.reghao.autodop.common.jvm.pojo.JvmStat;
 import cn.reghao.autodop.common.utils.serializer.JsonConverter;
 import cn.reghao.autodop.dmaster.auth.entity.Role;
 import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
@@ -33,6 +36,7 @@ public class SysPageController {
     private BakService bakService;
     private UploadDownload uploadDownload;
     private RoleRepository roleRepository;
+    private JVM jvm;
 
     public SysPageController(BakService bakService,
                              UploadDownload uploadDownload,
@@ -40,6 +44,7 @@ public class SysPageController {
         this.bakService = bakService;
         this.uploadDownload = uploadDownload;
         this.roleRepository = roleRepository;
+        this.jvm = new JVM();
     }
 
     @ApiOperation(value = "系统备份还原页面")
@@ -54,6 +59,17 @@ public class SysPageController {
         return "/sys/bak";
     }
 
+    @ApiOperation(value = "JVM 状态页面")
+    @GetMapping("/jvmstatus")
+    public String jvmStatusPage(Model model) {
+        JvmInfo jvmInfo = jvm.info();
+        JvmStat jvmStat = jvm.stat();
+
+        model.addAttribute("jvmInfo", jvmInfo);
+        model.addAttribute("jvmStat", jvmStat);
+        return "/sys/jvmstatus";
+    }
+
     @ApiOperation(value = "数据备份")
     @GetMapping("/bak/export")
     @ResponseBody

+ 10 - 15
dmaster/src/main/resources/templates/app/config/app/index.html

@@ -67,13 +67,11 @@
                     </th>
                     <th class="sortable" data-field="appName">应用名</th>
                     <th class="sortable" data-field="appId">应用 ID</th>
-                    <th class="sortable" data-field="env">环境</th>
                     <th class="sortable" data-field="repoBranch">分支</th>
                     <th class="sortable" data-field="appType">应用类型</th>
-                    <th class="sortable" data-field="repoAuth">仓库认证</th>
-                    <th class="sortable" data-field="compiler">编译器</th>
-                    <th class="sortable" data-field="packer">打包工具</th>
                     <th class="sortable" data-field="httpPort">HTTP 端口</th>
+                    <th>构建配置</th>
+                    <th>部署配置</th>
                     <th>通知组</th>
                     <th>操作</th>
                 </tr>
@@ -84,20 +82,17 @@
                         <i class="layui-icon layui-icon-ok"></i></label></td>
                     <td th:text="${item.appName}">应用名</td>
                     <td th:text="${item.appId}">应用 ID</td>
-                    <td th:text="${item.env}">环境</td>
                     <td th:text="${item.repoBranch}">分支</td>
                     <td th:text="${item.appType}">应用类型</td>
-                    <span th:if="${item.proj} != null">
-                        <td th:text="${item.proj.repoAuthConfig.name}">仓库认证</td>
-                        <td th:text="${item.proj.compilerConfig.name}">编译器</td>
-                        <td th:text="${item.proj.packerConfig.name}">打包工具</td>
-                    </span>
-                    <span th:if="${item.proj} == null">
-                        <td th:text="${item.repoAuthConfig.name}">仓库认证</td>
-                        <td th:text="${item.compilerConfig.name}">编译器</td>
-                        <td th:text="${item.packerConfig.name}">打包工具</td>
-                    </span>
                     <td th:text="${item.runningConfig?.httpPort?: ''}">HTTP 端口</td>
+                    <td>
+                        <a class="open-popup" data-title="构建配置" th:attr="data-url=@{'/app/config/app/notify/'+${item.id}}"
+                           data-size="640,480" href="#">查看</a>
+                    </td>
+                    <td>
+                        <a class="open-popup" data-title="部署配置" th:attr="data-url=@{'/app/config/app/notify/'+${item.id}}"
+                           data-size="640,480" href="#">设置</a>
+                    </td>
                     <td>
                         <a class="open-popup" data-title="设置通知组" th:attr="data-url=@{'/app/config/app/notify/'+${item.id}}"
                            data-size="640,480" href="#">设置</a>

+ 8 - 8
dmaster/src/main/resources/templates/machine/host.html

@@ -39,18 +39,18 @@
             <table class="layui-table timo-table">
                 <thead>
                 <tr>
-                    <!-- TODO 使用 checkbox 批量指定环境 -->
+                    <!-- TODO 使用 checkbox 批量设置环境 -->
                     <th class="timo-table-checkbox">
                         <label class="timo-checkbox"><input type="checkbox">
                             <i class="layui-icon layui-icon-ok"></i></label>
                     </th>
-                    <th class="sortable" data-field="machineIpv4">机器地址</th>
-                    <th class="sortable" data-field="bootTime">启动时间</th>
-                    <th class="sortable" data-field="status">当前状态</th>
-                    <th class="sortable" data-field="lastCheck">上次心跳时间</th>
-                    <th class="sortable" data-field="osArch">系统架构</th>
-                    <th class="sortable" data-field="osName">系统名字</th>
-                    <th class="sortable" data-field="osVersion">系统版本</th>
+                    <th data-field="machineIpv4">机器地址</th>
+                    <th data-field="bootTime">启动时间</th>
+                    <th data-field="status">当前状态</th>
+                    <th data-field="lastCheck">上次心跳时间</th>
+                    <th data-field="osArch">系统架构</th>
+                    <th data-field="osName">系统名字</th>
+                    <th data-field="osVersion">系统版本</th>
                     <th>通知组</th>
                     <th>SSH 认证</th>
                     <th>SSH 控制台</th>

+ 38 - 36
dmaster/src/main/resources/templates/machine/status.html

@@ -38,44 +38,46 @@
         <div class="timo-table-wrap">
             <table class="layui-table timo-table">
                 <thead>
-                <tr>
-                    <th class="sortable" data-field="machineIpv4">机器地址</th>
-                    <th class="sortable" data-field="status">系统负载</th>
-                    <th class="sortable" data-field="lastCheck">网络状态</th>
-                    <th class="sortable" data-field="memAvail">CPU 使用率</th>
-                    <th class="sortable" data-field="memAvail">内存详情</th>
-                    <th class="sortable" data-field="diskAvail">磁盘详情</th>
-                </tr>
+                    <tr>
+                        <th data-field="machineIpv4">机器地址</th>
+                        <th data-field="status">当前状态</th>
+                        <th data-field="status">系统负载</th>
+                        <th data-field="lastCheck">网络状态</th>
+                        <th data-field="memAvail">CPU 使用率</th>
+                        <th data-field="memAvail">内存详情</th>
+                        <th data-field="diskAvail">磁盘详情</th>
+                    </tr>
                 </thead>
                 <tbody>
-                <tr th:each="item:${list}">
-                    <td th:text="${item.machineIpv4}">机器地址</td>
-                    <td>
-                        <a class="open-popup" data-title="系统负载"
-                           th:attr="data-url=@{'/machine/status/sys/'+${item.machineId}}" data-size="800,600"
-                           href="#">查看</a>
-                    </td>
-                    <td>
-                        <a class="open-popup" data-title="网络状态"
-                           th:attr="data-url=@{'/machine/status/network/'+${item.machineId}}" data-size="1200,600"
-                           href="#">查看</a>
-                    </td>
-                    <td>
-                        <a class="open-popup" data-title="CPU 使用率"
-                           th:attr="data-url=@{'/machine/status/cpu/'+${item.machineId}}" data-size="800,600"
-                           href="#">查看</a>
-                    </td>
-                    <td>
-                        <a class="open-popup" data-title="内存详情"
-                           th:attr="data-url=@{'/machine/status/mem/'+${item.machineId}}" data-size="800,600"
-                           href="#">查看</a>
-                    </td>
-                    <td>
-                        <a class="open-popup" data-title="磁盘详情"
-                           th:attr="data-url=@{'/machine/status/disk/'+${item.machineId}}" data-size="1200,600"
-                           href="#">查看</a>
-                    </td>
-                </tr>
+                    <tr th:each="item:${list}">
+                        <td th:text="${item.machineIpv4}">机器地址</td>
+                        <td th:text="${item.status}">当前状态</td>
+                        <td>
+                            <a class="open-popup" data-title="系统负载"
+                               th:attr="data-url=@{'/machine/status/sys/'+${item.machineId}}" data-size="800,600"
+                               href="#">查看</a>
+                        </td>
+                        <td>
+                            <a class="open-popup" data-title="网络状态"
+                               th:attr="data-url=@{'/machine/status/network/'+${item.machineId}}" data-size="1200,600"
+                               href="#">查看</a>
+                        </td>
+                        <td>
+                            <a class="open-popup" data-title="CPU 使用率"
+                               th:attr="data-url=@{'/machine/status/cpu/'+${item.machineId}}" data-size="800,600"
+                               href="#">查看</a>
+                        </td>
+                        <td>
+                            <a class="open-popup" data-title="内存详情"
+                               th:attr="data-url=@{'/machine/status/mem/'+${item.machineId}}" data-size="800,600"
+                               href="#">查看</a>
+                        </td>
+                        <td>
+                            <a class="open-popup" data-title="磁盘详情"
+                               th:attr="data-url=@{'/machine/status/disk/'+${item.machineId}}" data-size="1200,600"
+                               href="#">查看</a>
+                        </td>
+                    </tr>
                 </tbody>
             </table>
         </div>

+ 85 - 44
dmaster/src/main/resources/templates/sys/jvmstatus.html

@@ -3,50 +3,91 @@
 <head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
 
 <body class="timo-layout-page">
-<div class="layui-card" th:attr="data-url=@{/sys/bak}">
-    <div class="layui-card-header timo-card-header">
-        <span><i class="fa fa-bars"></i> 备份还原</span>
-        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
-    </div>
-    <div class="layui-card-body">
-        <div class="timo-table-wrap">
-            <table class="layui-table timo-table">
-                <thead>
-                <tr>
-                    <th class="timo-table-checkbox">
-                        <label class="timo-checkbox"><input type="checkbox">
-                            <i class="layui-icon layui-icon-ok"></i></label>
-                    </th>
-                    <th class="sortable" data-field="title">数据源</th>
-                    <th class="sortable" data-field="name">角色名</th>
-                    <th class="sortable" data-field="createTime">最近一次备份</th>
-                    <th class="sortable" data-field="updateTime">最近一次还原</th>
-                    <th>备份</th>
-                    <th>还原</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr th:each="item:${list}">
-                    <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.id}">
-                        <i class="layui-icon layui-icon-ok"></i></label></td>
-                    <td th:text="${item.title}">数据源</td>
-                    <td th:text="${item.name}">角色名</td>
-                    <td th:text="${item.createTime}">最近一次备份</td>
-                    <td th:text="${item.updateTime}">最近一次还原</td>
-                    <td>
-                        <a th:href="@{/sys/bak/export}"><i class="fa fa-download"></i></a>
-                    </td>
-                    <td>
-                        <button type="button" class="layui-btn upload-image" name="file[]"
-                                th:attr="up-url=@{/sys/bak/import}" up-field="path">
-                            <i class="fa fa-upload"></i>
-                        </button>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-    </div>
+<div class="timo-detail-page">
+    <div class="timo-detail-title">系统信息</div>
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>系统名字</th>
+            <td th:text="${jvmInfo.osName}"></td>
+            <th>系统架构</th>
+            <td th:text="${jvmInfo.osArch}"></td>
+            <th>系统版本</th>
+            <td th:text="${jvmInfo.osVersion}"></td>
+        </tr>
+        </tbody>
+    </table>
+    <div class="timo-detail-title">Java 信息</div>
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>Java Runtime 名字</th>
+            <td th:text="${jvmInfo.javaRuntimeName}"></td>
+            <th>Java Runtime 版本</th>
+            <td th:text="${jvmInfo.javaRuntimeVersion}"></td>
+            <th>Java Class 版本</th>
+            <td th:text="${jvmInfo.javaClassVersion}"></td>
+        </tr>
+        </tbody>
+    </table>
+    <div class="timo-detail-title">JVM 信息</div>
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>JVM 名字</th>
+            <td th:text="${jvmInfo.jvmName}"></td>
+            <th>JVM 版本</th>
+            <td th:text="${jvmInfo.jvmVersion}"></td>
+            <th>JVM Vendor</th>
+            <td th:text="${jvmInfo.jvmVendor}"></td>
+            <th>JVM 进程 ID</th>
+            <td th:text="${jvmInfo.jvmPid}"></td>
+            <th>JVM 启动时间</th>
+            <td th:text="${jvmInfo.jvmStartTime}"></td>
+        </tr>
+        </tbody>
+    </table>
+    <div class="timo-detail-title">类加载详情</div>
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>已加载类数量</th>
+            <td th:text="${jvmStat.jvmClassesLoaded}"></td>
+            <th>未加载类数量</th>
+            <td th:text="${jvmStat.jvmClassesUnloaded}"></td>
+            <th>JVM 总的类总量</th>
+            <td th:text="${jvmStat.jvmClassesTotal}"></td>
+        </tr>
+        </tbody>
+    </table>
+    <div class="timo-detail-title">堆区和非堆区内存详情</div>
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>初始化堆大小</th>
+            <td th:text="${jvmStat.jvmMemoryHeapInit}"></td>
+            <th>堆最大值</th>
+            <td th:text="${jvmStat.jvmMemoryHeapMax}"></td>
+            <th>已使用堆大小</th>
+            <td th:text="${jvmStat.jvmMemoryHeapUsed}"></td>
+            <th>已提交堆大小</th>
+            <td th:text="${jvmStat.jvmMemoryHeapCommitted}"></td>
+        </tr>
+        </tbody>
+    </table>
+    <div class="timo-detail-title">线程详情</div>
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>活动线程数</th>
+            <td th:text="${jvmStat.jvmThreadsLive}"></td>
+            <th>守护线程数</th>
+            <td th:text="${jvmStat.jvmThreadsDaemon}"></td>
+            <th>线程最大数</th>
+            <td th:text="${jvmStat.jvmThreadsPeak}"></td>
+        </tr>
+        </tbody>
+    </table>
 </div>
 
 <script th:replace="/common/template :: script"></script>