Просмотр исходного кода

完成构建历史模块后端接口和前端页面,完成运行日志模块后端接口和前端页面

reghao 5 лет назад
Родитель
Сommit
9e3ad5c7b1
47 измененных файлов с 620 добавлено и 182 удалено
  1. 4 4
      common/src/main/java/cn/reghao/autodop/common/log/Appenders.java
  2. 10 3
      common/src/main/java/cn/reghao/autodop/common/log/LoggerConfig.java
  3. 1 1
      common/src/main/java/cn/reghao/autodop/common/log/MqttAppender.java
  4. 1 0
      common/src/main/java/cn/reghao/autodop/common/mqtt/DefaultMqttClient.java
  5. 3 6
      dagent/src/main/java/cn/reghao/autodop/dagent/app/App.java
  6. 4 10
      dagent/src/main/java/cn/reghao/autodop/dagent/app/DockerAppServiceImpl.java
  7. 9 9
      dagent/src/main/java/cn/reghao/autodop/dagent/app/ZipAppServiceImpl.java
  8. 7 3
      dagent/src/main/java/cn/reghao/autodop/dagent/utils/DagentLifecycle.java
  9. 1 1
      dagent/src/main/resources/application-test.yml
  10. 7 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/AppStatusController.java
  11. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/BuildDeployController.java
  12. 56 13
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppPageController.java
  13. 5 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/crud/config/AppCrudService.java
  14. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/query/config/build/CompilerQuery.java
  15. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/query/config/build/PackerQuery.java
  16. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/query/config/build/RepoAuthQuery.java
  17. 4 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/AppBuilding.java
  18. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/AppOrchestration.java
  19. 3 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/deploy/DeployConfig.java
  20. 4 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/log/BuildLog.java
  21. 20 24
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppBuildDeployService.java
  22. 11 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppStatusService.java
  23. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/AppIntegrate.java
  24. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/BuildNotifyMsg.java
  25. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/DeployNotifyMsg.java
  26. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/NewApp.java
  27. 32 14
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysLogPageController.java
  28. 67 27
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/MongoQuery.java
  29. 17 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/vo/AppRuntimeLogVO.java
  30. 16 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/vo/RuntimeLogVO.java
  31. 7 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/lifecycle/DmasterLifecycle.java
  32. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/log/Appenders.java
  33. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/log/MongoAppender.java
  34. 19 0
      dmaster/src/main/resources/application-dev0.yml
  35. 3 3
      dmaster/src/main/resources/application-test.yml
  36. 0 0
      dmaster/src/main/resources/templates/app/bd/build.html
  37. 37 0
      dmaster/src/main/resources/templates/app/bd/buildconfig.html
  38. 71 0
      dmaster/src/main/resources/templates/app/bd/buildlog.html
  39. 0 1
      dmaster/src/main/resources/templates/app/bd/buildresult.html
  40. 25 0
      dmaster/src/main/resources/templates/app/bd/buildtime.html
  41. 47 0
      dmaster/src/main/resources/templates/app/bd/commitinfo.html
  42. 0 0
      dmaster/src/main/resources/templates/app/bd/deploy.html
  43. 0 21
      dmaster/src/main/resources/templates/sys/log/rtdetail.html
  44. 4 3
      dmaster/src/main/resources/templates/sys/log/runtime.html
  45. 37 0
      dmaster/src/main/resources/templates/sys/log/runtimedetail.html
  46. 37 0
      dmaster/src/main/resources/templates/sys/log/runtimeinfo.html
  47. 31 0
      dmaster/src/test/java/cn/reghao/autodop/dmaster/sys/db/MongoQueryTest.java

+ 4 - 4
common/src/main/java/cn/reghao/autodop/common/log/Appenders.java

@@ -14,9 +14,9 @@ import org.slf4j.LoggerFactory;
  * @date 2021-06-11 13:31:20
  */
 public class Appenders {
-    private LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+    private static LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
 
-    public Appender<ILoggingEvent> mqttAppender(String machineId, String machineIpv4, String appId,
+    public static Appender<ILoggingEvent> mqttAppender(String machineId, String machineIpv4, String appId,
                                                 DefaultMqttClient mqttClient) {
         PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
         layoutEncoder.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n");
@@ -29,7 +29,7 @@ public class Appenders {
         return mqttAppender;
     }
 
-    public Appender<ILoggingEvent> fileAppender(LoggerContext loggerContext) {
+    public static Appender<ILoggingEvent> fileAppender(LoggerContext loggerContext) {
         PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
         layoutEncoder.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n");
         layoutEncoder.setContext(loggerContext);
@@ -43,7 +43,7 @@ public class Appenders {
         return fileAppender;
     }
 
-    public Appender<ILoggingEvent> consoleAppender(LoggerContext loggerContext) {
+    public static Appender<ILoggingEvent> consoleAppender(LoggerContext loggerContext) {
         PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
         layoutEncoder.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %c %M %L - %msg%n");
         layoutEncoder.setContext(loggerContext);

+ 10 - 3
common/src/main/java/cn/reghao/autodop/common/log/LoggerConfig.java

@@ -7,6 +7,8 @@ import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
+
 /**
  * 编程方式配置 logback,相当于 logback-spring-bak.xml 配置
  *
@@ -14,12 +16,17 @@ import org.slf4j.LoggerFactory;
  * @date 2021-02-23 23:53:35
  */
 public class LoggerConfig {
-    private LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+    private static LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+    public static void initLogger(List<Appender<ILoggingEvent>> appenders) {
+        String env = System.getProperty("spring.profiles.active");
+        if (!"dev".equals(env)) {
+            // TODO 非 dev 环境则禁止日志写入 console
+        }
 
-    public void addAppender(Appender<ILoggingEvent> appender) {
         Logger rootLogger = loggerContext.getLogger("ROOT");
         rootLogger.setAdditive(false);
         rootLogger.setLevel(Level.INFO);
-        rootLogger.addAppender(appender);
+        appenders.forEach(rootLogger::addAppender);
     }
 }

+ 1 - 1
common/src/main/java/cn/reghao/autodop/common/log/MqttAppender.java

@@ -63,7 +63,7 @@ public class MqttAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
         runtimeLog.setLevel(event.getLevel().toString());
         runtimeLog.setThreadName(event.getThreadName());
         runtimeLog.setLoggerName(event.getLoggerName());
-        runtimeLog.setMessage(event.getMessage());
+        runtimeLog.setMessage(event.getFormattedMessage());
         return runtimeLog;
     }
 }

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

@@ -50,6 +50,7 @@ public class DefaultMqttClient implements AutoCloseable {
         return client.isConnected();
     }
 
+    // TODO 处理系统启动时没有成功连接的情况
     private void connect() throws MqttException {
         if (!client.isConnected()) {
             client.setCallback(callback);

+ 3 - 6
dagent/src/main/java/cn/reghao/autodop/dagent/app/App.java

@@ -27,16 +27,12 @@ import java.util.List;
 @Slf4j
 @Component
 public class App {
-    private String machineId;
-    private String machineIpv4;
     private DockerAppServiceImpl dockerAppServiceImpl;
     private ZipAppServiceImpl zipAppServiceImpl;
 
     public App() {
         // TODO 对于托管给 Spring 的对象,这种创建对象的方式是否合理
-        this.machineId = DagentLifecycle.MACHINE_ID;
-        this.machineIpv4 = DagentLifecycle.MACHINE_IPV4;
-        this.dockerAppServiceImpl = new DockerAppServiceImpl(machineId, machineIpv4);
+        this.dockerAppServiceImpl = new DockerAppServiceImpl();
         this.zipAppServiceImpl = new ZipAppServiceImpl();
     }
 
@@ -46,7 +42,8 @@ public class App {
         String packType = appDeployArgs.getPackType();
 
         AppStatus appStatus;
-        DeployResult deployResult = new DeployResult(buildLogId, machineId, machineIpv4);
+        DeployResult deployResult = new DeployResult(buildLogId,
+                DagentLifecycle.MACHINE_ID, DagentLifecycle.MACHINE_IPV4);
         switch (PackType.valueOf(packType)) {
             case docker:
                 try {

+ 4 - 10
dagent/src/main/java/cn/reghao/autodop/dagent/app/DockerAppServiceImpl.java

@@ -15,6 +15,7 @@ import cn.reghao.autodop.common.docker.pojo.result.ContainerInfo;
 import cn.reghao.autodop.common.utils.DateTimeConverter;
 import cn.reghao.autodop.common.utils.ExceptionUtil;
 import cn.reghao.autodop.common.utils.serializer.JsonConverter;
+import cn.reghao.autodop.dagent.utils.DagentLifecycle;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -24,15 +25,8 @@ import java.util.List;
  * @date 2021-02-22 16:21:37
  */
 public class DockerAppServiceImpl implements AppService {
-    private String machineId;
-    private String machineIpv4;
     private final long sleep = 10_000;
 
-    public DockerAppServiceImpl(String machineId, String machineIpv4) {
-        this.machineId = machineId;
-        this.machineIpv4 = machineIpv4;
-    }
-
     @Override
     public AppStatus deploy(AppDeployArgs appDeployArgs) throws DockerException {
         String appId = appDeployArgs.getAppId();
@@ -61,8 +55,8 @@ public class DockerAppServiceImpl implements AppService {
 
     private AppStatus getAppStatus(String appId, ContainerInfo containerInfo) {
         AppStatus appStatus = new AppStatus();
-        appStatus.setMachineId(machineId);
-        appStatus.setMachineIpv4(machineIpv4);
+        appStatus.setMachineId(DagentLifecycle.MACHINE_ID);
+        appStatus.setMachineIpv4(DagentLifecycle.MACHINE_IPV4);
         appStatus.setAppId(appId);
         appStatus.setPackagePath(containerInfo.getConfig().getImage());
 
@@ -83,7 +77,7 @@ public class DockerAppServiceImpl implements AppService {
         try (Docker docker = new Docker()) {
             String containerId = docker.getIdByName(appId);
             if (containerId == null) {
-                throw new DockerException("没有和 " + appId + " 关联的容器");
+                throw new DockerException("没有和 " + appId + " 应用 ID关联的容器");
             }
             ContainerInfo containerInfo = docker.inspectContainer(containerId);
             return getAppStatus(appId, containerInfo);

+ 9 - 9
dagent/src/main/java/cn/reghao/autodop/dagent/app/ZipAppServiceImpl.java

@@ -4,9 +4,9 @@ import cn.reghao.autodop.common.dagent.app.api.data.AppStatus;
 import cn.reghao.autodop.common.dagent.app.api.data.deploy.AppDeployArgs;
 import cn.reghao.autodop.common.dagent.app.api.data.log.AppLogArgs;
 import cn.reghao.autodop.common.dagent.app.api.data.log.LogFile;
-import cn.reghao.autodop.common.docker.exception.DockerException;
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -22,32 +22,32 @@ public class ZipAppServiceImpl implements AppService {
     }
 
     @Override
-    public List<LogFile> logFiles(AppLogArgs appLogArgs) {
+    public AppStatus status(String appId) {
         return null;
     }
 
     @Override
-    public List<String> logContent(AppLogArgs appLogArgs) throws DockerException {
+    public AppStatus restart(String appId)  {
         return null;
     }
 
     @Override
-    public AppStatus status(String appId) {
+    public AppStatus stop(String appId)  {
         return null;
     }
 
     @Override
-    public AppStatus restart(String appId)  {
+    public AppStatus start(String appId) {
         return null;
     }
 
     @Override
-    public AppStatus stop(String appId)  {
-        return null;
+    public List<LogFile> logFiles(AppLogArgs appLogArgs) {
+        return Collections.emptyList();
     }
 
     @Override
-    public AppStatus start(String appId) {
-        return null;
+    public List<String> logContent(AppLogArgs appLogArgs) {
+        return Collections.emptyList();
     }
 }

+ 7 - 3
dagent/src/main/java/cn/reghao/autodop/dagent/utils/DagentLifecycle.java

@@ -1,5 +1,7 @@
 package cn.reghao.autodop.dagent.utils;
 
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
 import cn.reghao.autodop.common.log.Appenders;
 import cn.reghao.autodop.common.message.AsyncMsg;
 import cn.reghao.autodop.common.message.MessageType;
@@ -21,6 +23,8 @@ import org.springframework.boot.ApplicationRunner;
 import org.springframework.context.annotation.Configuration;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * TODO 无法处理 kill -9 和机器断电的情况
@@ -70,9 +74,9 @@ public class DagentLifecycle implements ApplicationRunner, DisposableBean {
     }
 
     private void initLogger() {
-        Appenders appenders = new Appenders();
-        LoggerConfig loggerConfig = new LoggerConfig();
-        loggerConfig.addAppender(appenders.mqttAppender(MACHINE_ID, MACHINE_IPV4, "dagent", mqttClient));
+        List<Appender<ILoggingEvent>> appenders = new ArrayList<>();
+        appenders.add(Appenders.mqttAppender(MACHINE_ID, MACHINE_IPV4, "dagent", mqttClient));
+        LoggerConfig.initLogger(appenders);
     }
 
     /**

+ 1 - 1
dagent/src/main/resources/application-test.yml

@@ -1,5 +1,5 @@
 mosquitto:
-  broker: tcp://192.168.0.220:1883
+  broker: tcp://mosquitto.alpha.iquizoo.com:1883
   username: test
   password: Test@123456
   clientId: dagent

+ 7 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/AppStatusController.java

@@ -53,6 +53,13 @@ public class AppStatusController {
         return ResponseEntity.ok().body(WebBody.success(appId + " 已启动"));
     }
 
+    @ApiOperation(value = "刷新某个已部署应用状态")
+    @PostMapping(value = "/refresh/{appId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<String> refreshDeployedApp(@PathVariable("appId") String appId) {
+        statusService.refreshAppStatus(appId);
+        return ResponseEntity.ok().body(WebBody.success());
+    }
+
     @ApiOperation(value = "刷新已部署应用状态")
     @PostMapping(value = "/refresh", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<String> refreshDeployedApps() {

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/BuildDeployController.java

@@ -1,6 +1,6 @@
 package cn.reghao.autodop.dmaster.app.controller;
 
-import cn.reghao.autodop.dmaster.app.service.AppBuildService;
+import cn.reghao.autodop.dmaster.app.service.AppBuildDeployService;
 import cn.reghao.autodop.dmaster.app.service.BuildDeployDispatcher;
 import cn.reghao.autodop.dmaster.utils.WebBody;
 import io.swagger.annotations.Api;
@@ -21,9 +21,9 @@ import org.springframework.web.bind.annotation.*;
 @RequestMapping("/api/app/bd")
 public class BuildDeployController {
     private BuildDeployDispatcher buildDeployDispatcher;
-    private AppBuildService buildService;
+    private AppBuildDeployService buildService;
 
-    public BuildDeployController(BuildDeployDispatcher buildDeployDispatcher, AppBuildService buildService) {
+    public BuildDeployController(BuildDeployDispatcher buildDeployDispatcher, AppBuildDeployService buildService) {
         this.buildDeployDispatcher = buildDeployDispatcher;
         this.buildService = buildService;
     }

+ 56 - 13
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppPageController.java

@@ -12,6 +12,10 @@ import cn.reghao.autodop.dmaster.app.entity.config.AppOrchestration;
 import cn.reghao.autodop.dmaster.app.entity.config.deploy.DeployConfig;
 import cn.reghao.autodop.dmaster.app.entity.log.BuildLog;
 import cn.reghao.autodop.dmaster.app.entity.AppBuilding;
+import cn.reghao.autodop.dmaster.app.entity.log.BuildTime;
+import cn.reghao.autodop.dmaster.app.repository.log.BuildLogRepository;
+import cn.reghao.autodop.dmaster.app.service.bd.tools.repo.CommitInfo;
+import cn.reghao.autodop.dmaster.app.vo.BuildConfig;
 import cn.reghao.autodop.dmaster.auth.UserContext;
 import cn.reghao.autodop.dmaster.auth.entity.RoleType;
 import cn.reghao.autodop.dmaster.utils.db.PageList;
@@ -39,15 +43,18 @@ public class AppPageController {
     private AppBuildingQuery buildingQuery;
     private AppDeployingQuery deployingQuery;
     private AppRunningQuery runningQuery;
+    private BuildLogRepository buildLogRepository;
 
     public AppPageController(AppQuery appQuery,
                              AppBuildingQuery buildingQuery,
                              AppDeployingQuery deployingQuery,
-                             AppRunningQuery runningQuery) {
+                             AppRunningQuery runningQuery,
+                             BuildLogRepository buildLogRepository) {
         this.appQuery = appQuery;
         this.buildingQuery = buildingQuery;
         this.deployingQuery = deployingQuery;
         this.runningQuery = runningQuery;
+        this.buildLogRepository = buildLogRepository;
     }
 
     @ApiOperation(value = "构建部署页面")
@@ -69,7 +76,7 @@ public class AppPageController {
             model.addAttribute("env", env);
             model.addAttribute("page", page);
             model.addAttribute("list", pageList.getList());
-            return "/app/build";
+            return "/app/bd/build";
         }
 
         Set<String> set = new HashSet<>();
@@ -102,7 +109,7 @@ public class AppPageController {
         model.addAttribute("env", env);
         model.addAttribute("page", appBuildings);
         model.addAttribute("list", pageList.getList());
-        return "/app/build";
+        return "/app/bd/build";
     }
 
     @ApiOperation(value = "部署页面")
@@ -120,7 +127,7 @@ public class AppPageController {
         }
 
         model.addAttribute("list", list);
-        return "/app/deploy";
+        return "/app/bd/deploy";
     }
 
     @ApiOperation(value = "构建日志结果页面")
@@ -128,8 +135,51 @@ public class AppPageController {
     public String buildLogResultPage(@PathVariable("buildLogId") BuildLog buildLog, Model model) {
         String msg = buildLog.getResult().getMsg();
         model.addAttribute("msg", msg);
-        // TODO 后期使用 layui dialogue
-        return "/app/log";
+        return "/app/bd/buildresult";
+    }
+
+    @ApiOperation(value = "构建日志页面")
+    @GetMapping("/log/build")
+    public String buildLogPage(Model model) {
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<BuildLog> buildLogs = buildLogRepository.findAll(pageRequest);
+        PageList<BuildLog> pageList = PageList.pageList(buildLogs);
+
+        model.addAttribute("page", buildLogs);
+        model.addAttribute("list", pageList.getList());
+        return "/app/bd/buildlog";
+    }
+
+    @ApiOperation(value = "构建配置页面")
+    @GetMapping("/log/build/{buildLogId}/buildconfig")
+    public String buildConfigPage(@PathVariable("buildLogId") String buildLogId, Model model) {
+        BuildLog buildLog = buildLogRepository.findById(buildLogId).orElse(null);
+        if (buildLog != null) {
+            BuildConfig buildConfig = buildLog.getBuildConfig();
+            model.addAttribute("buildConfig", buildConfig);
+        }
+        return "/app/bd/buildconfig";
+    }
+
+    @ApiOperation(value = "版本信息页面")
+    @GetMapping("/log/build/{buildLogId}/commitinfo")
+    public String commitInfoPage(@PathVariable("buildLogId") String buildLogId,Model model) {
+        BuildLog buildLog = buildLogRepository.findById(buildLogId).orElse(null);
+        if (buildLog != null && buildLog.getCommitInfo() != null) {
+            model.addAttribute("commitInfo", buildLog.getCommitInfo());
+        }
+        return "/app/bd/commitinfo";
+    }
+
+    @ApiOperation(value = "构建时间页面")
+    @GetMapping("/log/build/{buildLogId}/buildtime")
+    public String buildTimePage(@PathVariable("buildLogId") String buildLogId,Model model) {
+        BuildLog buildLog = buildLogRepository.findById(buildLogId).orElse(null);
+        if (buildLog != null) {
+            BuildTime buildTime = buildLog.getBuildTime();
+            model.addAttribute("buildTime", buildTime);
+        }
+        return "/app/bd/buildtime";
     }
 
     @ApiOperation(value = "运行状态页面")
@@ -165,11 +215,4 @@ public class AppPageController {
         model.addAttribute("list", pageList.getList());
         return "/app/status";
     }
-
-    @ApiOperation(value = "构建历史页面")
-    @GetMapping("/log/build")
-    public String buildLogPage(Model model) {
-        String env = EnvType.test.name();
-        return "/app/log";
-    }
 }

+ 5 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/crud/config/AppCrudService.java

@@ -7,15 +7,13 @@ import cn.reghao.autodop.dmaster.app.constant.EnvType;
 import cn.reghao.autodop.dmaster.app.constant.NotifyType;
 import cn.reghao.autodop.dmaster.app.entity.config.NotifyReceiver;
 import cn.reghao.autodop.dmaster.app.entity.config.deploy.DeployConfig;
-import cn.reghao.autodop.dmaster.app.service.AppBuildService;
+import cn.reghao.autodop.dmaster.app.service.AppBuildDeployService;
 import cn.reghao.autodop.dmaster.app.vo.NewApp;
 import cn.reghao.autodop.dmaster.app.entity.config.AppOrchestration;
 import cn.reghao.autodop.dmaster.app.repository.config.AppOrchestrationRepository;
 import cn.reghao.autodop.dmaster.machine.entity.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.repository.MachineInfoRepository;
 import org.springframework.cache.annotation.CacheConfig;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.CachePut;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -35,19 +33,19 @@ public class AppCrudService {
     private AppOrchestrationRepository appRepository;
     private MachineInfoRepository machineRepository;
     private SharedEntityChecker sharedEntityChecker;
-    private AppBuildService appBuildService;
+    private AppBuildDeployService appBuildService;
 
     public AppCrudService(AppOrchestrationRepository appRepository,
                           MachineInfoRepository machineRepository,
                           SharedEntityChecker sharedEntityChecker,
-                          AppBuildService appBuildService) {
+                          AppBuildDeployService appBuildService) {
         this.appRepository = appRepository;
         this.machineRepository = machineRepository;
         this.sharedEntityChecker = sharedEntityChecker;
         this.appBuildService = appBuildService;
     }
 
-    @CachePut(cacheNames = {"app"}, key = "#app.appId")
+    //@CachePut(cacheNames = {"app"}, key = "#app.appId")
     @Transactional(rollbackFor = Exception.class)
     public Result insertOrUpdate(AppOrchestration app) throws Exception {
         // TODO 处理所有与 app 关联的数据
@@ -144,7 +142,7 @@ public class AppCrudService {
         return insertOrUpdate(toApp);
     }
 
-    @CacheEvict(cacheNames = {"app"}, key = "#app.appId")
+    //@CacheEvict(cacheNames = {"app"}, key = "#app.appId")
     @Transactional(rollbackFor = Exception.class)
     public Result delete(AppOrchestration app) {
         // TODO 处理所有与 app 关联的数据

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/query/config/build/CompilerQuery.java

@@ -23,7 +23,7 @@ public class CompilerQuery {
         this.compilerRepository = compilerRepository;
     }
 
-    @Cacheable(cacheNames = {"compiler"}, key = "#name")
+    //@Cacheable(cacheNames = {"compiler"}, key = "#name")
     public CompilerConfig findByName(String name) {
         return compilerRepository.findByName(name);
     }

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/query/config/build/PackerQuery.java

@@ -23,7 +23,7 @@ public class PackerQuery {
         this.packerRepository = packerRepository;
     }
 
-    @Cacheable(cacheNames = {"packer"}, key = "#name")
+    //@Cacheable(cacheNames = {"packer"}, key = "#name")
     public PackerConfig findByName(String name) {
         return packerRepository.findByName(name);
     }

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/query/config/build/RepoAuthQuery.java

@@ -23,7 +23,7 @@ public class RepoAuthQuery {
         this.repoAuthRepository = repoAuthRepository;
     }
 
-    @Cacheable(cacheNames = {"repoAuth"}, key = "#name")
+    //@Cacheable(cacheNames = {"repoAuth"}, key = "#name")
     public RepoAuthConfig findByName(String name) {
         return repoAuthRepository.findByName(name);
     }

+ 4 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/AppBuilding.java

@@ -27,7 +27,7 @@ public class AppBuilding extends BaseEntity<Integer> {
     private String appName;
     private String appType;
     private String env;
-    private String branch;
+    private String repoBranch;
     private Integer httpPort;
 
     private String buildLogId;
@@ -43,7 +43,7 @@ public class AppBuilding extends BaseEntity<Integer> {
         this.appName = app.getAppName();
         this.env = app.getEnv();
         this.appType = app.getAppType();
-        this.branch = app.getRepoBranch();
+        this.repoBranch = app.getRepoBranch();
         RunningConfig runningConfig = app.getRunningConfig();
         if (runningConfig != null) {
             this.httpPort = runningConfig.getHttpPort();
@@ -56,7 +56,7 @@ public class AppBuilding extends BaseEntity<Integer> {
         this.appName = app.getAppName();
         this.env = app.getEnv();
         this.appType = app.getAppType();
-        this.branch = app.getRepoBranch();
+        this.repoBranch = app.getRepoBranch();
         RunningConfig runningConfig = app.getRunningConfig();
         if (runningConfig != null) {
             this.httpPort = runningConfig.getHttpPort();
@@ -72,7 +72,7 @@ public class AppBuilding extends BaseEntity<Integer> {
         this.setAppId(buildLog.getAppId());
         this.setEnv(buildLog.getEnv());
         this.setAppType(buildLog.getAppType());
-        this.setBranch(buildLog.getBranch());
+        this.setRepoBranch(buildLog.getRepoBranch());
 
         CommitInfo commitInfo = buildLog.getCommitInfo();
         if (commitInfo != null) {

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/AppOrchestration.java

@@ -56,10 +56,10 @@ public class AppOrchestration extends BaseEntity<Integer> implements Cloneable {
     @NotBlank(message = "代码编译主目录不能为空白字符串")
     private String compileHome;
     private String execBinName;
-    // TODO packType 是 docker 时使用
+    // TODO packType 是 docker 时使用 Dockerfile
     @Lob
     @Column(columnDefinition="text")
-    private String dockerfile;
+    private String packScript;
 
     // buildConfig 和 projId 二者只能存在一个
     @ManyToOne(cascade = CascadeType.REFRESH)

+ 3 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/deploy/DeployConfig.java

@@ -18,6 +18,9 @@ public class DeployConfig {
     private String machineId;
     private String machineIpv4;
     private String packType;
+    @Lob
+    @Column(columnDefinition="text")
+    private String unpackScript;
     // packType 是 docker 时 startScript 的内容是 cn.reghao.autodop.common.dockerc.pojo.Config 序列化为 JSON 后的字符串
     // 具体参照 https://docs.docker.com/engine/api/v1.40/#operation/ContainerCreate 的 reqeust body
     @Lob

+ 4 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/log/BuildLog.java

@@ -23,9 +23,9 @@ public class BuildLog extends BaseDocument {
     private String appId;
     private String appType;
     private String env;
-    private String branch;
+    private String repoBranch;
     private BuildConfig buildConfig;
-    private String dockerfile;
+    private String packScript;
     private String packagePath;
 
     private CommitInfo commitInfo;
@@ -38,10 +38,10 @@ public class BuildLog extends BaseDocument {
         buildLog.setAppId(app.getAppId());
         buildLog.setAppType(app.getAppType());
         buildLog.setEnv(app.getEnv());
-        buildLog.setBranch(app.getRepoBranch());
+        buildLog.setRepoBranch(app.getRepoBranch());
         buildLog.setBuildConfig(
                 new BuildConfig(app.getRepoAuthConfig(), app.getCompilerConfig(), app.getPackerConfig()));
-        buildLog.setDockerfile(app.getDockerfile());
+        buildLog.setPackScript(app.getPackScript());
 
         buildLog.setBuildTime(new BuildTime());
         buildLog.setResult(new Result());

+ 20 - 24
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppBuildService.java → dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppBuildDeployService.java

@@ -18,26 +18,26 @@ import java.util.stream.Collectors;
  * @date 2021-06-04 10:01:41
  */
 @Service
-public class AppBuildService {
+public class AppBuildDeployService {
     private AppQuery appQuery;
     private AppBuildingRepository buildingRepository;
     private AppDeployingRepository deployingRepository;
     private AppRunningRepository runningRepository;
 
-    public AppBuildService(AppQuery appQuery,
-                           AppBuildingRepository buildingRepository,
-                           AppDeployingRepository deployingRepository,
-                           AppRunningRepository runningRepository) {
+    public AppBuildDeployService(AppQuery appQuery,
+                                 AppBuildingRepository buildingRepository,
+                                 AppDeployingRepository deployingRepository,
+                                 AppRunningRepository runningRepository) {
         this.appQuery = appQuery;
         this.buildingRepository = buildingRepository;
         this.deployingRepository = deployingRepository;
         this.runningRepository = runningRepository;
     }
 
+    // TODO 启用 env 和 appType 字段,根据环境和应用类型来刷新,避免一次刷新过多应用
     public void refresh() {
         refreshAppBuilding();
-        refreshAppDeploying();
-        refreshAppRunning();
+        refreshAppDeployingAndRunning();
     }
 
     public void refreshApp(AppOrchestration app) {
@@ -52,7 +52,7 @@ public class AppBuildService {
     }
 
     /**
-     * 刷新应用构建列表
+     * 刷新应用构建信息
      *
      * @param
      * @return
@@ -68,22 +68,25 @@ public class AppBuildService {
         buildingRepository.save(appBuilding);
     }
 
-    /**
-     * 刷新应用部署列表
-     *
-     * @param
-     * @return
-     * @date 2021-06-18 下午5:25
-     */
-    public void refreshAppDeploying() {
+    public void refreshAppDeployingAndRunning() {
+        // 配置了 DeployConfig 的应用
         List<AppOrchestration> apps = appQuery.findAllByEnableIsTrue().stream()
                 .filter(app -> !app.getDeployConfigs().isEmpty())
                 // TODO 使用 peek
                 //.peek()
                 .collect(Collectors.toList());
+
         apps.forEach(this::refreshAppDeploying);
+        apps.forEach(this::refreshAppRunning);
     }
 
+    /**
+     * 刷新应用部署信息
+     *
+     * @param
+     * @return
+     * @date 2021-06-18 下午5:25
+     */
     private void refreshAppDeploying(AppOrchestration app) {
         String appId = app.getAppId();
         List<AppDeploying> list = app.getDeployConfigs().stream()
@@ -102,19 +105,12 @@ public class AppBuildService {
     }
 
     /**
-     * 刷新应用状态列表
+     * 刷新应用运行信息
      *
      * @param
      * @return
      * @date 2021-06-18 下午5:29
      */
-    public void refreshAppRunning() {
-        List<AppOrchestration> apps = appQuery.findAllByEnableIsTrue().stream()
-                .filter(app -> !app.getDeployConfigs().isEmpty())
-                .collect(Collectors.toList());
-        apps.forEach(this::refreshAppRunning);
-    }
-
     private void refreshAppRunning(AppOrchestration app) {
         String appId = app.getAppId();
         List<AppRunning> list = app.getDeployConfigs().stream()

+ 11 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppStatusService.java

@@ -80,6 +80,17 @@ public class AppStatusService {
         });
     }
 
+    public void refreshAppStatus(String appId) {
+        List<AppRunning> appRunnings = runningRepository.findByAppId(appId);
+    }
+
+    public void refreshAppStatus(AppRunning appRunning) {
+        String appId = appRunning.getAppId();
+        AppOrchestration app = appQuery.findByAppId(appId);
+        String machineId = appRunning.getMachineId();
+        getStatus(app, machineId);
+    }
+
     public void getStatus(AppOrchestration app, String machineId) {
         AppIdArgs appIdArgs = new AppIdArgs(app.getPackerConfig().getType(), app.getAppId());
         AsyncMsg asyncMsg = new AsyncMsg();

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

@@ -121,7 +121,7 @@ public class AppIntegrate {
         PackerConfig packerConfig = app.getPackerConfig();
         switch (PackType.valueOf(packerConfig.getType())) {
             case docker:
-                codePacker = new DockerPack(packerConfig, app.getDockerfile());
+                codePacker = new DockerPack(packerConfig, app.getPackScript());
                 break;
             case zip:
                 codePacker = new ZipPack(packerConfig);

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/BuildNotifyMsg.java

@@ -20,7 +20,7 @@ public class BuildNotifyMsg {
     private String buildId;
     private String appId;
     private String env;
-    private String branch;
+    private String repoBranch;
     private String commitId;
     private String commitTime;
     private String buildResult;
@@ -31,7 +31,7 @@ public class BuildNotifyMsg {
         this.buildId = buildLog.getId();
         this.appId = buildLog.getAppId();
         this.env = buildLog.getEnv();
-        this.branch = buildLog.getBranch();
+        this.repoBranch = buildLog.getRepoBranch();
         this.commitId = buildLog.getCommitInfo().getCommitId();
         this.commitTime = DateTimeConverter.format(buildLog.getCommitInfo().getMsCommitTime());
         this.buildResult = buildLog.getResult().getMsg();
@@ -47,7 +47,7 @@ public class BuildNotifyMsg {
         sb.append("# 构建 ID: ").append(buildId).append(System.lineSeparator());
         sb.append("# 应用: ").append(appId).append(System.lineSeparator());
         sb.append("# 环境: ").append(env).append(System.lineSeparator());
-        sb.append("# 分支: ").append(branch).append(System.lineSeparator());
+        sb.append("# 分支: ").append(repoBranch).append(System.lineSeparator());
         sb.append("# 版本: ").append(commitId).append(System.lineSeparator());
         sb.append("# 提交时间: ").append(commitTime).append(System.lineSeparator());
         sb.append("# 构建结果: ").append(buildResult).append(System.lineSeparator());

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/DeployNotifyMsg.java

@@ -19,7 +19,7 @@ public class DeployNotifyMsg {
     private String buildId;
     private String appId;
     private String env;
-    private String branch;
+    private String repoBranch;
     private String commitId;
     private String commitTime;
     private String machineIpv4;
@@ -31,7 +31,7 @@ public class DeployNotifyMsg {
         this.buildId = buildLog.getId();
         this.appId = buildLog.getAppId();
         this.env = buildLog.getEnv();
-        this.branch = buildLog.getBranch();
+        this.repoBranch = buildLog.getRepoBranch();
         this.commitId = buildLog.getCommitInfo().getCommitId();
         this.commitTime = DateTimeConverter.format(buildLog.getCommitInfo().getMsCommitTime());
         this.machineIpv4 = deployResult.getMachineIpv4();
@@ -53,7 +53,7 @@ public class DeployNotifyMsg {
         sb.append("# 构建 ID: ").append(buildId).append(System.lineSeparator());
         sb.append("# 应用: ").append(appId).append(System.lineSeparator());
         sb.append("# 环境: ").append(env).append(System.lineSeparator());
-        sb.append("# 分支: ").append(branch).append(System.lineSeparator());
+        sb.append("# 分支: ").append(repoBranch).append(System.lineSeparator());
         sb.append("# 版本: ").append(commitId).append(System.lineSeparator());
         sb.append("# 提交时间: ").append(commitTime).append(System.lineSeparator());
         sb.append("# 部署结果: ").append(machineIpv4).append(" -> ").append(deployResult)

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/NewApp.java

@@ -25,7 +25,7 @@ public class NewApp {
     @NotBlank(message = "代码目录不能为空白字符串")
     private String newCodeDirname;
     private String newCompileHome;
-    private String newDockerfile;
+    private String newPackScript;
 
     public AppOrchestration app(AppOrchestration from) {
         from.setAppId(newId);
@@ -35,7 +35,7 @@ public class NewApp {
         from.setRepoBranch(newRepoBranch);
         from.setCodeDirname(newCodeDirname);
         from.setCompileHome(newCompileHome);
-        from.setDockerfile(newDockerfile);
+        from.setPackScript(newPackScript);
         from.setNotifyReceivers(Collections.emptyList());
         from.setDeployConfigs(Collections.emptyList());
         from.setRunningConfig(null);

+ 32 - 14
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysLogPageController.java

@@ -3,6 +3,8 @@ package cn.reghao.autodop.dmaster.sys.controller;
 import cn.reghao.autodop.dmaster.sys.db.MongoQuery;
 import cn.reghao.autodop.dmaster.sys.entity.AppRuntimeLog;
 import cn.reghao.autodop.dmaster.sys.repository.AppRuntimeLogRepository;
+import cn.reghao.autodop.dmaster.sys.vo.AppRuntimeLogVO;
+import cn.reghao.autodop.dmaster.sys.vo.RuntimeLogVO;
 import cn.reghao.autodop.dmaster.utils.db.PageList;
 import cn.reghao.autodop.dmaster.utils.db.PageSort;
 import io.swagger.annotations.Api;
@@ -14,6 +16,10 @@ import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author reghao
  * @date 2021-04-04 21:24:18
@@ -33,32 +39,44 @@ public class SysLogPageController {
     @ApiOperation(value = "运行日志页面")
     @GetMapping("/runtime")
     public String runtimeLogPage(Model model) {
-        mongoQuery.aggregate("AppRuntimeLog");
-
-        PageRequest pageRequest = PageSort.pageRequest("createTime", Sort.Direction.DESC);
-        Page<AppRuntimeLog> page = runtimeLogRepository.findAll(pageRequest);
-        PageList<AppRuntimeLog> pageList = PageList.pageList(page);
+        Map<String, String> groupBy = new HashMap<>();
+        groupBy.put("machineId", "$machineId");
+        groupBy.put("appId", "$appId");
+        List<RuntimeLogVO> list = mongoQuery.aggregate("AppRuntimeLog", groupBy);
 
-        model.addAttribute("page", page);
-        model.addAttribute("list", pageList.getList());
+        // TODO 后面添加分页
+        // model.addAttribute("page", page);
+        model.addAttribute("list", list);
         return "/sys/log/runtime";
     }
 
-    @ApiOperation(value = "运行日志详情页面")
-    @GetMapping("/runtime/detail/{id}")
-    public String runtimeLogDeatilPage(@PathVariable("id") String id, Model model) {
-        return "/sys/log/rtdetail";
+    @GetMapping("/runtime/detail/{machineId}/{appId}")
+    public String runtimeLogDeatilPage(@PathVariable("machineId") String machineId,
+                                       @PathVariable("appId") String appId,
+                                       Model model) {
+        List<AppRuntimeLogVO> list = mongoQuery.aggregate1("AppRuntimeLog", machineId, appId);
+        model.addAttribute("list", list);
+        return "/sys/log/runtimeinfo";
+    }
+
+    @GetMapping("/runtime/detail/{machineId}/{appId}/{yearMonthDay}")
+    public String apRruntimeLogDeatilPage(@PathVariable("machineId") String machineId,
+                                       @PathVariable("appId") String appId,
+                                       @PathVariable("yearMonthDay") String yearMonthDay,
+                                       Model model) {
+        List<AppRuntimeLog> list = mongoQuery.query(machineId, appId, yearMonthDay);
+        model.addAttribute("list", list);
+        return "/sys/log/runtimedetail";
     }
 
     @ApiOperation(value = "访问日志页面")
     @GetMapping("/access")
     public String accessLogPage(Model model) {
-        PageRequest pageRequest = PageSort.pageRequest("createTime", Sort.Direction.DESC);
+        /*PageRequest pageRequest = PageSort.pageRequest("createTime", Sort.Direction.DESC);
         Page<AppRuntimeLog> page = runtimeLogRepository.findAll(pageRequest);
         PageList<AppRuntimeLog> pageList = PageList.pageList(page);
-
         model.addAttribute("page", page);
-        model.addAttribute("list", pageList.getList());
+        model.addAttribute("list", pageList.getList());*/
         return "/sys/log/access";
     }
 }

+ 67 - 27
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/MongoQuery.java

@@ -1,16 +1,22 @@
 package cn.reghao.autodop.dmaster.sys.db;
 
+import cn.reghao.autodop.dmaster.sys.entity.AppRuntimeLog;
+import cn.reghao.autodop.dmaster.sys.vo.AppRuntimeLogVO;
+import cn.reghao.autodop.dmaster.sys.vo.RuntimeLogVO;
 import com.mongodb.BasicDBObject;
 import com.mongodb.client.AggregateIterable;
 import org.bson.Document;
-import org.bson.types.ObjectId;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.stereotype.Component;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
 
 /**
  * @author reghao
@@ -24,36 +30,70 @@ public class MongoQuery {
         this.mongoTemplate = mongoTemplate;
     }
 
-    public void aggregate(String col) {
-        String groupById = "$answerId";
-        Document groupObject = new Document("_id", groupById);
-        groupObject.put("total", new BasicDBObject("$sum", 1));
-        groupObject.put("data", new BasicDBObject("$push", "$$ROOT"));
-        Document queryGroup = new Document("$group", groupObject);
+    public List<RuntimeLogVO> aggregate(String col, Map<String, String> groupByIds) {
+        Document groupBy = new Document();
+        groupBy.putAll(groupByIds);
 
-        Document sortObject = new Document("$sort", new BasicDBObject("total", -1));
-        Document limitObject = new Document("$limit", 10000);
+        Document groupByObject = new Document("_id", groupBy);
+        groupByObject.put("machineIpv4", new BasicDBObject("$first", "$machineIpv4"));
+        groupByObject.put("total", new BasicDBObject("$sum", 1));
 
+        Document queryObject = new Document("$group", groupByObject);
         List<Document> pipeline = new ArrayList<>();
-        pipeline.add(queryGroup);
-        pipeline.add(sortObject);
-        pipeline.add(limitObject);
+        pipeline.add(queryObject);
 
+        List<RuntimeLogVO> list = new ArrayList<>();
         AggregateIterable<Document> result = mongoTemplate.getCollection(col).aggregate(pipeline).allowDiskUse(true);
         for (Document document : result) {
-            List<Document> list = document.getList("data", Document.class);
-            int size = list.size();
-            // 删除重复的数据
-            if (size > 1) {
-                for (int i = 1; i < size; i++) {
-                    Document doc = list.get(i);
-                    ObjectId objectId = doc.get("_id", ObjectId.class);
-
-                    Query query = new Query();
-                    query.addCriteria(Criteria.where("_id").is(objectId));
-                    //mongoTemplate.remove(query, col);
-                }
-            }
+            Document doc = document.get("_id", Document.class);
+            String machineId = doc.get("machineId", String.class);
+            String appId = doc.get("appId", String.class);
+            String machineIpv4 = document.get("machineIpv4", String.class);
+            Integer total = document.get("total", Integer.class);
+            list.add(new RuntimeLogVO(machineId, machineIpv4, appId));
         }
+        return list;
+    }
+
+    public List<AppRuntimeLogVO> aggregate1(String col, String machineId, String appId) {
+        Map<String, String> matchMap = new HashMap<>();
+        matchMap.put("machineId", machineId);
+        matchMap.put("appId", appId);
+        Document matchObject = new Document("$match", matchMap);
+
+        Map<String, String> groupMap = new HashMap<>();
+        groupMap.put("format", "%Y-%m-%d");
+        groupMap.put("date", "$createTime");
+        Document groupBy = new Document("yearMonthDay",
+                new BasicDBObject("$dateToString", new BasicDBObject(groupMap)));
+        Document groupByObject = new Document("_id", groupBy);
+        groupByObject.put("total", new BasicDBObject("$sum", 1));
+        Document groupObject = new Document("$group", groupByObject);
+
+        List<Document> pipeline = new ArrayList<>();
+        pipeline.add(matchObject);
+        pipeline.add(groupObject);
+
+        List<AppRuntimeLogVO> list = new ArrayList<>();
+        AggregateIterable<Document> result = mongoTemplate.getCollection(col).aggregate(pipeline).allowDiskUse(true);
+        for (Document document : result) {
+            Document doc = document.get("_id", Document.class);
+            String yearMonthDay = doc.get("yearMonthDay", String.class);
+            Integer total = document.get("total", Integer.class);
+            list.add(new AppRuntimeLogVO(machineId, appId, yearMonthDay, total));
+        }
+        return list;
+    }
+
+    public List<AppRuntimeLog> query(String machineId, String appId, String yearMonthDay) {
+        LocalDate localDate = LocalDate.parse(yearMonthDay, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        LocalDate localDate1 = localDate.plusDays(1);
+
+        Query query = new Query();
+        query.addCriteria(Criteria.where("machineId").is(machineId));
+        query.addCriteria(Criteria.where("appId").is(appId));
+        query.addCriteria(Criteria.where("createTime").gte(localDate.atStartOfDay())
+                .andOperator(Criteria.where("createTime").lt(localDate1.atStartOfDay())));
+        return mongoTemplate.find(query, AppRuntimeLog.class);
     }
 }

+ 17 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/vo/AppRuntimeLogVO.java

@@ -0,0 +1,17 @@
+package cn.reghao.autodop.dmaster.sys.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-06-22 11:00:07
+ */
+@AllArgsConstructor
+@Data
+public class AppRuntimeLogVO {
+    private String machineId;
+    private String appId;
+    private String yearMonthDay;
+    private int total;
+}

+ 16 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/vo/RuntimeLogVO.java

@@ -0,0 +1,16 @@
+package cn.reghao.autodop.dmaster.sys.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-06-22 11:00:07
+ */
+@AllArgsConstructor
+@Data
+public class RuntimeLogVO {
+    private String machineId;
+    private String machineIpv4;
+    private String appId;
+}

+ 7 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/lifecycle/DmasterLifecycle.java

@@ -1,8 +1,9 @@
 package cn.reghao.autodop.dmaster.utils.lifecycle;
 
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
 import cn.reghao.autodop.common.log.LoggerConfig;
 import cn.reghao.autodop.common.mqtt.DefaultMqttClient;
-import cn.reghao.autodop.common.result.Result;
 import cn.reghao.autodop.common.utils.MachineIdentity;
 import cn.reghao.autodop.dmaster.app.db.crud.config.build.BuildDirCrudService;
 import cn.reghao.autodop.dmaster.app.entity.config.build.BuildDir;
@@ -19,6 +20,8 @@ import org.springframework.boot.ApplicationRunner;
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author reghao
@@ -67,9 +70,9 @@ public class DmasterLifecycle implements ApplicationRunner, DisposableBean {
     }
 
     private void initLogger() {
-        Appenders appenders = new Appenders();
-        LoggerConfig loggerConfig = new LoggerConfig();
-        loggerConfig.addAppender(appenders.mongoAppender("dmaster", logRepository));
+        List<Appender<ILoggingEvent>> appenders = new ArrayList<>();
+        appenders.add(Appenders.mongoAppender("dmaster", logRepository));
+        LoggerConfig.initLogger(appenders);
     }
 
     private void initBuildDir() {

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/log/Appenders.java

@@ -12,9 +12,9 @@ import org.slf4j.LoggerFactory;
  * @date 2021-06-11 13:31:20
  */
 public class Appenders {
-    private LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+    private static LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
     
-    public Appender<ILoggingEvent> mongoAppender(String appId, AppRuntimeLogRepository logRepository) {
+    public static Appender<ILoggingEvent> mongoAppender(String appId, AppRuntimeLogRepository logRepository) {
         PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
         layoutEncoder.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n");
         layoutEncoder.setContext(loggerContext);

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/log/MongoAppender.java

@@ -45,7 +45,7 @@ public class MongoAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
         runtimeLog.setLevel(event.getLevel().toString());
         runtimeLog.setThreadName(event.getThreadName());
         runtimeLog.setLoggerName(event.getLoggerName());
-        runtimeLog.setMessage(event.getMessage());
+        runtimeLog.setMessage(event.getFormattedMessage());
         return runtimeLog;
     }
 }

+ 19 - 0
dmaster/src/main/resources/application-dev0.yml

@@ -0,0 +1,19 @@
+spring:
+  datasource:
+    url: jdbc:mysql://mysql.alpha.iquizoo.com:3306/devops_tdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
+    username: azy_test
+    password: Azy@123456
+  data:
+    mongodb:
+      uri: mongodb://mongodb.alpha.iquizoo.com/devops_tdb
+mosquitto:
+  broker: tcp://mosquitto.alpha.iquizoo.com:1883
+  username: test
+  password: Test@123456
+  clientId: dmaster
+oss:
+  host: http://static.reghao.icu
+  key: minioadmin
+  secret: minioadmin
+  bucket: autodop
+  folder: test/1/2/3

+ 3 - 3
dmaster/src/main/resources/application-test.yml

@@ -1,13 +1,13 @@
 spring:
   datasource:
-    url: jdbc:mysql://192.168.0.77:3306/devops_tdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
+    url: jdbc:mysql://mysql.alpha.iquizoo.com:3306/devops_tdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
     username: azy_test
     password: Azy@123456
   data:
     mongodb:
-      uri: mongodb://192.168.0.220/devops_tdb
+      uri: mongodb://mongodb.alpha.iquizoo.com/devops_tdb
 mosquitto:
-  broker: tcp://192.168.0.220:1883
+  broker: tcp://mosquitto.alpha.iquizoo.com:1883
   username: test
   password: Test@123456
   clientId: dmaster

+ 0 - 0
dmaster/src/main/resources/templates/app/build.html → dmaster/src/main/resources/templates/app/bd/build.html


+ 37 - 0
dmaster/src/main/resources/templates/app/bd/buildconfig.html

@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+<body>
+<div class="timo-detail-page">
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>仓库类型</th>
+            <td th:text="${buildConfig.repoAuth.type}"></td>
+            <th>仓库认证名字</th>
+            <td th:text="${buildConfig.repoAuth.name}"></td>
+            <th>认证类型</th>
+            <td th:text="${buildConfig.repoAuth.authType}"></td>
+        </tr>
+        <tr>
+            <th>编译器类型</th>
+            <td th:text="${buildConfig.compiler.type}"></td>
+            <th>编译器名字</th>
+            <td th:text="${buildConfig.compiler.name}"></td>
+            <th>编译命令</th>
+            <td th:text="${buildConfig.compiler.compileCmd}"></td>
+        </tr>
+        <tr>
+            <th>打包类型</th>
+            <td th:text="${buildConfig.packer.type}"></td>
+            <th>打包名字</th>
+            <td th:text="${buildConfig.packer.name}"></td>
+            <th>打包路径</th>
+            <td th:text="${buildConfig.packer.targetPath}"></td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 71 - 0
dmaster/src/main/resources/templates/app/bd/buildlog.html

@@ -0,0 +1,71 @@
+<!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-header timo-card-header">
+        <span><i class="fa fa-bars"></i> 构建日志</span>
+        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
+    </div>
+    <div class="layui-card-body">
+        <div class="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="sortable" data-field="appId">应用 ID</th>
+                    <th class="sortable" data-field="appType">应用类型</th>
+                    <th class="sortable" data-field="env">环境</th>
+                    <th class="sortable" data-field="repoBranch">分支</th>
+                    <th class="sortable" data-field="buildConfig">构建配置</th>
+                    <th class="sortable" data-field="packScript">打包脚本</th>
+                    <th class="sortable" data-field="packagePath">包路径</th>
+                    <th class="sortable" data-field="commitInfo">版本信息</th>
+                    <th class="sortable" data-field="buildTime">构建时间</th>
+                    <th class="sortable" data-field="result">构建结果</th>
+                    <th class="sortable" data-field="buildBy">构建用户</th>
+                    <th>操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td th:text="${item.appId}">应用 ID</td>
+                    <td th:text="${item.appType}">应用类型</td>
+                    <td th:text="${item.env}">环境</td>
+                    <td th:text="${item.repoBranch}">分支</td>
+                    <td>
+                        <a class="open-popup" data-title="构建配置" data-size="1000,600" href="#"
+                           th:attr="data-url=@{'/app/log/build/'+${item.id} + '/buildconfig'}">查看</a>
+                    </td>
+                    <td th:text="${item.packScript}">打包脚本</td>
+                    <td th:text="${item.packagePath}">包路径</td>
+                    <td>
+                        <a class="open-popup" data-title="版本信息" data-size="1000,600" href="#"
+                           th:attr="data-url=@{'/app/log/build/'+${item.id} + '/commitinfo'}">查看</a>
+                    </td>
+                    <td>
+                        <a class="open-popup" data-title="构建时间" data-size="1000,600" href="#"
+                           th:attr="data-url=@{'/app/log/build/'+${item.id} + '/buildtime'}">查看</a>
+                    </td>
+                    <td>
+                        <a class="open-popup" data-title="构建结果" data-size="1000,600" href="#"
+                           th:attr="data-url=@{'/app/log/build/'+${item.id} + '/result'}">查看</a>
+                    </td>
+                    <td th:text="${item.buildBy}">构建用户</td>
+                    <td>
+                        <a class="open-popup" data-title="应用部署" th:attr="data-url=@{'/app/deploy/' + ${item.appId}}"
+                           data-size="1000,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">
+</script>
+</body>
+</html>

+ 0 - 1
dmaster/src/main/resources/templates/app/log.html → dmaster/src/main/resources/templates/app/bd/buildresult.html

@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <html xmlns:th="http://www.thymeleaf.org">
 <head th:replace="/common/template :: header(~{::title},~{::link},~{::style})">
-    <link rel="stylesheet" th:href="@{/lib/zTree_v3/css/zTreeStyle/zTreeStyle.css}" type="text/css">
 </head>
 <body class="timo-layout-page">
 <div class="layui-card">

+ 25 - 0
dmaster/src/main/resources/templates/app/bd/buildtime.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+<body>
+<div class="timo-detail-page">
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>代码更新耗时</th>
+            <td th:text="${buildTime.updateTotalTime}"></td>
+            <th>代码编译耗时</th>
+            <td th:text="${buildTime.compileTotalTime}"></td>
+            <th>代码打包耗时</th>
+            <td th:text="${buildTime.packTotalTime}"></td>
+        </tr>
+        <tr>
+            <th>构建时间</th>
+            <td th:text="${buildTime.buildTime}"></td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 47 - 0
dmaster/src/main/resources/templates/app/bd/commitinfo.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+<body>
+<div class="timo-detail-page">
+    <table class="layui-table timo-detail-table">
+        <tbody>
+        <tr>
+            <th>远程仓库</th>
+            <td th:text="${commitInfo?.remote}"></td>
+            <th>仓库分支</th>
+            <td th:text="${commitInfo?.branch}"></td>
+            <th>版本 ID</th>
+            <td th:text="${commitInfo?.commitId}"></td>
+        </tr>
+        <tr>
+            <th>提交用户</th>
+            <td th:text="${commitInfo?.commitAuthor}"></td>
+            <th>提交信息</th>
+            <td th:text="${commitInfo?.commitMsg}"></td>
+            <th>提交时间</th>
+            <td th:text="${commitInfo?.msCommitTime}"></td>
+        </tr>
+        </tbody>
+    </table>
+    <div class="timo-detail-title">文件变动列表</div>
+    <table class="layui-table timo-detail-table">
+        <thead>
+        <tr>
+            <th class="sortable" data-field="changeType">变更类型</th>
+            <th class="sortable" data-field="oldFilePath">变更前路径</th>
+            <th class="sortable" data-field="newFilePath">变更后路径</th>
+        </tr>
+        </thead>
+
+        <tbody>
+        <tr th:each="item:${commitInfo?.changedFiles}">
+            <td th:text="${item.changeType}">变更类型</td>
+            <td th:text="${item.oldFilePath}">变更前路径</td>
+            <td th:text="${item.newFilePath}">变更后路径</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 0 - 0
dmaster/src/main/resources/templates/app/deploy.html → dmaster/src/main/resources/templates/app/bd/deploy.html


+ 0 - 21
dmaster/src/main/resources/templates/sys/log/rtdetail.html

@@ -1,21 +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-header timo-card-header">
-        <span><i class="fa fa-bars"></i> 运行日志详情</span>
-        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
-    </div>
-    <div class="layui-card-body">
-        <div class="timo-table-wrap">
-        </div>
-    </div>
-</div>
-
-<script th:replace="/common/template :: script"></script>
-<script type="text/javascript">
-</script>
-</body>
-</html>

+ 4 - 3
dmaster/src/main/resources/templates/sys/log/runtime.html

@@ -24,14 +24,15 @@
                     <td th:text="${item.appId}">应用</td>
                     <td>
                         <a class="open-popup" data-title="日志"
-                           th:attr="data-url=@{'/sys/log/runtime/detail/'+${item.id}}" data-size="640,480"
-                           href="#">查看</a>
+                           th:attr="data-url=@{'/sys/log/runtime/detail/'+${item.machineId}+'/'+${item.appId}}"
+                           data-size="1200,600" href="#">查看</a>
                     </td>
                 </tr>
                 </tbody>
             </table>
         </div>
-        <div th:replace="/common/fragment :: page"></div>
+        <!--TODO 暂不使用分页
+        <div th:replace="/common/fragment :: page"></div>-->
     </div>
 </div>
 

+ 37 - 0
dmaster/src/main/resources/templates/sys/log/runtimedetail.html

@@ -0,0 +1,37 @@
+<!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="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="sortable" data-field="logTime">时间</th>
+                    <th class="sortable" data-field="level">级别</th>
+                    <th class="sortable" data-field="threadName">线程</th>
+                    <th class="sortable" data-field="loggerName">记录器</th>
+                    <th class="sortable" data-field="message">内容</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td th:text="${item.logTime}">时间</td>
+                    <td th:text="${item.level}">级别</td>
+                    <td th:text="${item.threadName}">线程</td>
+                    <td th:text="${item.loggerName}">记录器</td>
+                    <td th:text="${item.message}">内容</td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 37 - 0
dmaster/src/main/resources/templates/sys/log/runtimeinfo.html

@@ -0,0 +1,37 @@
+<!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="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="sortable" data-field="yearMonthDay">日期</th>
+                    <th class="sortable" data-field="total">数量</th>
+                    <th>查看</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td th:text="${item.yearMonthDay}">日期</td>
+                    <td th:text="${item.total}">总数</td>
+                    <td>
+                        <a class="open-popup" data-title="日志"
+                           th:attr="data-url=@{'/sys/log/runtime/detail/'+${item.machineId}+'/'+${item.appId}+'/'+${item.yearMonthDay}}" data-size="1000,500"
+                           href="#">查看</a>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 31 - 0
dmaster/src/test/java/cn/reghao/autodop/dmaster/sys/db/MongoQueryTest.java

@@ -0,0 +1,31 @@
+package cn.reghao.autodop.dmaster.sys.db;
+
+import cn.reghao.autodop.dmaster.DmasterApplication;
+import cn.reghao.autodop.dmaster.sys.entity.AppRuntimeLog;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@Slf4j
+@ActiveProfiles("dev")
+@SpringBootTest(classes = DmasterApplication.class)
+@RunWith(SpringRunner.class)
+class MongoQueryTest {
+    @Autowired
+    private MongoQuery mongoQuery;
+
+    @Test
+    void aggregate() {
+    }
+}