Browse Source

又重新改了一边监控功能 :-(

reghao 5 years ago
parent
commit
117c5a0f80
38 changed files with 477 additions and 1078 deletions
  1. 2 0
      common/src/main/java/cn/reghao/autodop/common/dagent/machine/Machine.java
  2. 2 0
      common/src/main/java/cn/reghao/autodop/common/dagent/machine/MachineStat.java
  3. 0 1
      common/src/main/java/cn/reghao/autodop/common/message/AsyncMsg.java
  4. 18 0
      common/src/main/java/cn/reghao/autodop/common/mqtt/DefaultMqttClient.java
  5. 0 1
      dagent/src/main/java/cn/reghao/autodop/dagent/mqttsub/DmasterMsgDispatcher.java
  6. 2 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppStatusService.java
  7. 1 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/AppDeployer.java
  8. 2 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/MachinePageController.java
  9. 0 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/crud/MachineInfoCrudService.java
  10. 6 10
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/crud/MachineStatCrudService.java
  11. 75 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/stat/MachineStat.java
  12. 6 6
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/MachineService.java
  13. 4 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/vo/HostInfo.java
  14. 20 92
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/controller/MonitorController.java
  15. 23 191
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/controller/MonitorPageController.java
  16. 0 37
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/AppMonitor.java
  17. 0 39
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/BaseMonitor.java
  18. 0 28
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/MachineMonitor.java
  19. 18 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/MonitorJob.java
  20. 0 11
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/MonitorType.java
  21. 0 12
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/repository/AppMonitorRepository.java
  22. 0 12
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/repository/MachineMonitorRepository.java
  23. 12 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/repository/MonitorJobRepository.java
  24. 0 49
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/AppMonitorServiceImpl.java
  25. 0 126
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MachineMonitorServiceImpl.java
  26. 29 28
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorListService.java
  27. 8 100
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorScheduler.java
  28. 7 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorService.java
  29. 174 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorServiceImpl.java
  30. 0 48
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/job/machine/MachineDiskUsageCheckJob.java
  31. 13 9
      dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/job/machine/MachineHeartbeatCheckJob.java
  32. 18 95
      dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/processor/DagentOpsProcessor.java
  33. 12 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/clazz/PackageScanner.java
  34. 5 6
      dmaster/src/main/resources/templates/monitor/edit.html
  35. 19 15
      dmaster/src/main/resources/templates/monitor/index.html
  36. 0 81
      dmaster/src/main/resources/templates/monitor/machinemonitor.html
  37. 0 57
      dmaster/src/main/resources/templates/monitor/monitorjobs.html
  38. 1 1
      dmaster/src/main/resources/templates/monitor/monitornotify.html

+ 2 - 0
common/src/main/java/cn/reghao/autodop/common/dagent/machine/Machine.java

@@ -11,6 +11,7 @@ import cn.reghao.autodop.common.utils.MachineIdentity;
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
+import java.time.LocalDateTime;
 
 /**
  * @author reghao
@@ -47,6 +48,7 @@ public class Machine {
     public MachineStat heartbeat() {
         MachineStat machineStat = new MachineStat();
         machineStat.setMachineId(machineId);
+        machineStat.setMachineTime(LocalDateTime.now());
         machineStat.setOsStat(os.stat());
         machineStat.setNetworkStat(network.stat());
         machineStat.setCpuStat(null);

+ 2 - 0
common/src/main/java/cn/reghao/autodop/common/dagent/machine/MachineStat.java

@@ -7,6 +7,7 @@ import cn.reghao.autodop.common.dagent.machine.network.NetworkStat;
 import cn.reghao.autodop.common.dagent.machine.os.OsStat;
 import lombok.Data;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -16,6 +17,7 @@ import java.util.List;
 @Data
 public class MachineStat {
     private String machineId;
+    private LocalDateTime machineTime;
     private OsStat osStat;
     private NetworkStat networkStat;
     private CpuStat cpuStat;

+ 0 - 1
common/src/main/java/cn/reghao/autodop/common/message/AsyncMsg.java

@@ -28,7 +28,6 @@ public class AsyncMsg {
 
     public static AsyncMsg asyncMsg(String machineId, String type, String ops, String payload) {
         AsyncMsg asyncMsg = new AsyncMsg();
-        asyncMsg.setMsgId(UUID.randomUUID().toString());
         asyncMsg.setMachineId(machineId);
         asyncMsg.setSendTime(System.currentTimeMillis());
         asyncMsg.setType(type);

+ 18 - 0
common/src/main/java/cn/reghao/autodop/common/mqtt/DefaultMqttClient.java

@@ -2,6 +2,7 @@ package cn.reghao.autodop.common.mqtt;
 
 import cn.reghao.autodop.common.message.AsyncMsg;
 import cn.reghao.autodop.common.utils.MachineIdentity;
+import cn.reghao.autodop.common.utils.serializer.JsonConverter;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.paho.client.mqttv3.*;
 import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
@@ -107,6 +108,23 @@ public class DefaultMqttClient implements AutoCloseable {
         client.publish(topic, message);
     }
 
+    /**
+     * pub 消息后,等 sub 端处理后在 pub 结果
+     *
+     * @param
+     * @return
+     * @date 2021-06-30 上午11:22
+     */
+    public void pubWithResult(String topic, int qos, AsyncMsg asyncMsg) throws MqttException {
+        MqttMessage message = new MqttMessage();
+        message.setQos(qos);
+        message.setPayload(JsonConverter.objectToJson(asyncMsg).getBytes());
+
+        connect();
+        client.publish(topic, message);
+        pubSubRecorder.put(asyncMsg.getMsgId(), asyncMsg);
+    }
+
     class MqttClientCallback implements MqttCallbackExtended {
         @Override
         public void connectComplete(boolean reconnect, String serverUri) {

+ 0 - 1
dagent/src/main/java/cn/reghao/autodop/dagent/mqttsub/DmasterMsgDispatcher.java

@@ -8,7 +8,6 @@ import cn.reghao.autodop.dagent.mqttsub.processor.machine.MachineOpsProcessor;
 import cn.reghao.autodop.dagent.utils.DagentLifecycle;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
-import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
 import org.eclipse.paho.client.mqttv3.MqttCallback;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
 import org.springframework.stereotype.Component;

+ 2 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppStatusService.java

@@ -64,8 +64,7 @@ public class AppStatusService {
 
         String topic = "dagent/" + machineId;
         try {
-            mqttClient.pub(topic, 1, JsonConverter.objectToJson(asyncMsg));
-            mqttClient.putRecord(asyncMsg.getMsgId(), asyncMsg);
+            mqttClient.pubWithResult(topic, 1, asyncMsg);
         } catch (MqttException e) {
             e.printStackTrace();
         }
@@ -103,8 +102,7 @@ public class AppStatusService {
 
         String topic = "dagent/" + machineId;
         try {
-            mqttClient.pub(topic, 1, JsonConverter.objectToJson(asyncMsg));
-            mqttClient.putRecord(asyncMsg.getMsgId(), asyncMsg);
+            mqttClient.pubWithResult(topic, 1, asyncMsg);
         } catch (MqttException e) {
             e.printStackTrace();
         }

+ 1 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/AppDeployer.java

@@ -55,8 +55,7 @@ public class AppDeployer {
 
             // TODO 对于需要返回值的 pub,需要做一个记录,pub 和 sub 一一对应
             String topic = "dagent/" + machineId;
-            mqttClient.pub(topic, 1, JsonConverter.objectToJson(asyncMsg));
-            mqttClient.putRecord(asyncMsg.getMsgId(), asyncMsg);
+            mqttClient.pubWithResult(topic, 1, asyncMsg);
         }
     }
 

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

@@ -48,6 +48,8 @@ public class MachinePageController {
                            @RequestParam(value = "machineIpv4", required = false) String machineIpv4,
                            Model model) {
         PageRequest pageRequest = PageSort.pageRequest();
+
+
         Page<MachineInfo> page = infoCrudService.selectByPage(pageRequest);
         Page<HostInfo> hostInfos = page.map(machineService::hostInfo);
         PageList<HostInfo> pageList = PageList.pageList(hostInfos);

+ 0 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/crud/MachineInfoCrudService.java

@@ -2,7 +2,6 @@ package cn.reghao.autodop.dmaster.machine.db.crud;
 
 import cn.reghao.autodop.dmaster.machine.entity.info.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.repository.MachineInfoRepository;
-import cn.reghao.autodop.dmaster.common.orm.CrudOps;
 import org.springframework.cache.annotation.CacheConfig;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;

+ 6 - 10
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/crud/MachineStatCrudService.java

@@ -1,6 +1,7 @@
 package cn.reghao.autodop.dmaster.machine.db.crud;
 
 import cn.reghao.autodop.dmaster.machine.entity.stat.MachineStat;
+import cn.reghao.autodop.dmaster.machine.entity.stat.StatusType;
 import cn.reghao.autodop.dmaster.machine.repository.MachineStatRepository;
 import com.github.benmanes.caffeine.cache.Cache;
 import org.springframework.stereotype.Service;
@@ -24,22 +25,17 @@ public class MachineStatCrudService {
         this.statRepository = statRepository;
     }
 
-    public void insertOrUpdate(MachineStat machineStat) {
-        MachineStat stat = statRepository.findByMachineId(machineStat.getMachineId());
-        if (stat != null) {
-            machineStat.setId(stat.getId());
-            machineStat.setCreateTime(stat.getCreateTime());
-            machineStat.setUpdateTime(LocalDateTime.now());
-        }
+    public void insert(MachineStat machineStat) {
         statRepository.save(machineStat);
         //cache.put(machineStat.getMachineId(), machineStat);
     }
 
-    public void delete(MachineStat machineStat) {
+    public void update(MachineStat machineStat) {
+        machineStat.setLastCheck(LocalDateTime.now());
+        statRepository.save(machineStat);
     }
 
-    public MachineStat selectByPk(Integer id) {
-        return null;
+    public void delete(MachineStat machineStat) {
     }
 
     public MachineStat selectByUk(String machineId) {

+ 75 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/stat/MachineStat.java

@@ -4,25 +4,33 @@ import cn.reghao.autodop.common.dagent.machine.cpu.CpuStat;
 import cn.reghao.autodop.common.dagent.machine.disk.DiskInfo;
 import cn.reghao.autodop.common.dagent.machine.memory.MemoryInfo;
 import cn.reghao.autodop.common.dagent.machine.network.NetworkStat;
+import cn.reghao.autodop.common.dagent.machine.network.TcpConnStat;
+import cn.reghao.autodop.common.dagent.machine.network.TcpState;
 import cn.reghao.autodop.common.dagent.machine.os.OsStat;
+import cn.reghao.autodop.common.utils.ByteConverter;
+import cn.reghao.autodop.common.utils.ByteType;
+import cn.reghao.autodop.common.utils.PercentCalculator;
 import cn.reghao.autodop.dmaster.common.orm.BaseDocument;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.mongodb.core.mapping.Document;
 
 import java.time.LocalDateTime;
-import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
  * @date 2020-12-25 17:53:15
  */
+@Slf4j
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Document("MachineStat")
 public class MachineStat extends BaseDocument {
     private String machineId;
+    private LocalDateTime machineTime;
     private OsStat osStat;
     private NetworkStat networkStat;
     private CpuStat cpuStat;
@@ -39,10 +47,74 @@ public class MachineStat extends BaseDocument {
     }
 
     public MemoryUsage getMemoryUsage() {
-        return null;
+        long total = memoryInfo.getTotal();
+        long used = memoryInfo.getUsed();
+        long avail = memoryInfo.getAvailable();
+        long totalSwap = memoryInfo.getSwapTotal();
+        long usedSwap = memoryInfo.getSwapUsed();
+        long availSwap = memoryInfo.getSwapFree();
+
+        ByteConverter converter = new ByteConverter();
+        String totalSize = converter.convertStr(ByteType.KiB, ByteType.MiB, total);
+        String usedSize = converter.convertStr(ByteType.KiB, ByteType.MiB, used);
+        String availSize = converter.convertStr(ByteType.KiB, ByteType.MiB, avail);
+        String swapTotalSize = converter.convertStr(ByteType.KiB, ByteType.MiB, totalSwap);
+        String swapUsedSize = converter.convertStr(ByteType.KiB, ByteType.MiB, usedSwap);
+        String swapAvailSize = converter.convertStr(ByteType.KiB, ByteType.MiB, availSwap);
+
+        MemoryUsage memoryUsage = new MemoryUsage();
+        memoryUsage.setTotal(totalSize);
+        memoryUsage.setUsed(usedSize);
+        memoryUsage.setAvail(availSize);
+        memoryUsage.setSwapTotal(swapTotalSize);
+        memoryUsage.setSwapUsed(swapUsedSize);
+        memoryUsage.setSwapAvail(swapAvailSize);
+
+        return memoryUsage;
+    }
+
+    public void memoryUsage() {
+        long total = memoryInfo.getTotal();
+        long avail = memoryInfo.getAvailable();
+
+        ByteConverter converter = new ByteConverter();
+        String availSize = converter.convertStr(ByteType.KiB, ByteType.MiB, avail);
+
+        double value = PercentCalculator.percentValue(avail, total);
+        String percent = PercentCalculator.percent(value);
+        double minimalPercent = 0.20;
+        if (value < minimalPercent) {
+            // TODO 发出告警通知
+            log.info("{} 上可用的内存仅占内存的 {},共计 {}", machineId, percent, availSize);
+        }
     }
 
     public List<DiskUsage> getDiskUsages() {
-        return Collections.emptyList();
+        return diskInfos.stream().map(DiskUsage::new).collect(Collectors.toList());
+    }
+
+    public void diskUsage() {
+        long total = 0, avail = 0;
+        for (DiskInfo diskInfo : diskInfos) {
+            total += diskInfo.getSize();
+            avail += diskInfo.getAvail();
+        }
+
+        ByteConverter converter = new ByteConverter();
+        String availSize = converter.convert(ByteType.Bytes, ByteType.MiB, avail) + ByteType.MiB.name();
+        double value = PercentCalculator.percentValue(avail, total);
+        String percent = PercentCalculator.percent(value);
+        double minimalPercent = 0.20;
+        if (value < minimalPercent) {
+            // TODO 发出告警通知
+            log.info("{} 上可用的磁盘空间仅占总磁盘空间的 {},共计 {}", machineId, percent, availSize);
+        }
+    }
+
+    public Integer getTcpConnNum() {
+        List<TcpConnStat> list = networkStat.getTcpConnStats().stream()
+                .filter(tcpConnStat -> tcpConnStat.getTcpState().equals(TcpState.TCP_ESTABLISHED.name()))
+                .collect(Collectors.toList());
+        return list.size();
     }
 }

+ 6 - 6
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/MachineService.java

@@ -2,6 +2,7 @@ package cn.reghao.autodop.dmaster.machine.service;
 
 import cn.reghao.autodop.dmaster.machine.db.crud.MachineStatCrudService;
 import cn.reghao.autodop.dmaster.machine.entity.info.MachineInfo;
+import cn.reghao.autodop.dmaster.machine.entity.stat.MachineStat;
 import cn.reghao.autodop.dmaster.machine.vo.HostInfo;
 import org.springframework.stereotype.Service;
 
@@ -11,15 +12,14 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class MachineService {
-    private MachineStatCrudService machineStatusCrudService;
+    private MachineStatCrudService statCrudService;
 
-    public MachineService(MachineStatCrudService machineStatusCrudService) {
-        this.machineStatusCrudService = machineStatusCrudService;
+    public MachineService(MachineStatCrudService statCrudService) {
+        this.statCrudService = statCrudService;
     }
 
     public HostInfo hostInfo(MachineInfo machineInfo) {
-        /*MachineStat machineStatus = machineStatusCrudService.selectByUk(machineInfo.getMachineId());
-        return machineStatus != null ? new HostInfo(machineInfo, machineStatus) : new HostInfo(machineInfo);*/
-        return null;
+        MachineStat machineStat = statCrudService.selectByUk(machineInfo.getMachineId());
+        return machineStat != null ? new HostInfo(machineInfo, machineStat) : new HostInfo(machineInfo);
     }
 }

+ 4 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/vo/HostInfo.java

@@ -2,6 +2,7 @@ package cn.reghao.autodop.dmaster.machine.vo;
 
 import cn.reghao.autodop.dmaster.machine.entity.info.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.entity.info.NetworkInfo;
+import cn.reghao.autodop.dmaster.machine.entity.stat.MachineStat;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -34,7 +35,7 @@ public class HostInfo {
         this.osVersion = machineInfo.getOsInfo().getVersion();
     }
 
-    public HostInfo(MachineInfo machineInfo, MachineStatus machineStatus) {
+    public HostInfo(MachineInfo machineInfo, MachineStat machineStat) {
         this.machineId = machineInfo.getMachineId();
         List<NetworkInfo> list = machineInfo.getNetworkInfos();
         if (!list.isEmpty()) {
@@ -44,7 +45,7 @@ public class HostInfo {
         this.osArch = machineInfo.getOsInfo().getArch();
         this.osName = machineInfo.getOsInfo().getName();
         this.osVersion = machineInfo.getOsInfo().getVersion();
-        this.tcpConnNum = machineStatus.getTcpConnNum();
-        this.lastCheck = machineStatus.getLastCheck();
+        this.tcpConnNum = machineStat.getTcpConnNum();
+        this.lastCheck = machineStat.getLastCheck();
     }
 }

+ 20 - 92
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/controller/MonitorController.java

@@ -1,11 +1,6 @@
 package cn.reghao.autodop.dmaster.monitor.controller;
 
-import cn.reghao.autodop.dmaster.monitor.entity.AppMonitor;
-import cn.reghao.autodop.dmaster.monitor.entity.MachineMonitor;
 import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
-import cn.reghao.autodop.dmaster.monitor.entity.MonitorType;
-import cn.reghao.autodop.dmaster.monitor.repository.AppMonitorRepository;
-import cn.reghao.autodop.dmaster.monitor.repository.MachineMonitorRepository;
 import cn.reghao.autodop.dmaster.monitor.service.MonitorService;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
 import cn.reghao.autodop.dmaster.utils.WebBody;
@@ -24,107 +19,40 @@ import java.util.List;
  * @date 2019-08-30 18:49:15
  */
 @Slf4j
-@Api(tags = "监控接口")
+@Api(tags = "监控任务接口")
 @RestController
 @RequestMapping("/api/monitor")
 public class MonitorController {
-    private MonitorService<MachineMonitor> machineMonitorService;
-    private MonitorService<AppMonitor> appMonitorService;
-    private MachineMonitorRepository machineMonitorRepository;
-    private AppMonitorRepository appMonitorRepository;
+    private MonitorService monitorService;
 
-    public MonitorController(MonitorService<MachineMonitor> machineMonitorService,
-                             MonitorService<AppMonitor> appMonitorService,
-                             MachineMonitorRepository machineMonitorRepository,
-                             AppMonitorRepository appMonitorRepository) {
-        this.machineMonitorService = machineMonitorService;
-        this.appMonitorService = appMonitorService;
-        this.machineMonitorRepository = machineMonitorRepository;
-        this.appMonitorRepository = appMonitorRepository;
+    public MonitorController(MonitorService monitorService) {
+        this.monitorService = monitorService;
     }
 
-    @ApiOperation(value = "设置机器监控通知")
-    @PostMapping(value = "/{monitorType}/notify/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation(value = "设置监控通知")
+    @PostMapping(value = "/notify/{jobId}", produces = MediaType.APPLICATION_JSON_VALUE)
     @ResponseBody
-    public ResponseEntity<String> machineMonitorNotify(@PathVariable("monitorType") String monitorType,
-                                                       @PathVariable("id") Integer id,
-                                                       @RequestParam("groupId") List<NotifyGroup> notifyGroups) {
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                notifyGroups.forEach(notifyGroup -> machineMonitorService.setNotify(machineMonitor, notifyGroup));
-                break;
-            case app:
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                notifyGroups.forEach(notifyGroup -> appMonitorService.setNotify(appMonitor, notifyGroup));
-                break;
-            default:
-        }
-        return ResponseEntity.ok().body(WebBody.success());
-    }
-
-    @ApiOperation(value = "添加/编辑机器监控任务")
-    @PostMapping(value = "/{monitorType}/job/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<String> machineMonitorJob(@PathVariable("monitorType") String monitorType,
-                                                    @PathVariable("id") Integer id,
-                                                    @Valid MonitorJob monitorJob) {
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                machineMonitorService.addOrModifyJob(machineMonitor, monitorJob);
-                break;
-            case app:
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                appMonitorService.addOrModifyJob(appMonitor, monitorJob);
-                break;
-            default:
-        }
+    public ResponseEntity<String> setMonitorNotify(@PathVariable("jobId") String jobId,
+                                                   @RequestParam("groupId") List<NotifyGroup> notifyGroups) {
+        notifyGroups.forEach(notifyGroup -> monitorService.setNotify(jobId, notifyGroup));
         return ResponseEntity.ok().body(WebBody.success());
     }
 
-    @ApiOperation(value = "删除机器监控任务")
-    @DeleteMapping(value = "/{monitorType}/job/{id}/{jobId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<String> deleteMachineMonitorJob(@PathVariable("monitorType") String monitorType,
-                                                          @PathVariable("id") Integer id,
-                                                          @PathVariable("jobId") String jobId) {
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                machineMonitorService.deleteJob(machineMonitor, jobId);
-                break;
-            case app:
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                appMonitorService.deleteJob(appMonitor, jobId);
-                break;
-            default:
-        }
+    @ApiOperation(value = "编辑监控任务")
+    @PostMapping(value = "/job", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<String> editMonitorJob(@Valid MonitorJob monitorJob) {
+        monitorService.addOrModifyJob(monitorJob);
         return ResponseEntity.ok().body(WebBody.success());
     }
 
-    @ApiOperation(value = "开始/停止任务")
-    @PostMapping(value = "/{monitorType}/job/{id}/{jobId}/{enable}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<String> machineJobStatus(@PathVariable("monitorType") String monitorType,
-                                                   @PathVariable("id") Integer id,
-                                                   @PathVariable("jobId") String jobId,
+    @ApiOperation(value = "开始/停止监控任务")
+    @PostMapping(value = "/job/{jobId}/{enable}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<String> monitorJobStatus(@PathVariable("jobId") String jobId,
                                                    @PathVariable("enable") Boolean enable) {
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                if (enable) {
-                    machineMonitorService.startJob(machineMonitor, jobId);
-                } else {
-                    machineMonitorService.pauseJob(machineMonitor, jobId);
-                }
-                break;
-            case app:
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                if (enable) {
-                    appMonitorService.startJob(appMonitor, jobId);
-                } else {
-                    appMonitorService.pauseJob(appMonitor, jobId);
-                }
-                break;
-            default:
+        if (enable) {
+            monitorService.startJob(jobId);
+        } else {
+            monitorService.pauseJob(jobId);
         }
         return ResponseEntity.ok().body(WebBody.success());
     }

+ 23 - 191
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/controller/MonitorPageController.java

@@ -1,16 +1,10 @@
 package cn.reghao.autodop.dmaster.monitor.controller;
 
-import cn.reghao.autodop.dmaster.DmasterApplication;
 import cn.reghao.autodop.dmaster.app.vo.KeyValue;
-import cn.reghao.autodop.dmaster.monitor.entity.AppMonitor;
-import cn.reghao.autodop.dmaster.monitor.entity.MachineMonitor;
 import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
-import cn.reghao.autodop.dmaster.monitor.entity.MonitorType;
-import cn.reghao.autodop.dmaster.monitor.repository.AppMonitorRepository;
-import cn.reghao.autodop.dmaster.monitor.repository.MachineMonitorRepository;
+import cn.reghao.autodop.dmaster.monitor.repository.MonitorJobRepository;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
 import cn.reghao.autodop.dmaster.notification.repository.NotifyGroupRepository;
-import cn.reghao.autodop.dmaster.utils.clazz.PackageScanner;
 import cn.reghao.autodop.dmaster.utils.db.PageList;
 import cn.reghao.autodop.dmaster.utils.db.PageSort;
 import io.swagger.annotations.Api;
@@ -22,216 +16,54 @@ import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.IOException;
 import java.util.*;
-import java.util.stream.Collectors;
 
 /**
  * @author reghao
  * @date 2019-08-30 18:49:15
  */
 @Slf4j
-@Api(tags = "机器监控页面")
+@Api(tags = "监控任务页面")
 @Controller
 @RequestMapping("/monitor")
 public class MonitorPageController {
-    private MachineMonitorRepository machineMonitorRepository;
-    private AppMonitorRepository appMonitorRepository;
+    private MonitorJobRepository monitorJobRepository;
     private NotifyGroupRepository receiverRepository;
 
-    public MonitorPageController(MachineMonitorRepository machineMonitorRepository,
-                                 AppMonitorRepository appMonitorRepository,
-                                 NotifyGroupRepository receiverRepository) {
-        this.machineMonitorRepository = machineMonitorRepository;
-        this.appMonitorRepository = appMonitorRepository;
+    public MonitorPageController(MonitorJobRepository monitorJobRepository, NotifyGroupRepository receiverRepository) {
+        this.monitorJobRepository = monitorJobRepository;
         this.receiverRepository = receiverRepository;
     }
 
-    @ApiOperation(value = "监控页面")
-    @GetMapping("/{monitorType}")
-    public String machineMonitorPage(@PathVariable("monitorType") String monitorType, Model model) {
+    @ApiOperation(value = "监控任务页面")
+    @GetMapping("/job")
+    public String machineMonitorPage(Model model) {
         PageRequest pageRequest = PageSort.pageRequest();
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                Page<MachineMonitor> page = machineMonitorRepository.findAll(pageRequest);
-                PageList<MachineMonitor> pageList = PageList.pageList(page);
+        Page<MonitorJob> page = monitorJobRepository.findAll(pageRequest);
+        PageList<MonitorJob> pageList = PageList.pageList(page);
 
-                model.addAttribute("page", page);
-                model.addAttribute("list", pageList.getList());
-                return "/monitor/machinemonitor";
-            case app:
-                Page<AppMonitor> page1 = appMonitorRepository.findAll(pageRequest);
-                PageList<AppMonitor> pageList1 = PageList.pageList(page1);
-
-                model.addAttribute("page", page1);
-                model.addAttribute("list", pageList1.getList());
-                return "/monitor/appmonitor";
-            default:
-        }
-        return "";
+        model.addAttribute("page", page);
+        model.addAttribute("list", pageList.getList());
+        return "/monitor/index";
     }
 
-    @ApiOperation(value = "监控通知设置页面")
-    @GetMapping("/{monitorType}/notify/{id}")
-    public String monitorNotifyPage(@PathVariable("monitorType") String monitorType,
-                                    @PathVariable("id") Integer id,
-                                    Model model) {
-        String notifyApi;
-        Set<NotifyGroup> currentSet;
-        List<NotifyGroup> list;
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                notifyApi = "/api/monitor/machine/notify/" + id;
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                currentSet = new HashSet<>(machineMonitor.getNotifyGroups());
-                list = receiverRepository.findAll();
-                break;
-            case app:
-                notifyApi = "/api/monitor/app/notify/" + id;
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                currentSet = new HashSet<>(appMonitor.getNotifyGroups());
-                list = receiverRepository.findAll();
-                break;
-            default:
-                notifyApi = null;
-                currentSet = Collections.emptySet();
-                list = Collections.emptyList();
-        }
+    @ApiOperation(value = "监控任务通知设置页面")
+    @GetMapping("/notify/{id}")
+    public String monitorNotifyPage(@PathVariable("id") Integer id, Model model) {
+        MonitorJob monitorJob = monitorJobRepository.findById(id).orElse(null);
+        Set<NotifyGroup> currentSet = new HashSet<>(monitorJob.getNotifyGroups());
+        List<NotifyGroup> list = receiverRepository.findAll();
 
-        model.addAttribute("notifyApi", notifyApi);
+        model.addAttribute("jobId", monitorJob.getJobId());
         model.addAttribute("currentSet", currentSet);
         model.addAttribute("list", list);
         return "/monitor/monitornotify";
     }
 
-    @ApiOperation(value = "监控任务列表页面")
-    @GetMapping("/{monitorType}/jobs/{id}")
-    public String monitorAddPage(@PathVariable("monitorType") String monitorType,
-                                 @PathVariable("id") Integer id,
-                                 Model model) {
-        String addJobUrl;
-        String editJobUrl;
-        String jobDeleteApi;
-        String jobStatusApi;
-        List<MonitorJob> list;
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                addJobUrl = String.format("/monitor/machine/jobs/add/%s", id);
-                editJobUrl = String.format("/monitor/machine/jobs/edit/%s", id);
-                jobDeleteApi = String.format("/api/monitor/machine/job/%s", id);
-                jobStatusApi = String.format("/api/monitor/machine/job/%s", id);
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                list = new ArrayList<>(machineMonitor.getJobMap().values());
-                break;
-            case app:
-                addJobUrl = String.format("/monitor/app/jobs/add/%s", id);
-                editJobUrl = String.format("/monitor/app/jobs/edit/%s", id);
-                jobDeleteApi = String.format("/api/monitor/app/job/%s", id);
-                jobStatusApi = String.format("/api/monitor/app/job/%s", id);
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                list = new ArrayList<>(appMonitor.getJobMap().values());
-                break;
-            default:
-                addJobUrl = null;
-                editJobUrl = null;
-                jobDeleteApi = null;
-                jobStatusApi = null;
-                list = Collections.emptyList();
-        }
-
-        model.addAttribute("addJobUrl", addJobUrl);
-        model.addAttribute("editJobUrl", editJobUrl);
-        model.addAttribute("jobDeleteApi", jobDeleteApi);
-        model.addAttribute("jobStatusApi", jobStatusApi);
-        model.addAttribute("list", list);
-        return "/monitor/monitorjobs";
-    }
-
-    @ApiOperation(value = "监控任务添加页面")
-    @GetMapping("/{monitorType}/jobs/add/{id}")
-    public String monitorJobAddPage(@PathVariable("monitorType") String monitorType,
-                                    @PathVariable("id") Integer id,
-                                    Model model) throws IOException {
-        String addJobApi;
-        String jobPkg;
-        Set<String> exclude;
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                exclude = machineMonitor.getJobMap().values().stream()
-                        .map(MonitorJob::getJobClassName)
-                        .collect(Collectors.toSet());
-                addJobApi = String.format("/api/monitor/machine/job/%s", id);
-                jobPkg = "cn.reghao.autodop.dmaster.monitor.service.job.machine";
-                break;
-            case app:
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                exclude = appMonitor.getJobMap().values().stream()
-                        .map(MonitorJob::getJobClassName)
-                        .collect(Collectors.toSet());
-                addJobApi = String.format("/api/monitor/app/job/%s", id);
-                jobPkg = "cn.reghao.autodop.dmaster.monitor.service.job.app";
-                break;
-            default:
-                addJobApi = null;
-                jobPkg = null;
-                exclude = Collections.emptySet();
-        }
-
-        model.addAttribute("addJobApi", addJobApi);
-        setJobNames(model, jobPkg, exclude);
-        return "/monitor/monitorjob";
-    }
-
     @ApiOperation(value = "监控任务编辑页面")
-    @GetMapping("/{monitorType}/jobs/edit/{id}/{jobId}")
-    public String monitorJobEditPage(@PathVariable("monitorType") String monitorType,
-                                     @PathVariable("id") Integer id,
-                                     @PathVariable("jobId") String jobId,
-                                     Model model) {
-
-        String addJobApi;
-        List<KeyValue> jobNames;
-        MonitorJob monitorJob;
-        switch (MonitorType.valueOf(monitorType)) {
-            case machine:
-                addJobApi = String.format("/api/monitor/machine/job/%s", id);
-                MachineMonitor machineMonitor = machineMonitorRepository.findById(id).orElse(null);
-                monitorJob = machineMonitor.getJobMap().get(jobId);
-                jobNames = new ArrayList<>();
-                jobNames.add(new KeyValue(monitorJob.getJobClassName(), monitorJob.getJobClassName()));
-                break;
-            case app:
-                addJobApi = String.format("/api/monitor/app/job/%s", id);
-                AppMonitor appMonitor = appMonitorRepository.findById(id).orElse(null);
-                monitorJob = appMonitor.getJobMap().get(jobId);
-                jobNames = new ArrayList<>();
-                jobNames.add(new KeyValue(monitorJob.getJobClassName(), monitorJob.getJobClassName()));
-                break;
-            default:
-                addJobApi = null;
-                jobNames = Collections.emptyList();
-                monitorJob = null;
-        }
-
-        model.addAttribute("addJobApi", addJobApi);
-        model.addAttribute("jobNames", jobNames);
+    @GetMapping("/job/edit/{id}")
+    public String monitorJobEditPage(@PathVariable("id") MonitorJob monitorJob, Model model) {
         model.addAttribute("monitorJob", monitorJob);
-        return "/monitor/monitorjob";
-    }
-
-    private void setJobNames(Model model, String jobPkg, Set<String> exclude) throws IOException {
-        PackageScanner packageScanner = new PackageScanner();
-        List<Class<?>> classList = packageScanner.doScan(DmasterApplication.class, jobPkg);
-
-        List<KeyValue> jobNames = new ArrayList<>();
-        jobNames.add(new KeyValue("请选择任务", ""));
-        for (Class<?> clazz : classList) {
-            String simpleName = clazz.getSimpleName();
-            if (!exclude.contains(simpleName)) {
-                jobNames.add(new KeyValue(simpleName, simpleName));
-            }
-        }
-        model.addAttribute("jobNames", jobNames);
+        return "/monitor/edit";
     }
 }

+ 0 - 37
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/AppMonitor.java

@@ -1,37 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.entity;
-
-import cn.reghao.autodop.dmaster.app.entity.AppRunning;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.*;
-
-/**
- * @author reghao
- * @date 2021-06-23 15:35:17
- */
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = false)
-@Data
-@Entity
-public class AppMonitor extends BaseMonitor {
-    // TODO 与 AppRunning 关联
-    private String appId;
-    private String appName;
-    private String machineId;
-    private String machineIpv4;
-
-    public AppMonitor(AppRunning appRunning) {
-        this.appId = appRunning.getAppId();
-        this.appName = appRunning.getAppName();
-        this.machineId = appRunning.getMachineId();
-        this.machineIpv4 = appRunning.getMachineIpv4();
-    }
-
-    public AppMonitor update(AppRunning appRunning) {
-        this.appName = appRunning.getAppName();
-        this.machineIpv4 = appRunning.getMachineIpv4();
-        return this;
-    }
-}

+ 0 - 39
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/BaseMonitor.java

@@ -1,39 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.entity;
-
-import cn.reghao.autodop.dmaster.common.orm.BaseEntity;
-import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
-
-import javax.persistence.*;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author reghao
- * @date 2021-06-25 19:08:58
- */
-@MappedSuperclass
-@EqualsAndHashCode(callSuper = false)
-@Data
-public class BaseMonitor extends BaseEntity<Integer> {
-    private Integer totalJobs;
-    private Integer runningJobs;
-
-    @ElementCollection(targetClass = MonitorJob.class)
-    @MapKeyClass(String.class)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private Map<String, MonitorJob> jobMap;
-
-    @ManyToMany(cascade = CascadeType.REFRESH)
-    @JoinColumn(name = "notify_group_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private List<NotifyGroup> notifyGroups;
-
-    public BaseMonitor() {
-        this.totalJobs = 0;
-        this.runningJobs = 0;
-    }
-}

+ 0 - 28
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/MachineMonitor.java

@@ -1,28 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.entity;
-
-import cn.reghao.autodop.dmaster.machine.entity.info.MachineInfo;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.*;
-
-/**
- * @author reghao
- * @date 2021-06-23 15:35:17
- */
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = false)
-@Data
-@Entity
-public class MachineMonitor extends BaseMonitor {
-    // TODO 与 MachineInfo 关联
-    private String machineId;
-    private String machineIpv4;
-
-    public MachineMonitor(MachineInfo machineInfo) {
-        this.machineId = machineInfo.getMachineId();
-        // TODO 可能引发 null 异常
-        this.machineIpv4 = machineInfo.getNetworkInfos().get(0).getIpv4();
-    }
-}

+ 18 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/MonitorJob.java

@@ -1,10 +1,16 @@
 package cn.reghao.autodop.dmaster.monitor.entity;
 
+import cn.reghao.autodop.dmaster.common.orm.BaseEntity;
+import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.LazyCollection;
+import org.hibernate.annotations.LazyCollectionOption;
 
 import javax.persistence.*;
 import javax.validation.constraints.NotBlank;
+import java.util.List;
 
 /**
  * 监控任务
@@ -12,18 +18,27 @@ import javax.validation.constraints.NotBlank;
  * @author reghao
  * @date 2021-06-23 20:50:41
  */
+@NoArgsConstructor
 @EqualsAndHashCode(callSuper = false)
 @Data
-@Embeddable
-public class MonitorJob {
+@Entity
+public class MonitorJob extends BaseEntity<Integer> {
+    @NotBlank(message = "任务 ID 不能为空白字符串")
     private String jobId;
     @NotBlank(message = "任务类名不能为空白字符串")
     private String jobClassName;
     @NotBlank(message = "CRON 表达式不能为空白字符串")
     private String cronExp;
     private Boolean enable;
+    @ManyToMany(cascade = CascadeType.REFRESH)
+    @JoinColumn(name = "notify_group_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
+    @LazyCollection(LazyCollectionOption.FALSE)
+    private List<NotifyGroup> notifyGroups;
 
-    public MonitorJob() {
+    public MonitorJob(String jobId, String jobClassName) {
+        this.jobId = jobId;
+        this.jobClassName = jobClassName;
+        this.cronExp = "待设置";
         this.enable = false;
     }
 }

+ 0 - 11
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/entity/MonitorType.java

@@ -1,11 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.entity;
-
-/**
- * 监控类型
- *
- * @author reghao
- * @date 2021-06-25 18:11:55
- */
-public enum MonitorType {
-    machine,app;
-}

+ 0 - 12
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/repository/AppMonitorRepository.java

@@ -1,12 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.repository;
-
-import cn.reghao.autodop.dmaster.monitor.entity.AppMonitor;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-/**
- * @author reghao
- * @date 2021-05-24 15:20:24
- */
-public interface AppMonitorRepository extends JpaRepository<AppMonitor, Integer> {
-    AppMonitor findByAppIdAndMachineId(String appId, String machineId);
-}

+ 0 - 12
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/repository/MachineMonitorRepository.java

@@ -1,12 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.repository;
-
-import cn.reghao.autodop.dmaster.monitor.entity.MachineMonitor;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-/**
- * @author reghao
- * @date 2021-05-24 15:20:24
- */
-public interface MachineMonitorRepository extends JpaRepository<MachineMonitor, Integer> {
-    MachineMonitor findByMachineId(String machineId);
-}

+ 12 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/repository/MonitorJobRepository.java

@@ -0,0 +1,12 @@
+package cn.reghao.autodop.dmaster.monitor.repository;
+
+import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * @author reghao
+ * @date 2021-05-24 15:20:24
+ */
+public interface MonitorJobRepository extends JpaRepository<MonitorJob, Integer> {
+    MonitorJob findByJobId(String jobId);
+}

+ 0 - 49
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/AppMonitorServiceImpl.java

@@ -1,49 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.service;
-
-import cn.reghao.autodop.dmaster.monitor.entity.AppMonitor;
-import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
-import cn.reghao.autodop.dmaster.monitor.repository.AppMonitorRepository;
-import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
-import org.quartz.SchedulerException;
-import org.springframework.stereotype.Service;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * @author reghao
- * @date 2020-10-22 17:51:56
- */
-@Service
-public class AppMonitorServiceImpl implements MonitorService<AppMonitor> {
-    private MonitorScheduler monitorScheduler;
-    private AppMonitorRepository appMonitorRepository;
-
-    public AppMonitorServiceImpl(MonitorScheduler monitorScheduler,
-                                 AppMonitorRepository appMonitorRepository) {
-        this.monitorScheduler = monitorScheduler;
-        this.appMonitorRepository = appMonitorRepository;
-    }
-
-    @Override
-    public void setNotify(AppMonitor monitor, NotifyGroup notifyGroup) {
-        monitor.getNotifyGroups().add(notifyGroup);
-        appMonitorRepository.save(monitor);
-    }
-
-    @Override
-    public void addOrModifyJob(AppMonitor monitor, MonitorJob monitorJob) {
-    }
-
-    @Override
-    public void deleteJob(AppMonitor monitor, String jobId) {
-    }
-
-    @Override
-    public void startJob(AppMonitor monitor, String jobId) {
-    }
-
-    @Override
-    public void pauseJob(AppMonitor monitor, String jobId) {
-    }
-}

+ 0 - 126
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MachineMonitorServiceImpl.java

@@ -1,126 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.service;
-
-import cn.reghao.autodop.dmaster.monitor.entity.MachineMonitor;
-import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
-import cn.reghao.autodop.dmaster.monitor.repository.MachineMonitorRepository;
-import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
-import lombok.extern.slf4j.Slf4j;
-import org.quartz.SchedulerException;
-import org.springframework.stereotype.Service;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * @author reghao
- * @date 2020-10-22 17:51:56
- */
-@Slf4j
-@Service
-public class MachineMonitorServiceImpl implements MonitorService<MachineMonitor> {
-    private MonitorScheduler monitorScheduler;
-    private MachineMonitorRepository machineMonitorRepository;
-
-    public MachineMonitorServiceImpl(MonitorScheduler monitorScheduler,
-                                     MachineMonitorRepository machineMonitorRepository) {
-        this.monitorScheduler = monitorScheduler;
-        this.machineMonitorRepository = machineMonitorRepository;
-    }
-
-    @Override
-    public void setNotify(MachineMonitor monitor, NotifyGroup notifyGroup) {
-        monitor.getNotifyGroups().add(notifyGroup);
-        machineMonitorRepository.save(monitor);
-    }
-
-    @Override
-    public synchronized void addOrModifyJob(MachineMonitor monitor, MonitorJob monitorJob) {
-        Map<String, MonitorJob> jobMap = monitor.getJobMap();
-        String jobId = String.format("%s-%s", monitor.getMachineId(), monitorJob.getJobClassName());
-        MonitorJob job = jobMap.get(jobId);
-        try {
-            if (job == null) {
-                // 添加任务
-                monitorJob.setJobId(jobId);
-                monitorJob.setEnable(true);
-                jobMap.put(jobId, monitorJob);
-                int totalJobs = monitor.getTotalJobs();
-                monitor.setTotalJobs(totalJobs+1);
-                int runningJobs = monitor.getRunningJobs();
-                monitor.setRunningJobs(runningJobs+1);
-
-                monitorScheduler.addMachineMonitorJob(monitor, jobId);
-            } else {
-                // 修改任务
-                job.setCronExp(monitorJob.getCronExp());
-                monitorScheduler.modifyJob(jobId, monitorJob.getCronExp());
-            }
-            // TODO 数据库和 Scheduler 中的数据应该总是保持一致
-            machineMonitorRepository.save(monitor);
-        } catch (SchedulerException | IOException e) {
-            log.error("{}", e.getMessage());
-        }
-    }
-
-    @Override
-    public synchronized void deleteJob(MachineMonitor monitor, String jobId) {
-        Map<String, MonitorJob> map = monitor.getJobMap();
-        MonitorJob monitorJob = map.get(jobId);
-        map.remove(jobId);
-        int totalJobs = monitor.getTotalJobs();
-        monitor.setTotalJobs(totalJobs-1);
-        if (monitorJob.getEnable()) {
-            int runningJobs = monitor.getRunningJobs();
-            monitor.setRunningJobs(runningJobs-1);
-        }
-
-        try {
-            monitorScheduler.deleteJob(jobId);
-            machineMonitorRepository.save(monitor);
-        } catch (SchedulerException e) {
-            log.error("{}", e.getMessage());
-        }
-    }
-
-    @Override
-    public synchronized void startJob(MachineMonitor monitor, String jobId) {
-        MonitorJob monitorJob = monitor.getJobMap().get(jobId);
-        boolean isEnable = monitorJob.getEnable();
-        if (!isEnable) {
-            monitorJob.setEnable(true);
-            int runningJobs = monitor.getRunningJobs();
-            monitor.setRunningJobs(runningJobs+1);
-
-            try {
-                boolean isExist = monitorScheduler.isJobExist(jobId);
-                if (isExist) {
-                    monitorScheduler.resumeJob(monitorJob.getJobId());
-                } else {
-                    monitorScheduler.addMachineMonitorJob(monitor, jobId);
-                }
-                machineMonitorRepository.save(monitor);
-            } catch (SchedulerException | IOException e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    @Override
-    public synchronized void pauseJob(MachineMonitor monitor, String jobId) {
-        MonitorJob monitorJob = monitor.getJobMap().get(jobId);
-        boolean isEnable = monitorJob.getEnable();
-        if (isEnable) {
-            monitorJob.setEnable(false);
-            int runningJobs = monitor.getRunningJobs();
-            monitor.setRunningJobs(runningJobs-1);
-
-            try {
-                monitorScheduler.pauseJob(monitorJob.getJobId());
-                machineMonitorRepository.save(monitor);
-            } catch (SchedulerException e) {
-                log.error("{}", e.getMessage());
-            }
-
-        }
-    }
-}

+ 29 - 28
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorListService.java

@@ -4,10 +4,10 @@ import cn.reghao.autodop.dmaster.app.entity.AppRunning;
 import cn.reghao.autodop.dmaster.app.repository.AppRunningRepository;
 import cn.reghao.autodop.dmaster.machine.entity.info.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.repository.MachineInfoRepository;
-import cn.reghao.autodop.dmaster.monitor.entity.AppMonitor;
-import cn.reghao.autodop.dmaster.monitor.entity.MachineMonitor;
-import cn.reghao.autodop.dmaster.monitor.repository.AppMonitorRepository;
-import cn.reghao.autodop.dmaster.monitor.repository.MachineMonitorRepository;
+import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
+import cn.reghao.autodop.dmaster.monitor.repository.MonitorJobRepository;
+import cn.reghao.autodop.dmaster.monitor.service.job.app.AppHealthCheckJob;
+import cn.reghao.autodop.dmaster.monitor.service.job.machine.MachineHeartbeatCheckJob;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -21,54 +21,55 @@ import java.util.stream.Collectors;
 public class MonitorListService {
     private MachineInfoRepository infoRepository;
     private AppRunningRepository runningRepository;
-    private MachineMonitorRepository machineMonitorRepository;
-    private AppMonitorRepository appMonitorRepository;
+    private MonitorJobRepository monitorJobRepository;
 
     public MonitorListService(MachineInfoRepository infoRepository,
                               AppRunningRepository runningRepository,
-                              MachineMonitorRepository machineMonitorRepository,
-                              AppMonitorRepository appMonitorRepository) {
+                              MonitorJobRepository monitorJobRepository) {
         this.infoRepository = infoRepository;
         this.runningRepository = runningRepository;
-        this.machineMonitorRepository = machineMonitorRepository;
-        this.appMonitorRepository = appMonitorRepository;
+        this.monitorJobRepository = monitorJobRepository;
     }
 
     public void refresh() {
-        refreshMachines();
-        refreshApps();
+        refreshMachineJobs();
+        refreshAppJobs();
     }
 
-    private void refreshMachines() {
+    private void refreshMachineJobs() {
         List<MachineInfo> machineInfos = infoRepository.findAll();
-        List<MachineMonitor> machineMonitors = machineInfos.stream()
+        List<MonitorJob> monitorJobs = machineInfos.stream()
                 .map(machineInfo -> {
                     String machineId = machineInfo.getMachineId();
-                    MachineMonitor machineMonitor = machineMonitorRepository.findByMachineId(machineId);
-                    if (machineMonitor == null) {
-                        machineMonitor = new MachineMonitor(machineInfo);
+                    String jobClassName = MachineHeartbeatCheckJob.class.getSimpleName();
+                    String jobId = String.format("%s-%s", machineId, jobClassName);
+
+                    MonitorJob monitorJob = monitorJobRepository.findByJobId(jobId);
+                    if (monitorJob == null) {
+                        monitorJob = new MonitorJob(jobId, jobClassName);
                     }
-                    return machineMonitor;
+                    return monitorJob;
                 })
                 .collect(Collectors.toList());
-        machineMonitorRepository.saveAll(machineMonitors);
+        monitorJobRepository.saveAll(monitorJobs);
     }
 
-    private void refreshApps() {
+    private void refreshAppJobs() {
         List<AppRunning> appRunnings = runningRepository.findAll();
-        List<AppMonitor> appMonitors = appRunnings.stream()
+        List<MonitorJob> monitorJobs = appRunnings.stream()
                 .map(appRunning -> {
                     String appId = appRunning.getAppId();
                     String machineId = appRunning.getMachineId();
-                    AppMonitor appMonitor = appMonitorRepository.findByAppIdAndMachineId(appId, machineId);
-                    if (appMonitor == null) {
-                        appMonitor = new AppMonitor(appRunning);
-                    } else {
-                        appMonitor.update(appRunning);
+                    String jobClassName = AppHealthCheckJob.class.getSimpleName();
+                    String jobId = String.format("%s-%s-%s", appId, machineId, jobClassName);
+
+                    MonitorJob monitorJob = monitorJobRepository.findByJobId(jobId);
+                    if (monitorJob == null) {
+                        monitorJob = new MonitorJob(jobId, jobClassName);
                     }
-                    return appMonitor;
+                    return monitorJob;
                 })
                 .collect(Collectors.toList());
-        appMonitorRepository.saveAll(appMonitors);
+        monitorJobRepository.saveAll(monitorJobs);
     }
 }

+ 8 - 100
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorScheduler.java

@@ -1,18 +1,8 @@
 package cn.reghao.autodop.dmaster.monitor.service;
 
-import cn.reghao.autodop.common.http.DefaultWebRequest;
-import cn.reghao.autodop.common.http.WebRequest;
-import cn.reghao.autodop.dmaster.DmasterApplication;
-import cn.reghao.autodop.dmaster.machine.db.crud.MachineStatCrudService;
-import cn.reghao.autodop.dmaster.app.repository.AppRunningRepository;
-import cn.reghao.autodop.dmaster.monitor.entity.AppMonitor;
-import cn.reghao.autodop.dmaster.monitor.entity.MachineMonitor;
 import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
-import cn.reghao.autodop.dmaster.monitor.repository.AppMonitorRepository;
-import cn.reghao.autodop.dmaster.monitor.repository.MachineMonitorRepository;
+import cn.reghao.autodop.dmaster.monitor.repository.MonitorJobRepository;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
-import cn.reghao.autodop.dmaster.notification.service.NotifyService;
-import cn.reghao.autodop.dmaster.utils.clazz.PackageScanner;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.*;
 import org.quartz.impl.StdSchedulerFactory;
@@ -32,27 +22,11 @@ import java.util.List;
 @Service
 public class MonitorScheduler {
     private Scheduler scheduler;
-    private NotifyService notifyService;
-    private AppRunningRepository runningRepository;
-    private MachineStatCrudService statusCrudService;
-    private WebRequest webRequest;
-    private MachineMonitorRepository machineMonitorRepository;
-    private AppMonitorRepository appMonitorRepository;
-    private PackageScanner packageScanner;
+    private MonitorJobRepository monitorJobRepository;
 
-    public MonitorScheduler(NotifyService notifyService,
-                            AppRunningRepository runningRepository,
-                            MachineStatCrudService statusCrudService,
-                            MachineMonitorRepository machineMonitorRepository,
-                            AppMonitorRepository appMonitorRepository) throws SchedulerException {
+    public MonitorScheduler(MonitorJobRepository monitorJobRepository) throws SchedulerException {
         this.scheduler = StdSchedulerFactory.getDefaultScheduler();
-        this.notifyService = notifyService;
-        this.runningRepository = runningRepository;
-        this.statusCrudService = statusCrudService;
-        this.webRequest = new DefaultWebRequest();
-        this.machineMonitorRepository = machineMonitorRepository;
-        this.appMonitorRepository = appMonitorRepository;
-        this.packageScanner = new PackageScanner();
+        this.monitorJobRepository = monitorJobRepository;
     }
 
     /**
@@ -64,21 +38,10 @@ public class MonitorScheduler {
      */
     @PostConstruct
     public void startScheduler() throws SchedulerException, IOException {
-        List<MachineMonitor> machineMonitors = machineMonitorRepository.findAll();
-        for (MachineMonitor machineMonitor : machineMonitors) {
-            for (MonitorJob monitorJob : machineMonitor.getJobMap().values()) {
-                if (monitorJob.getEnable()) {
-                    addMachineMonitorJob(machineMonitor, monitorJob);
-                }
-            }
-        }
+        List<MonitorJob> jobs = monitorJobRepository.findAll();
+        for (MonitorJob job : jobs) {
+            if (job.getEnable()) {
 
-        List<AppMonitor> appMonitors = appMonitorRepository.findAll();
-        for (AppMonitor appMonitor : appMonitors) {
-            for (MonitorJob monitorJob : appMonitor.getJobMap().values()) {
-                if (monitorJob.getEnable()) {
-                    addAppMonitorJob(appMonitor, monitorJob);
-                }
             }
         }
         scheduler.start();
@@ -89,50 +52,7 @@ public class MonitorScheduler {
         JobDataMap jobDataMap = jobDetail.getJobDataMap();
     }
 
-    public void addMachineMonitorJob(MachineMonitor machineMonitor, String jobId)
-            throws SchedulerException, IOException {
-        MonitorJob monitorJob = machineMonitor.getJobMap().get(jobId);
-        List<NotifyGroup> notifyGroups = machineMonitor.getNotifyGroups();
-        String cronExp = monitorJob.getCronExp();
-        Class jobClass = findClassBySimpleName(monitorJob.getJobClassName());
-
-        JobDataMap jobDataMap = new JobDataMap();
-        jobDataMap.put("notifyService", notifyService);
-        jobDataMap.put("notifyGroups", notifyGroups);
-        jobDataMap.put("machineId", machineMonitor.getMachineId());
-        jobDataMap.put("statusCrudService", statusCrudService);
-        addJob(jobId, cronExp, jobClass, jobDataMap);
-    }
-
-    private void addMachineMonitorJob(MachineMonitor machineMonitor, MonitorJob monitorJob)
-            throws SchedulerException, IOException {
-        List<NotifyGroup> notifyGroups = machineMonitor.getNotifyGroups();
-        String cronExp = monitorJob.getCronExp();
-        Class jobClass = findClassBySimpleName(monitorJob.getJobClassName());
-
-        JobDataMap jobDataMap = new JobDataMap();
-        jobDataMap.put("notifyService", notifyService);
-        jobDataMap.put("notifyGroups", notifyGroups);
-        jobDataMap.put("machineId", machineMonitor.getMachineId());
-        jobDataMap.put("statusCrudService", statusCrudService);
-        addJob(monitorJob.getJobId(), cronExp, jobClass, jobDataMap);
-    }
-
-    private void addAppMonitorJob(AppMonitor appMonitor, MonitorJob monitorJob) throws SchedulerException, IOException {
-        String cronExp = monitorJob.getCronExp();
-        Class jobClass = findClassBySimpleName(monitorJob.getJobClassName());
-
-        JobDataMap jobDataMap = new JobDataMap();
-        jobDataMap.put("notifyService", notifyService);
-        jobDataMap.put("notifyGroups", appMonitor.getNotifyGroups());
-        jobDataMap.put("webRequest", webRequest);
-        jobDataMap.put("appId", appMonitor.getAppId());
-        jobDataMap.put("machineId", appMonitor.getMachineId());
-        jobDataMap.put("runningRepository", runningRepository);
-        addJob(monitorJob.getJobId(), cronExp, jobClass, jobDataMap);
-    }
-
-    private void addJob(String jobId, String cronExp, Class<? extends Job> clazz, JobDataMap jobDataMap)
+    public void addJob(String jobId, String cronExp, Class<? extends Job> clazz, JobDataMap jobDataMap)
             throws SchedulerException {
         JobDetail jobDetail = JobBuilder.newJob(clazz)
                 .withIdentity(jobId)
@@ -175,16 +95,4 @@ public class MonitorScheduler {
     public boolean isJobExist(String jobId) throws SchedulerException {
         return scheduler.checkExists(JobKey.jobKey(jobId));
     }
-
-    private Class findClassBySimpleName(String simpleName) throws IOException {
-        String jobPkg = "cn.reghao.autodop.dmaster.monitor.service.job";
-        List<Class<?>> classList = packageScanner.doScan(DmasterApplication.class, jobPkg);
-
-        for (Class<?> clazz : classList) {
-            if (clazz.getSimpleName().equals(simpleName)) {
-                return clazz;
-            }
-        }
-        return null;
-    }
 }

+ 7 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorService.java

@@ -4,15 +4,15 @@ import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
 
 /**
- * 监控任务接口
+ * 监控任务管理接口
  *
  * @author reghao
  * @date 2020-10-22 17:51:56
  */
-public interface MonitorService<T> {
-    void setNotify(T monitor, NotifyGroup notifyGroup);
-    void addOrModifyJob(T monitor, MonitorJob monitorJob);
-    void deleteJob(T monitor, String jobId);
-    void startJob(T monitor, String jobId);
-    void pauseJob(T monitor, String jobId);
+public interface MonitorService {
+    void setNotify(String jobId, NotifyGroup notifyGroup);
+    void addOrModifyJob(MonitorJob monitorJob);
+    void deleteJob(String jobId);
+    void startJob(String jobId);
+    void pauseJob(String jobId);
 }

+ 174 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/MonitorServiceImpl.java

@@ -0,0 +1,174 @@
+package cn.reghao.autodop.dmaster.monitor.service;
+
+import cn.reghao.autodop.common.http.DefaultWebRequest;
+import cn.reghao.autodop.common.http.WebRequest;
+import cn.reghao.autodop.dmaster.app.repository.AppRunningRepository;
+import cn.reghao.autodop.dmaster.machine.db.crud.MachineStatCrudService;
+import cn.reghao.autodop.dmaster.monitor.entity.MonitorJob;
+import cn.reghao.autodop.dmaster.monitor.repository.MonitorJobRepository;
+import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
+import cn.reghao.autodop.dmaster.notification.service.NotifyService;
+import cn.reghao.autodop.dmaster.utils.clazz.PackageScanner;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.JobDataMap;
+import org.quartz.SchedulerException;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+/**
+ * @author reghao
+ * @date 2020-10-22 17:51:56
+ */
+@Slf4j
+@Service
+public class MonitorServiceImpl implements MonitorService {
+    private MonitorScheduler monitorScheduler;
+    private MonitorJobRepository monitorJobRepository;
+    private MachineStatCrudService statCrudService;
+    private AppRunningRepository runningRepository;
+    private NotifyService notifyService;
+    private PackageScanner packageScanner;
+    private WebRequest webRequest;
+
+    public MonitorServiceImpl(MonitorScheduler monitorScheduler,
+                              MonitorJobRepository monitorJobRepository,
+                              MachineStatCrudService statCrudService,
+                              AppRunningRepository runningRepository,
+                              NotifyService notifyService) {
+        this.monitorScheduler = monitorScheduler;
+        this.monitorJobRepository = monitorJobRepository;
+        this.statCrudService = statCrudService;
+        this.runningRepository = runningRepository;
+        this.notifyService = notifyService;
+        this.packageScanner = new PackageScanner();
+        this.webRequest = new DefaultWebRequest();
+    }
+
+    public void startMachineMonitorJob(String machineId, String jobClassName) throws IOException, SchedulerException {
+        /*String jobId = String.format("%s-%s", machineId, jobClassName);
+        MonitorJob MonitorJob = MonitorJobRepository.findByMachineId(machineId);
+        MonitorJob monitorJob = MonitorJob.getJobMap().get(jobId);
+
+        List<NotifyGroup> notifyGroups = MonitorJob.getNotifyGroups();
+        String cronExp = monitorJob.getCronExp();
+        String jobPkg = "cn.reghao.autodop.dmaster.monitor.service.job";
+        Class jobClass = packageScanner.findClassBySimpleName(monitorJob.getJobClassName(), jobPkg);
+
+        JobDataMap jobDataMap = new JobDataMap();
+        jobDataMap.put("notifyService", notifyService);
+        jobDataMap.put("notifyGroups", notifyGroups);
+        jobDataMap.put("machineId", MonitorJob.getMachineId());
+        jobDataMap.put("statCrudService", statCrudService);
+        monitorScheduler.addJob(jobId, cronExp, jobClass, jobDataMap);*/
+    }
+
+    public void startAppMonitorJob(String appId, String machineId, String jobClassName)
+            throws IOException, SchedulerException {
+        String jobId = String.format("%s-%s-%s", appId, machineId, jobClassName);
+        MonitorJob monitorJob = monitorJobRepository.findByJobId(jobId);
+
+        String cronExp = monitorJob.getCronExp();
+        String jobPkg = "cn.reghao.autodop.dmaster.monitor.service.job";
+        Class jobClass = packageScanner.findClassBySimpleName(monitorJob.getJobClassName(), jobPkg);
+
+        JobDataMap jobDataMap = new JobDataMap();
+        jobDataMap.put("notifyService", notifyService);
+        jobDataMap.put("notifyGroups", monitorJob.getNotifyGroups());
+        jobDataMap.put("webRequest", webRequest);
+        jobDataMap.put("appId", appId);
+        jobDataMap.put("machineId", machineId);
+        jobDataMap.put("runningRepository", runningRepository);
+        monitorScheduler.addJob(monitorJob.getJobId(), cronExp, jobClass, jobDataMap);
+    }
+
+    @Override
+    public void setNotify(String jobId, NotifyGroup notifyGroup) {
+        MonitorJob monitorJob = monitorJobRepository.findByJobId(jobId);
+        monitorJob.getNotifyGroups().add(notifyGroup);
+        monitorJobRepository.save(monitorJob);
+    }
+
+    @Override
+    public synchronized void addOrModifyJob(MonitorJob monitorJob) {
+        String jobId = monitorJob.getJobId();
+        //jobId = String.format("%s-%s", monitor.getMachineId(), monitorJob.getJobClassName());
+
+        Integer id = monitorJob.getId();
+        try {
+            if (id == null) {
+                // 添加任务
+                //monitorScheduler.addJob(monitor, jobId);
+            } else {
+                // 修改任务
+                monitorScheduler.modifyJob(jobId, monitorJob.getCronExp());
+            }
+            // TODO 数据库和 Scheduler 中的数据应该总是保持一致
+            monitorJobRepository.save(monitorJob);
+        } catch (SchedulerException e) {
+            log.error("{}", e.getMessage());
+        }
+    }
+
+    @Override
+    public synchronized void deleteJob(String jobId) {
+        /*Map<String, MonitorJob> map = monitor.getJobMap();
+        MonitorJob monitorJob = map.get(jobId);
+        map.remove(jobId);
+        int totalJobs = monitor.getTotalJobs();
+        monitor.setTotalJobs(totalJobs-1);
+        if (monitorJob.getEnable()) {
+            int runningJobs = monitor.getRunningJobs();
+            monitor.setRunningJobs(runningJobs-1);
+        }
+
+        try {
+            monitorScheduler.deleteJob(jobId);
+            MonitorJobRepository.save(monitor);
+        } catch (SchedulerException e) {
+            log.error("{}", e.getMessage());
+        }*/
+    }
+
+    @Override
+    public synchronized void startJob(String jobId) {
+        /*MonitorJob monitorJob = monitor.getJobMap().get(jobId);
+        boolean isEnable = monitorJob.getEnable();
+        if (!isEnable) {
+            monitorJob.setEnable(true);
+            int runningJobs = monitor.getRunningJobs();
+            monitor.setRunningJobs(runningJobs+1);
+
+            try {
+                boolean isExist = monitorScheduler.isJobExist(jobId);
+                if (isExist) {
+                    monitorScheduler.resumeJob(monitorJob.getJobId());
+                } else {
+                    //monitorScheduler.addMonitorJobJob(monitor, jobId);
+                }
+                MonitorJobRepository.save(monitor);
+            } catch (SchedulerException e) {
+                e.printStackTrace();
+            }
+        }*/
+    }
+
+    @Override
+    public synchronized void pauseJob(String jobId) {
+        /*MonitorJob monitorJob = monitor.getJobMap().get(jobId);
+        boolean isEnable = monitorJob.getEnable();
+        if (isEnable) {
+            monitorJob.setEnable(false);
+            int runningJobs = monitor.getRunningJobs();
+            monitor.setRunningJobs(runningJobs-1);
+
+            try {
+                monitorScheduler.pauseJob(monitorJob.getJobId());
+                MonitorJobRepository.save(monitor);
+            } catch (SchedulerException e) {
+                log.error("{}", e.getMessage());
+            }
+
+        }*/
+    }
+}

+ 0 - 48
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/job/machine/MachineDiskUsageCheckJob.java

@@ -1,48 +0,0 @@
-package cn.reghao.autodop.dmaster.monitor.service.job.machine;
-
-import cn.reghao.autodop.dmaster.machine.db.crud.MachineStatCrudService;
-import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
-import cn.reghao.autodop.dmaster.notification.service.NotifyService;
-import lombok.extern.slf4j.Slf4j;
-import org.quartz.Job;
-import org.quartz.JobDataMap;
-import org.quartz.JobDetail;
-import org.quartz.JobExecutionContext;
-
-import java.util.List;
-
-/**
- * 机器磁盘使用情况监控任务
- *
- * @author reghao
- * @date 2021-06-22 19:04:10
- */
-@Slf4j
-public class MachineDiskUsageCheckJob implements Job {
-    @Override
-    public void execute(JobExecutionContext context) {
-        JobDetail jobDetail = context.getJobDetail();
-        JobDataMap jobDataMap = jobDetail.getJobDataMap();
-
-        NotifyService notifyService = (NotifyService) jobDataMap.get("notifyService");
-        List<NotifyGroup> notifyGroups = (List<NotifyGroup>) jobDataMap.get("notifyGroups");
-        MachineStatCrudService statusCrudService = (MachineStatCrudService) jobDataMap.get("statusCrudService");
-        String machineId = jobDataMap.getString("machineId");
-        log.info("检查 {} 的磁盘使用情况...", machineId);
-
-        /*MachineStatus machineStatus = statusCrudService.selectByUniqueKey(machineId);
-        long lastCheck = DateTimeConverter.msTimestamp(machineStatus.getLastCheck());
-        long now = System.currentTimeMillis();
-        machineStatus.setLastCheck(LocalDateTime.now());
-        statusCrudService.insertOrUpdate(machineStatus);
-
-        long result = now - lastCheck;
-        if (result > 10_000) {
-            // TODO 检测 IP 是否能 ping 通
-            // TODO 检测 MQTT 服务器是否正常连接
-            String msg = String.format("距离上次接收到 %s 的心跳消息已过去 %ss", machineStatus.getMachineIpv4(), result/1000);
-            DingMsg dingMsg = new DingMsg("监控报警",msg);
-            notifyGroups.forEach(notifyGroup -> notifyService.notify(notifyGroup, dingMsg));
-        }*/
-    }
-}

+ 13 - 9
dmaster/src/main/java/cn/reghao/autodop/dmaster/monitor/service/job/machine/MachineHeartbeatCheckJob.java

@@ -1,8 +1,12 @@
 package cn.reghao.autodop.dmaster.monitor.service.job.machine;
 
+import cn.reghao.autodop.common.utils.DateTimeConverter;
 import cn.reghao.autodop.dmaster.machine.db.crud.MachineStatCrudService;
+import cn.reghao.autodop.dmaster.machine.entity.stat.MachineStat;
+import cn.reghao.autodop.dmaster.machine.entity.stat.StatusType;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
 import cn.reghao.autodop.dmaster.notification.service.NotifyService;
+import cn.reghao.autodop.dmaster.notification.service.notifier.ding.DingMsg;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.Job;
 import org.quartz.JobDataMap;
@@ -26,23 +30,23 @@ public class MachineHeartbeatCheckJob implements Job {
 
         NotifyService notifyService = (NotifyService) jobDataMap.get("notifyService");
         List<NotifyGroup> notifyGroups = (List<NotifyGroup>) jobDataMap.get("notifyGroups");
-        MachineStatCrudService statusCrudService = (MachineStatCrudService) jobDataMap.get("statusCrudService");
+        MachineStatCrudService statCrudService = (MachineStatCrudService) jobDataMap.get("statCrudService");
         String machineId = jobDataMap.getString("machineId");
-        log.info("检查 {} 的上次心跳时间...", machineId);
 
-        /*MachineStatus machineStatus = statusCrudService.selectByUniqueKey(machineId);
-        long lastCheck = DateTimeConverter.msTimestamp(machineStatus.getLastCheck());
+        MachineStat machineStat = statCrudService.selectByUk(machineId);
+        long lastCheck = DateTimeConverter.msTimestamp(machineStat.getLastCheck());
         long now = System.currentTimeMillis();
-        machineStatus.setLastCheck(LocalDateTime.now());
-        statusCrudService.insertOrUpdate(machineStatus);
 
         long result = now - lastCheck;
         if (result > 10_000) {
+            // TODO 通知三次后,停止心跳检测
+            machineStat.setStatus(StatusType.DOWN.name());
+            statCrudService.update(machineStat);
             // TODO 检测 IP 是否能 ping 通
             // TODO 检测 MQTT 服务器是否正常连接
-            String msg = String.format("距离上次接收到 %s 的心跳消息已过去 %ss", machineStatus.getMachineIpv4(), result/1000);
+            String msg = String.format("距离上次接收到 %s 的心跳消息已过去 %ss", machineStat.getMachineId(), result/1000);
             DingMsg dingMsg = new DingMsg("监控报警",msg);
-            notifyGroups.forEach(notifyGroup -> notifyService.notify(notifyGroup, dingMsg));
-        }*/
+            //notifyGroups.forEach(notifyGroup -> notifyService.notify(notifyGroup, dingMsg));
+        }
     }
 }

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

@@ -1,15 +1,7 @@
 package cn.reghao.autodop.dmaster.mqttsub.processor;
 
-import cn.reghao.autodop.common.dagent.machine.disk.DiskInfo;
-import cn.reghao.autodop.common.dagent.machine.memory.MemoryInfo;
-import cn.reghao.autodop.common.dagent.machine.network.NetworkStat;
-import cn.reghao.autodop.common.dagent.machine.network.TcpConnStat;
-import cn.reghao.autodop.common.dagent.machine.network.TcpState;
 import cn.reghao.autodop.common.log.RuntimeLog;
 import cn.reghao.autodop.common.message.ops.DagentOps;
-import cn.reghao.autodop.common.utils.ByteConverter;
-import cn.reghao.autodop.common.utils.ByteType;
-import cn.reghao.autodop.common.utils.PercentCalculator;
 import cn.reghao.autodop.common.utils.serializer.JsonConverter;
 import cn.reghao.autodop.common.message.ops.OpsProcessor;
 import cn.reghao.autodop.dmaster.machine.db.crud.MachineInfoCrudService;
@@ -21,10 +13,6 @@ import cn.reghao.autodop.dmaster.sys.repository.AppRuntimeLogRepository;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.stream.Collectors;
-
 /**
  * 分发处理 Dagent 相关的消息
  *
@@ -34,7 +22,6 @@ import java.util.stream.Collectors;
 @Slf4j
 @Component
 public class DagentOpsProcessor implements OpsProcessor {
-    private ByteConverter converter = new ByteConverter();
     private MachineInfoCrudService machineInfoCrudService;
     private MachineStatCrudService statCrudService;
     private AppRuntimeLogRepository runtimeLogRepository;
@@ -72,103 +59,39 @@ public class DagentOpsProcessor implements OpsProcessor {
         MachineInfo machineInfo = JsonConverter.jsonToObject(payload, MachineInfo.class);
         machineInfoCrudService.insertOrUpdate(machineInfo);
 
-        MachineStat stat = statCrudService.selectByUk(machineInfo.getMachineId());
+        String machineId = machineInfo.getMachineId();
+        MachineStat stat = statCrudService.selectByUk(machineId);
         if (stat != null) {
             stat.setStatus(StatusType.UP.name());
-            stat.setLastCheck(LocalDateTime.now());
+            statCrudService.update(stat);
         } else {
             stat = new MachineStat(machineInfo.getMachineId());
+            statCrudService.insert(stat);
         }
-        statCrudService.insertOrUpdate(stat);
+
+        // TODO 开启心跳检测任务
     }
 
     private void processDagentHeartbeat(String payload) {
         MachineStat machineStat = JsonConverter.jsonToObject(payload, MachineStat.class);
-        statCrudService.insertOrUpdate(machineStat);
-        /*int tcpConnNum = tcpConnNum(machineStat.getNetworkStat());
-        MemoryUsage memoryUsage = getMemoryUsage(machineIpv4, machineStat.getMemoryInfo());
-        List<DiskUsage> diskUsages = getDiskUsage(machineIpv4, machineStat.getDiskInfos());
-        MachineStat status = statusCrudService.selectByUk(machineStat.getMachineId());
-        if (status != null) {
-            status.setMachineIpv4(machineIpv4);
-            status.setLastCheck(LocalDateTime.now());
-            status.setTcpConnNum(tcpConnNum);
-            status.setMemoryUsage(memoryUsage);
-            status.setDiskUsages(diskUsages);
-        } else {
-            status = new MachineStat(machineStat);
-            status.setTcpConnNum(tcpConnNum);
-            status.setMemoryUsage(memoryUsage);
-            status.setDiskUsages(diskUsages);
-        }
-        statusCrudService.insertOrUpdate(status);*/
-    }
-
-    private int tcpConnNum(NetworkStat networkStat) {
-        List<TcpConnStat> list = networkStat.getTcpConnStats().stream()
-                .filter(tcpConnStat -> tcpConnStat.getTcpState().equals(TcpState.TCP_ESTABLISHED.name()))
-                .collect(Collectors.toList());
-        return list.size();
-    }
-
-    private MemoryUsage getMemoryUsage(String machineIpv4, MemoryInfo memoryInfo) {
-        long total = memoryInfo.getTotal();
-        long used = memoryInfo.getUsed();
-        long avail = memoryInfo.getAvailable();
-        long totalSwap = memoryInfo.getSwapTotal();
-        long usedSwap = memoryInfo.getSwapUsed();
-        long availSwap = memoryInfo.getSwapFree();
-
-        String totalSize = converter.convertStr(ByteType.KiB, ByteType.MiB, total);
-        String usedSize = converter.convertStr(ByteType.KiB, ByteType.MiB, used);
-        String availSize = converter.convertStr(ByteType.KiB, ByteType.MiB, avail);
-        String swapTotalSize = converter.convertStr(ByteType.KiB, ByteType.MiB, totalSwap);
-        String swapUsedSize = converter.convertStr(ByteType.KiB, ByteType.MiB, usedSwap);
-        String swapAvailSize = converter.convertStr(ByteType.KiB, ByteType.MiB, availSwap);
-
-        MemoryUsage memoryUsage = new MemoryUsage();
-        memoryUsage.setTotal(totalSize);
-        memoryUsage.setUsed(usedSize);
-        memoryUsage.setAvail(availSize);
-        memoryUsage.setSwapTotal(swapTotalSize);
-        memoryUsage.setSwapUsed(swapUsedSize);
-        memoryUsage.setSwapAvail(swapAvailSize);
-
-        double value = PercentCalculator.percentValue(avail, total);
-        String percent = PercentCalculator.percent(value);
-        double minimalPercent = 0.20;
-        if (value < minimalPercent) {
-            // TODO 发出告警通知
-            log.info("{} 上可用的内存仅占内存的 {},共计 {}", machineIpv4, percent, availSize);
-        }
-
-        return memoryUsage;
-    }
-
-    private List<DiskUsage> getDiskUsage(String machineIpv4, List<DiskInfo> diskInfos) {
-        long total = 0, avail = 0;
-        for (DiskInfo diskInfo : diskInfos) {
-            total += diskInfo.getSize();
-            avail += diskInfo.getAvail();
-        }
-
-        String availSize = converter.convert(ByteType.Bytes, ByteType.MiB, avail) + ByteType.MiB.name();
-        double value = PercentCalculator.percentValue(avail, total);
-        String percent = PercentCalculator.percent(value);
-        double minimalPercent = 0.20;
-        if (value < minimalPercent) {
-            // TODO 发出告警通知
-            log.info("{} 上可用的磁盘空间仅占总磁盘空间的 {},共计 {}", machineIpv4, percent, availSize);
+        MachineStat stat = statCrudService.selectByUk(machineStat.getMachineId());
+        if (stat != null) {
+            if (stat.getStatus().equals(StatusType.DOWN.name())) {
+                stat.setStatus(StatusType.UP.name());
+            }
+            statCrudService.update(stat);
         }
-        return diskInfos.stream().map(DiskUsage::new).collect(Collectors.toList());
     }
 
     private void processDagentShutdown(String payload) {
         String machineId = JsonConverter.jsonToObject(payload, String.class);
-        MachineStat status = statCrudService.selectByUk(machineId);
-        if (status != null) {
-            status.setStatus(StatusType.DOWN.name());
+        MachineStat machineStat = statCrudService.selectByUk(machineId);
+        if (machineStat != null) {
+            machineStat.setStatus(StatusType.DOWN.name());
+            statCrudService.update(machineStat);
         }
+
+        // TODO 停止心跳检测任务
     }
 
     private void processDagentLog(String payload) {

+ 12 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/clazz/PackageScanner.java

@@ -1,5 +1,7 @@
 package cn.reghao.autodop.dmaster.utils.clazz;
 
+import cn.reghao.autodop.dmaster.DmasterApplication;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -17,6 +19,16 @@ import java.util.jar.JarInputStream;
  * @date 2020-09-24 15:41:07
  */
 public class PackageScanner {
+    public Class findClassBySimpleName(String simpleName, String pkgPath) throws IOException {
+        List<Class<?>> classList = doScan(DmasterApplication.class, pkgPath);
+        for (Class<?> clazz : classList) {
+            if (clazz.getSimpleName().equals(simpleName)) {
+                return clazz;
+            }
+        }
+        return null;
+    }
+
     public List<Class<?>> doScan(Class<?> clazz, String basePackage) throws IOException {
         List<Class<?>> classList = new ArrayList<>();
         String pkgPath = basePackage.replace(".", "/");

+ 5 - 6
dmaster/src/main/resources/templates/monitor/monitorjob.html → dmaster/src/main/resources/templates/monitor/edit.html

@@ -4,19 +4,18 @@
 
 <body>
 <div class="layui-form timo-compile">
-        <form th:action="@{${addJobApi}}">
+        <form th:action="@{'/api/monitor/job'}">
+            <input type="hidden" name="jobId" th:value="${monitorJob.jobId}"/>
             <div class="layui-form-item">
-                <label class="layui-form-label required">任务名</label>
+                <label class="layui-form-label required">任务名</label>
                 <div class="layui-input-inline">
-                    <select name="jobClassName">
-                        <option th:each="item : ${jobNames}" th:value="${item.key}" th:selected="${monitorJob?.jobClassName} eq ${item.key}">[[${item.value}]]</option>
-                    </select>
+                    <input class="layui-input" type="text" name="jobClassName" readonly="true" th:value="${monitorJob.jobClassName}">
                 </div>
             </div>
             <div class="layui-form-item">
                 <label class="layui-form-label required">CRON 表达式</label>
                 <div class="layui-input-inline">
-                    <input class="layui-input" type="text" name="cronExp" placeholder="请输入 CRON 表达式" required th:value="${monitorJob?.cronExp}">
+                    <input class="layui-input" type="text" name="cronExp" placeholder="请输入 CRON 表达式" required th:value="${monitorJob.cronExp}">
                 </div>
             </div>
             <div class="layui-form-item timo-finally">

+ 19 - 15
dmaster/src/main/resources/templates/monitor/appmonitor.html → dmaster/src/main/resources/templates/monitor/index.html

@@ -6,7 +6,7 @@
 <body class="timo-layout-page">
 <div class="layui-card">
     <div class="layui-card-header timo-card-header">
-        <span><i class="fa fa-bars"></i> 应用监控列表</span>
+        <span><i class="fa fa-bars"></i> 监控任务列表</span>
         <i class="layui-icon layui-icon-refresh refresh-btn"></i>
     </div>
     <div class="layui-card-body">
@@ -21,9 +21,9 @@
                         </div>
                     </div>
                     <div class="layui-inline timo-search-box">
-                        <label class="layui-form-label">应用名字</label>
+                        <label class="layui-form-label">任务 ID</label>
                         <div class="layui-input-block">
-                            <input type="text" name="appName" th:value="${param.appName}" placeholder="请输入应用名字"
+                            <input type="text" name="jobId" th:value="${param.jobId}" placeholder="请输入任务 ID"
                                    autocomplete="off" class="layui-input">
                         </div>
                     </div>
@@ -39,27 +39,31 @@
             <table class="layui-table timo-table">
                 <thead>
                 <tr>
-                    <th class="sortable" data-field="appName">应用名字</th>
-                    <th class="sortable" data-field="machineIpv4">机器地址</th>
-                    <th class="sortable" data-field="totalJobs">任务总数</th>
-                    <th class="sortable" data-field="runningJobs">正在运行的任务</th>
+                    <th class="sortable" data-field="jobId">任务 ID</th>
+                    <th class="sortable" data-field="jobClassName">任务类名</th>
+                    <th class="sortable" data-field="cronExp">CRON 表达式</th>
+                    <th class="sortable" data-field="enable">是否启用</th>
                     <th class="sortable" data-field="notifyGroups">通知组</th>
-                    <th class="sortable" data-field="jobs">任务列表</th>
+                    <th>操作</th>
                 </tr>
                 </thead>
                 <tbody>
                 <tr th:each="item:${list}">
-                    <td th:text="${item.appName}">应用名字</td>
-                    <td th:text="${item.machineIpv4}">机器地址</td>
-                    <td th:text="${item.totalJobs}">任务总数</td>
-                    <td th:text="${item.runningJobs}">正在运行的任务</td>
+                    <td th:text="${item.jobId}">任务 ID</td>
+                    <td th:text="${item.jobClassName}">任务类名</td>
+                    <td th:text="${item.cronExp}">CRON 表达式</td>
+                    <td th:text="${item.enable}">是否启用</td>
                     <td>
-                        <a class="open-popup" data-title="设置通知组" th:attr="data-url=@{'/monitor/app/notify/'+${item.id}}"
+                        <a class="open-popup" data-title="设置通知组" th:attr="data-url=@{'/monitor/notify/'+${item.id}}"
                            data-size="640,480" href="#">设置</a>
                     </td>
                     <td>
-                        <a class="open-popup" data-title="任务列表" th:attr="data-url=@{'/monitor/app/jobs/'+${item.id}}"
-                           data-size="1200,600" href="#">查看</a>
+                        <a class="open-popup" data-title="编辑任务" th:attr="data-url=@{'/monitor/job/edit/'+${item.id}}"
+                           data-size="640,480" href="#">编辑</a>
+                        <a class="ajax-post"
+                           th:href="@{'/api/monitor/job/'+${item.jobId}+'/1'}">启用</a>
+                        <a class="ajax-post"
+                           th:href="@{'/api/monitor/job/'+${item.jobId}+'/0'}">禁用</a>
                     </td>
                 </tr>
                 </tbody>

+ 0 - 81
dmaster/src/main/resources/templates/monitor/machinemonitor.html

@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org"
-      xmlns:mo="https://gitee.com/aun/Timo">
-<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
-
-<body class="timo-layout-page">
-<div class="layui-card">
-    <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="layui-row timo-card-screen put-row">
-            <div class="layui-row timo-card-screen put-row">
-                <div class="pull-left layui-form-pane">
-                    <div class="layui-inline">
-                        <label class="layui-form-label">环境</label>
-                        <div class="layui-input-block timo-search-status">
-                            <select id="getPageByEnv" class="timo-search-select" name="env" onchange="getPageByEnv()"
-                                    mo:dict="ENVIRONMENT" mo-selected="${env}"></select>
-                        </div>
-                    </div>
-                    <div class="layui-inline timo-search-box">
-                        <label class="layui-form-label">机器地址</label>
-                        <div class="layui-input-block">
-                            <input type="text" name="appName" th:value="${param.machineIpv4}" placeholder="请输入机器地址"
-                                   autocomplete="off" class="layui-input">
-                        </div>
-                    </div>
-                    <div class="layui-inline">
-                        <button class="layui-btn timo-search-btn">
-                            <i class="fa fa-search"></i>
-                        </button>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <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="totalJobs">任务总数</th>
-                    <th class="sortable" data-field="runningJobs">正在运行的任务</th>
-                    <th class="sortable" data-field="notifyGroups">通知组</th>
-                    <th class="sortable" data-field="jobs">任务列表</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr th:each="item:${list}">
-                    <td th:text="${item.machineIpv4}">机器地址</td>
-                    <td th:text="${item.totalJobs}">任务总数</td>
-                    <td th:text="${item.runningJobs}">正在运行的任务</td>
-                    <td>
-                        <a class="open-popup" data-title="设置通知组" th:attr="data-url=@{'/monitor/machine/notify/'+${item.id}}"
-                           data-size="640,480" href="#">设置</a>
-                    </td>
-                    <td>
-                        <a class="open-popup" data-title="任务列表" th:attr="data-url=@{'/monitor/machine/jobs/'+${item.id}}"
-                           data-size="1200,600" href="#">查看</a>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-        <div th:replace="/common/fragment :: page"></div>
-    </div>
-</div>
-
-<script th:replace="/common/template :: script"></script>
-<script type="text/javascript" th:src="@{/js/plugins/jquery-2.2.4.min.js}"></script>
-<script type="text/javascript">
-    function getPageByEnv() {
-        var selectedOption = $("#getPageByEnv option:selected")
-        var param = selectedOption.text()
-        url = '?env=' + param
-        window.location.href = window.location.pathname + url;
-    }
-</script>
-</body>
-</html>

+ 0 - 57
dmaster/src/main/resources/templates/monitor/monitorjobs.html

@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org">
-<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
-
-<body class="timo-layout-page">
-<div class="layui-card">
-    <div class="layui-card-body">
-        <div class="layui-row timo-card-screen put-row">
-            <div class="pull-right screen-btn-group">
-                <div class="btn-group-right">
-                    <button class="layui-btn open-popup" data-title="添加任务" data-size="640,480"
-                            th:attr="data-url=@{${addJobUrl}}">
-                        <i class="fa fa-plus"></i> 添加
-                    </button>
-                </div>
-            </div>
-        </div>
-        <div class="timo-table-wrap">
-            <table class="layui-table timo-table">
-                <thead>
-                <tr>
-                    <th class="sortable" data-field="jobId">任务 ID</th>
-                    <th class="sortable" data-field="jobClassName">任务名</th>
-                    <th class="sortable" data-field="cronExp">CRON 表达式</th>
-                    <th class="sortable" data-field="enable">是否启用</th>
-                    <th>操作</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr th:each="item:${list}">
-                    <td th:text="${item.jobId}">任务 ID</td>
-                    <td th:text="${item.jobClassName}">任务名</td>
-                    <td th:text="${item.cronExp}">CRON 表达式</td>
-                    <td th:text="${item.enable}">是否启用</td>
-                    <td>
-                        <a class="open-popup" data-title="编辑任务"
-                           th:attr="data-url=@{${editJobUrl}+'/'+${item.jobId}}"
-                           data-size="640,480" href="#">编辑</a>
-                        <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.jobId} + '?'"
-                           th:href="@{${jobDeleteApi}+'/' + ${item.jobId}}">删除</a>
-                        <a class="ajax-post"
-                           th:href="@{${jobStatusApi}+'/'+${item.jobId}+'/1'}">启用</a>
-                        <a class="ajax-post"
-                           th:href="@{${jobStatusApi}+'/'+${item.jobId}+'/0'}">禁用</a>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-    </div>
-</div>
-
-<script th:replace="/common/template :: script"></script>
-<script type="text/javascript">
-</script>
-</body>
-</html>

+ 1 - 1
dmaster/src/main/resources/templates/monitor/monitornotify.html

@@ -20,7 +20,7 @@
 </head>
 <body>
 <div class="layui-form timo-compile">
-    <form th:action="@{${notifyApi}}">
+    <form th:action="@{'/api/monitor/notify/'+ ${jobId}}">
         <div class="layui-form-item">
             <div class="layui-input-block">
                 <input th:each="item:${list}" type="checkbox" name="groupId" th:title="${item.groupId}"