diff --git a/docs/docs/en/guide/monitor.md b/docs/docs/en/guide/monitor.md index eb8600d8b7..95a6c9c75b 100644 --- a/docs/docs/en/guide/monitor.md +++ b/docs/docs/en/guide/monitor.md @@ -16,6 +16,12 @@ ![worker](../../../img/new_ui/dev/monitor/worker.png) +### Alert Server + +- Mainly related to alert server information. + +![alert-server](../../../img/new_ui/dev/monitor/alert-server.png) + ### Database - Mainly the health status of the DB. @@ -26,18 +32,17 @@ ### Statistics -![statistics](../../../img/new_ui/dev/monitor/statistics.png) +![Command Statistics List](../../../img/new_ui/dev/monitor/command-list.png) + +Shows the command list in the system. Data is from the `t_ds_command` table. + +![Failure Command Statistics List](../../../img/new_ui/dev/monitor/failure-command-list.png) -| **Parameter** | **Description** | -|----------------------------------------|----------------------------------------------------| -| Number of commands wait to be executed | Statistics of the `t_ds_command` table data. | -| The number of failed commands | Statistics of the `t_ds_error_command` table data. | -| Number of tasks wait to run | Count the data of `task_queue` in the ZooKeeper. | -| Number of tasks wait to be killed | Count the data of `task_kill` in the ZooKeeper. | +Shows the failure command list in the system. Data is from the `t_ds_error_command` table. ### Audit Log The audit log provides information about who accesses the system and the operations made to the system and record related time, which strengthen the security of the system and maintenance. -![audit-log](../../../img/new_ui/dev/monitor/audit-log.jpg) +![audit-log](../../../img/new_ui/dev/monitor/audit-log.png) diff --git a/docs/docs/zh/guide/monitor.md b/docs/docs/zh/guide/monitor.md index b45d7a59b3..8033fbb966 100644 --- a/docs/docs/zh/guide/monitor.md +++ b/docs/docs/zh/guide/monitor.md @@ -16,6 +16,12 @@ ![worker](../../../img/new_ui/dev/monitor/worker.png) +### Alert Server + +- 主要是 alert server 的相关信息。 + +![alert-server](../../../img/new_ui/dev/monitor/alert-server.png) + ### Database - 主要是 DB 的健康状况 @@ -26,15 +32,16 @@ ### Statistics -![statistics](../../../img/new_ui/dev/monitor/statistics.png) +![Command Statistics List](../../../img/new_ui/dev/monitor/command-list.png) + +展示系统中的命令列表,数据来自`t_ds_command`表。 + +![Failure Command Statistics List](../../../img/new_ui/dev/monitor/failure-command-list.png) -- 待执行命令数:统计 t_ds_command 表的数据 -- 执行失败的命令数:统计 t_ds_error_command 表的数据 -- 待运行任务数:统计 Zookeeper 中 task_queue 的数据 -- 待杀死任务数:统计 Zookeeper 中 task_kill 的数据 +展示系统中的失败命令列表,数据来自`t_ds_error_command`表。 ### 审计日志 -审计日志的记录提供了有关谁访问了系统,以及他或她在给定时间段内执行了哪些操作的信息,他对于维护安全都很有用。 +审计日志的记录提供了有关谁访问了系统,以及他或她在给定时间段内执行了哪些操作的信息,对于维护安全都很有用。 -![audit-log](../../../img/new_ui/dev/monitor/audit-log.jpg) +![audit-log](../../../img/new_ui/dev/monitor/audit-log.png) diff --git a/docs/img/new_ui/dev/monitor/alert-server.png b/docs/img/new_ui/dev/monitor/alert-server.png new file mode 100644 index 0000000000..8ffc7725dc Binary files /dev/null and b/docs/img/new_ui/dev/monitor/alert-server.png differ diff --git a/docs/img/new_ui/dev/monitor/audit-log.jpg b/docs/img/new_ui/dev/monitor/audit-log.jpg deleted file mode 100644 index bc396ad303..0000000000 Binary files a/docs/img/new_ui/dev/monitor/audit-log.jpg and /dev/null differ diff --git a/docs/img/new_ui/dev/monitor/audit-log.png b/docs/img/new_ui/dev/monitor/audit-log.png new file mode 100644 index 0000000000..72acd1f839 Binary files /dev/null and b/docs/img/new_ui/dev/monitor/audit-log.png differ diff --git a/docs/img/new_ui/dev/monitor/command-list.png b/docs/img/new_ui/dev/monitor/command-list.png new file mode 100644 index 0000000000..d8fca25d10 Binary files /dev/null and b/docs/img/new_ui/dev/monitor/command-list.png differ diff --git a/docs/img/new_ui/dev/monitor/failure-command-list.png b/docs/img/new_ui/dev/monitor/failure-command-list.png new file mode 100644 index 0000000000..75c7cda1da Binary files /dev/null and b/docs/img/new_ui/dev/monitor/failure-command-list.png differ diff --git a/docs/img/new_ui/dev/monitor/master.png b/docs/img/new_ui/dev/monitor/master.png index 6505595d6a..bbbb808ca7 100644 Binary files a/docs/img/new_ui/dev/monitor/master.png and b/docs/img/new_ui/dev/monitor/master.png differ diff --git a/docs/img/new_ui/dev/monitor/statistics.png b/docs/img/new_ui/dev/monitor/statistics.png deleted file mode 100644 index a7f4a4a438..0000000000 Binary files a/docs/img/new_ui/dev/monitor/statistics.png and /dev/null differ diff --git a/docs/img/new_ui/dev/monitor/worker.png b/docs/img/new_ui/dev/monitor/worker.png index 4a68279385..166820c930 100644 Binary files a/docs/img/new_ui/dev/monitor/worker.png and b/docs/img/new_ui/dev/monitor/worker.png differ diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataAnalysisController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataAnalysisController.java index c69c1d969c..9e57ce34dd 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataAnalysisController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataAnalysisController.java @@ -20,17 +20,21 @@ package org.apache.dolphinscheduler.api.controller; import static org.apache.dolphinscheduler.api.enums.Status.COMMAND_STATE_COUNT_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.COUNT_PROCESS_DEFINITION_USER_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.COUNT_PROCESS_INSTANCE_STATE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.LIST_PAGING_ALERT_GROUP_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.QUEUE_COUNT_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.TASK_INSTANCE_STATE_COUNT_ERROR; import org.apache.dolphinscheduler.api.dto.CommandStateCount; import org.apache.dolphinscheduler.api.exceptions.ApiException; import org.apache.dolphinscheduler.api.service.DataAnalysisService; +import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.vo.TaskInstanceCountVO; import org.apache.dolphinscheduler.api.vo.WorkflowDefinitionCountVO; import org.apache.dolphinscheduler.api.vo.WorkflowInstanceCountVO; import org.apache.dolphinscheduler.common.constants.Constants; +import org.apache.dolphinscheduler.dao.entity.Command; +import org.apache.dolphinscheduler.dao.entity.ErrorCommand; import org.apache.dolphinscheduler.dao.entity.User; import java.util.List; @@ -148,4 +152,54 @@ public class DataAnalysisController extends BaseController { Map stringIntegerMap = dataAnalysisService.countQueueState(loginUser); return Result.success(stringIntegerMap); } + + /** + * command queue + * + * @param loginUser login user + * @return queue state count + */ + @Operation(summary = "listPendingCommands", description = "LIST_PENDING_COMMANDS") + @Parameters({ + @Parameter(name = "searchVal", description = "SEARCH_VAL", schema = @Schema(implementation = String.class)), + @Parameter(name = "pageNo", description = "PAGE_NO", required = true, schema = @Schema(implementation = int.class, example = "1")), + @Parameter(name = "pageSize", description = "PAGE_SIZE", required = true, schema = @Schema(implementation = int.class, example = "20")) + }) + @GetMapping("/listCommand") + @ResponseStatus(HttpStatus.OK) + @ApiException(LIST_PAGING_ALERT_GROUP_ERROR) + public Result> listPaging(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "projectCode", required = false) Long projectCode, + @RequestParam("pageNo") Integer pageNo, + @RequestParam("pageSize") Integer pageSize) { + checkPageParams(pageNo, pageSize); + PageInfo commandPageInfo = + dataAnalysisService.listPendingCommands(loginUser, projectCode, pageNo, pageSize); + return Result.success(commandPageInfo); + } + + /** + * error command + * + * @param loginUser login user + * @return queue state count + */ + @Operation(summary = "listErrorCommand", description = "LIST_ERROR_COMMAND_LIST_PAGING_NOTES") + @Parameters({ + @Parameter(name = "searchVal", description = "SEARCH_VAL", schema = @Schema(implementation = String.class)), + @Parameter(name = "pageNo", description = "PAGE_NO", required = true, schema = @Schema(implementation = int.class, example = "1")), + @Parameter(name = "pageSize", description = "PAGE_SIZE", required = true, schema = @Schema(implementation = int.class, example = "20")) + }) + @GetMapping("/listErrorCommand") + @ResponseStatus(HttpStatus.OK) + @ApiException(LIST_PAGING_ALERT_GROUP_ERROR) + public Result> listErrorCommand(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "projectCode", required = false) Long projectCode, + @RequestParam("pageNo") Integer pageNo, + @RequestParam("pageSize") Integer pageSize) { + checkPageParams(pageNo, pageSize); + PageInfo errorCommandPageInfo = + dataAnalysisService.listErrorCommand(loginUser, projectCode, pageNo, pageSize); + return Result.success(errorCommandPageInfo); + } } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/MonitorController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/MonitorController.java index 7c0a8ef0e1..4bf952d006 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/MonitorController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/MonitorController.java @@ -18,7 +18,6 @@ package org.apache.dolphinscheduler.api.controller; import static org.apache.dolphinscheduler.api.enums.Status.LIST_MASTERS_ERROR; -import static org.apache.dolphinscheduler.api.enums.Status.LIST_WORKERS_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.QUERY_DATABASE_STATE_ERROR; import org.apache.dolphinscheduler.api.exceptions.ApiException; @@ -26,15 +25,16 @@ import org.apache.dolphinscheduler.api.service.MonitorService; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.constants.Constants; import org.apache.dolphinscheduler.common.model.Server; -import org.apache.dolphinscheduler.common.model.WorkerServerModel; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.plugin.api.monitor.DatabaseMetrics; +import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; @@ -56,35 +56,19 @@ public class MonitorController extends BaseController { private MonitorService monitorService; /** - * master list + * server list * - * @param loginUser login user - * @return master list + * @return server list */ - @Operation(summary = "listMaster", description = "MASTER_LIST_NOTES") - @GetMapping(value = "/masters") + @Operation(summary = "listServer", description = "SERVER_LIST_NOTES") + @GetMapping(value = "/{nodeType}") @ResponseStatus(HttpStatus.OK) @ApiException(LIST_MASTERS_ERROR) - public Result> listMaster(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser) { - List servers = monitorService.queryMaster(loginUser); + public Result> listServer(@PathVariable("nodeType") RegistryNodeType nodeType) { + List servers = monitorService.listServer(nodeType); return Result.success(servers); } - /** - * worker list - * - * @param loginUser login user - * @return worker information list - */ - @Operation(summary = "listWorker", description = "WORKER_LIST_NOTES") - @GetMapping(value = "/workers") - @ResponseStatus(HttpStatus.OK) - @ApiException(LIST_WORKERS_ERROR) - public Result> listWorker(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser) { - List workerServerModels = monitorService.queryWorker(loginUser); - return Result.success(workerServerModels); - } - /** * query database state * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataAnalysisService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataAnalysisService.java index 351a3d5c91..f312707c2c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataAnalysisService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataAnalysisService.java @@ -21,9 +21,12 @@ import org.apache.dolphinscheduler.api.dto.CommandStateCount; import org.apache.dolphinscheduler.api.dto.DefineUserDto; import org.apache.dolphinscheduler.api.dto.TaskCountDto; import org.apache.dolphinscheduler.api.dto.project.StatisticsStateRequest; +import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.vo.TaskInstanceCountVO; import org.apache.dolphinscheduler.api.vo.WorkflowDefinitionCountVO; import org.apache.dolphinscheduler.api.vo.WorkflowInstanceCountVO; +import org.apache.dolphinscheduler.dao.entity.Command; +import org.apache.dolphinscheduler.dao.entity.ErrorCommand; import org.apache.dolphinscheduler.dao.entity.User; import java.util.List; @@ -117,4 +120,7 @@ public interface DataAnalysisService { */ TaskCountDto countOneTaskStates(User loginUser, Long taskCode); + PageInfo listPendingCommands(User loginUser, Long projectCode, Integer pageNo, Integer pageSize); + + PageInfo listErrorCommand(User loginUser, Long projectCode, Integer pageNo, Integer pageSize); } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/MonitorService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/MonitorService.java index c4a8d94a1f..f054fafdce 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/MonitorService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/MonitorService.java @@ -18,9 +18,9 @@ package org.apache.dolphinscheduler.api.service; import org.apache.dolphinscheduler.common.model.Server; -import org.apache.dolphinscheduler.common.model.WorkerServerModel; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.plugin.api.monitor.DatabaseMetrics; +import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType; import java.util.List; @@ -38,20 +38,10 @@ public interface MonitorService { List queryDatabaseState(User loginUser); /** - * query master list + * query server list * - * @param loginUser login user - * @return master information list + * @param nodeType RegistryNodeType + * @return server information list */ - List queryMaster(User loginUser); - - /** - * query worker list - * - * @param loginUser login user - * @return worker information list - */ - List queryWorker(User loginUser); - - List getServerListFromRegistry(boolean isMaster); + List listServer(RegistryNodeType nodeType); } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java index 36c9c2b8c1..9520b5090c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java @@ -27,14 +27,18 @@ import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.exceptions.ServiceException; import org.apache.dolphinscheduler.api.service.DataAnalysisService; import org.apache.dolphinscheduler.api.service.ProjectService; +import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.vo.TaskInstanceCountVO; import org.apache.dolphinscheduler.api.vo.WorkflowDefinitionCountVO; import org.apache.dolphinscheduler.api.vo.WorkflowInstanceCountVO; import org.apache.dolphinscheduler.common.constants.Constants; import org.apache.dolphinscheduler.common.enums.AuthorizationType; import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.UserType; import org.apache.dolphinscheduler.common.utils.DateUtils; +import org.apache.dolphinscheduler.dao.entity.Command; import org.apache.dolphinscheduler.dao.entity.CommandCount; +import org.apache.dolphinscheduler.dao.entity.ErrorCommand; import org.apache.dolphinscheduler.dao.entity.ExecuteStatusCount; import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; import org.apache.dolphinscheduler.dao.entity.Project; @@ -71,6 +75,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.Lists; /** @@ -380,6 +386,66 @@ public class DataAnalysisServiceImpl extends BaseServiceImpl implements DataAnal return new TaskCountDto(executeStatusCounts); } + @Override + public PageInfo listPendingCommands(User loginUser, Long projectCode, Integer pageNo, Integer pageSize) { + Page page = new Page<>(pageNo, pageSize); + if (loginUser.getUserType().equals(UserType.ADMIN_USER)) { + IPage commandIPage = commandMapper.queryCommandPage(page); + return PageInfo.of(commandIPage); + } + + List workflowDefinitionCodes = getAuthDefinitionCodes(loginUser, projectCode); + + if (workflowDefinitionCodes.isEmpty()) { + return PageInfo.of(pageNo, pageSize); + } + + IPage commandIPage = + commandMapper.queryCommandPageByIds(page, new ArrayList<>(workflowDefinitionCodes)); + return PageInfo.of(commandIPage); + } + + @Override + public PageInfo listErrorCommand(User loginUser, Long projectCode, Integer pageNo, Integer pageSize) { + Page page = new Page<>(pageNo, pageSize); + if (loginUser.getUserType().equals(UserType.ADMIN_USER)) { + IPage commandIPage = errorCommandMapper.queryErrorCommandPage(page); + return PageInfo.of(commandIPage); + } + + List workflowDefinitionCodes = getAuthDefinitionCodes(loginUser, projectCode); + + if (workflowDefinitionCodes.isEmpty()) { + return PageInfo.of(pageNo, pageSize); + } + + IPage commandIPage = + errorCommandMapper.queryErrorCommandPageByIds(page, new ArrayList<>(workflowDefinitionCodes)); + return PageInfo.of(commandIPage); + } + + private List getAuthDefinitionCodes(User loginUser, Long projectCode) { + Set projectIds = resourcePermissionCheckService + .userOwnedResourceIdsAcquisition(AuthorizationType.PROJECTS, loginUser.getId(), log); + if (CollectionUtils.isEmpty(projectIds)) { + return Collections.emptyList(); + } + List projectCodes = projectMapper.selectBatchIds(projectIds) + .stream() + .map(Project::getCode) + .collect(Collectors.toList()); + + if (projectCode != null) { + if (!projectCodes.contains(projectCode)) { + return Collections.emptyList(); + } + + projectCodes = Collections.singletonList(projectCode); + } + + return processDefinitionMapper.queryDefinitionCodeListByProjectCodes(projectCodes); + } + /** * statistics the process definition quantities of a certain person *

diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ExecutorServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ExecutorServiceImpl.java index 5b576ce95a..dafef79615 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ExecutorServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ExecutorServiceImpl.java @@ -90,6 +90,7 @@ import org.apache.dolphinscheduler.extract.master.transportor.StreamingTaskTrigg import org.apache.dolphinscheduler.extract.master.transportor.StreamingTaskTriggerResponse; import org.apache.dolphinscheduler.extract.master.transportor.WorkflowInstanceStateChangeEvent; import org.apache.dolphinscheduler.plugin.task.api.TaskConstants; +import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType; import org.apache.dolphinscheduler.service.command.CommandService; import org.apache.dolphinscheduler.service.cron.CronUtils; import org.apache.dolphinscheduler.service.exceptions.CronParseException; @@ -289,7 +290,7 @@ public class ExecutorServiceImpl extends BaseServiceImpl implements ExecutorServ private void checkMasterExists() { // check master server exists - List masterServers = monitorService.getServerListFromRegistry(true); + List masterServers = monitorService.listServer(RegistryNodeType.MASTER); // no master if (masterServers.isEmpty()) { @@ -1142,7 +1143,7 @@ public class ExecutorServiceImpl extends BaseServiceImpl implements ExecutorServ checkValidTenant(tenantCode); checkMasterExists(); // todo dispatch improvement - List masterServerList = monitorService.getServerListFromRegistry(true); + List masterServerList = monitorService.listServer(RegistryNodeType.MASTER); Server server = masterServerList.get(0); StreamingTaskTriggerRequest taskExecuteStartMessage = new StreamingTaskTriggerRequest(); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/MonitorServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/MonitorServiceImpl.java index 907ab2329c..24bfcc5b25 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/MonitorServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/MonitorServiceImpl.java @@ -19,7 +19,6 @@ package org.apache.dolphinscheduler.api.service.impl; import org.apache.dolphinscheduler.api.service.MonitorService; import org.apache.dolphinscheduler.common.model.Server; -import org.apache.dolphinscheduler.common.model.WorkerServerModel; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.plugin.api.monitor.DatabaseMetrics; import org.apache.dolphinscheduler.dao.plugin.api.monitor.DatabaseMonitor; @@ -27,7 +26,6 @@ import org.apache.dolphinscheduler.registry.api.RegistryClient; import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType; import java.util.List; -import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -35,7 +33,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; /** * monitor service impl @@ -61,48 +58,8 @@ public class MonitorServiceImpl extends BaseServiceImpl implements MonitorServic return Lists.newArrayList(databaseMonitor.getDatabaseMetrics()); } - /** - * query master list - * - * @param loginUser login user - * @return master information list - */ @Override - public List queryMaster(User loginUser) { - return registryClient.getServerList(RegistryNodeType.MASTER); + public List listServer(RegistryNodeType nodeType) { + return registryClient.getServerList(nodeType); } - - /** - * query worker list - * - * @param loginUser login user - * @return worker information list - */ - @Override - public List queryWorker(User loginUser) { - - return registryClient.getServerList(RegistryNodeType.WORKER) - .stream() - .map((Server server) -> { - WorkerServerModel model = new WorkerServerModel(); - model.setId(server.getId()); - model.setHost(server.getHost()); - model.setPort(server.getPort()); - model.setZkDirectories(Sets.newHashSet(server.getZkDirectory())); - model.setResInfo(server.getResInfo()); - model.setCreateTime(server.getCreateTime()); - model.setLastHeartbeatTime(server.getLastHeartbeatTime()); - return model; - }) - .collect(Collectors.toList()); - - } - - @Override - public List getServerListFromRegistry(boolean isMaster) { - return isMaster - ? registryClient.getServerList(RegistryNodeType.MASTER) - : registryClient.getServerList(RegistryNodeType.WORKER); - } - } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/MonitorControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/MonitorControllerTest.java index 737faa1636..93dc48b80c 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/MonitorControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/MonitorControllerTest.java @@ -41,8 +41,7 @@ public class MonitorControllerTest extends AbstractControllerTest { @Test public void testListMaster() throws Exception { - - MvcResult mvcResult = mockMvc.perform(get("/monitor/masters") + MvcResult mvcResult = mockMvc.perform(get("/monitor/MASTER") .header(SESSION_ID, sessionId) /* .param("type", ResourceType.FILE.name()) */) .andExpect(status().isOk()) @@ -59,7 +58,7 @@ public class MonitorControllerTest extends AbstractControllerTest { @Test public void testListWorker() throws Exception { - MvcResult mvcResult = mockMvc.perform(get("/monitor/workers") + MvcResult mvcResult = mockMvc.perform(get("/monitor/WORKER") .header(SESSION_ID, sessionId) /* .param("type", ResourceType.FILE.name()) */) .andExpect(status().isOk()) @@ -74,8 +73,9 @@ public class MonitorControllerTest extends AbstractControllerTest { } @Test - public void testQueryDatabaseState() throws Exception { - MvcResult mvcResult = mockMvc.perform(get("/monitor/databases") + public void testListAlert() throws Exception { + + MvcResult mvcResult = mockMvc.perform(get("/monitor/ALERT_SERVER") .header(SESSION_ID, sessionId) /* .param("type", ResourceType.FILE.name()) */) .andExpect(status().isOk()) @@ -89,4 +89,19 @@ public class MonitorControllerTest extends AbstractControllerTest { logger.info(mvcResult.getResponse().getContentAsString()); } + @Test + public void testQueryDatabaseState() throws Exception { + MvcResult mvcResult = mockMvc.perform(get("/monitor/databases") + .header(SESSION_ID, sessionId)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + result.getCode().equals(Status.SUCCESS.getCode()); + + Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } + } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecuteFunctionServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecuteFunctionServiceTest.java index 23085cb3f5..8f1869c1fb 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecuteFunctionServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecuteFunctionServiceTest.java @@ -67,6 +67,7 @@ import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionMapper; import org.apache.dolphinscheduler.dao.mapper.TaskGroupQueueMapper; import org.apache.dolphinscheduler.dao.mapper.TenantMapper; import org.apache.dolphinscheduler.dao.repository.ProcessInstanceDao; +import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType; import org.apache.dolphinscheduler.service.command.CommandService; import org.apache.dolphinscheduler.service.process.ProcessService; import org.apache.dolphinscheduler.service.process.TriggerRelationService; @@ -242,7 +243,7 @@ public class ExecuteFunctionServiceTest { Mockito.when(processService.getTenantForProcess(tenantCode, userId)).thenReturn(tenantCode); doReturn(1).when(commandService).createCommand(argThat(c -> c.getId() == null)); doReturn(0).when(commandService).createCommand(argThat(c -> c.getId() != null)); - Mockito.when(monitorService.getServerListFromRegistry(true)).thenReturn(getMasterServersList()); + Mockito.when(monitorService.listServer(RegistryNodeType.MASTER)).thenReturn(getMasterServersList()); Mockito.when(processService.findProcessInstanceDetailById(processInstanceId)) .thenReturn(Optional.ofNullable(processInstance)); Mockito.when(processService.findProcessDefinition(1L, 1)).thenReturn(this.processDefinition); @@ -498,7 +499,7 @@ public class ExecuteFunctionServiceTest { @Test public void testNoMasterServers() { - Mockito.when(monitorService.getServerListFromRegistry(true)).thenReturn(new ArrayList<>()); + Mockito.when(monitorService.listServer(RegistryNodeType.MASTER)).thenReturn(new ArrayList<>()); Assertions.assertThrows(ServiceException.class, () -> executorService.execProcessInstance( loginUser, diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java index 6bfbffd093..e1318e936d 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java @@ -98,13 +98,13 @@ public class MonitorServiceTest { public void testQueryMaster() { mockPermissionCheck(ApiFuncIdentificationConstant.MONITOR_MASTER_VIEW, true); Mockito.when(registryClient.getServerList(RegistryNodeType.MASTER)).thenReturn(getServerList()); - assertDoesNotThrow(() -> monitorService.queryMaster(user)); + assertDoesNotThrow(() -> monitorService.listServer(RegistryNodeType.MASTER)); } @Test public void testQueryWorker() { Mockito.when(registryClient.getServerList(RegistryNodeType.WORKER)).thenReturn(getServerList()); - AssertionsHelper.assertDoesNotThrow(() -> monitorService.queryWorker(user)); + AssertionsHelper.assertDoesNotThrow(() -> monitorService.listServer(RegistryNodeType.WORKER)); } @Test diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/CommandMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/CommandMapper.java index 8c8314e7cc..ff0f6243ce 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/CommandMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/CommandMapper.java @@ -26,6 +26,8 @@ import java.util.Date; import java.util.List; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; /** * command mapper interface @@ -50,7 +52,7 @@ public interface CommandMapper extends BaseMapper { * * @return */ - List queryCommandPage(@Param("limit") int limit, @Param("offset") int offset); + IPage queryCommandPage(Page page); List queryCommandByIdSlot(@Param("currentSlotIndex") int currentSlotIndex, @Param("totalSlot") int totalSlot, @@ -58,4 +60,7 @@ public interface CommandMapper extends BaseMapper { @Param("fetchNumber") int fetchNum); void deleteByWorkflowInstanceIds(@Param("workflowInstanceIds") List workflowInstanceIds); + + IPage queryCommandPageByIds(Page page, + @Param("workflowDefinitionCodes") List workflowDefinitionCodes); } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ErrorCommandMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ErrorCommandMapper.java index 8054a91786..9dee5bbc32 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ErrorCommandMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ErrorCommandMapper.java @@ -26,6 +26,8 @@ import java.util.Date; import java.util.List; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; /** * error command mapper interface @@ -43,4 +45,9 @@ public interface ErrorCommandMapper extends BaseMapper { @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("projectCodes") List projectCodes); + + IPage queryErrorCommandPage(Page page); + + IPage queryErrorCommandPageByIds(Page page, + @Param("workflowDefinitionCodes") List workflowDefinitionCodes); } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java index 67140720fe..67522caf50 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java @@ -188,4 +188,5 @@ public interface ProcessDefinitionMapper extends BaseMapper { * @return project ids list */ List listProjectIds(); + List queryDefinitionCodeListByProjectCodes(@Param("projectCodes") List projectCodes); } diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/CommandMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/CommandMapper.xml index 16f7c05f25..7f587ef899 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/CommandMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/CommandMapper.xml @@ -34,10 +34,22 @@ group by cmd.command_type + + + + + + diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml index 77775b7668..79f0d54931 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml @@ -208,4 +208,14 @@ SELECT DISTINCT(id) as project_id FROM t_ds_project + + diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/CommandMapperTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/CommandMapperTest.java index 560b68754a..5623969b08 100644 --- a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/CommandMapperTest.java +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/CommandMapperTest.java @@ -42,6 +42,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Lists; /** @@ -135,7 +136,7 @@ public class CommandMapperTest extends BaseDaoTest { createCommand(CommandType.START_PROCESS, processDefinition.getCode()); - List actualCommand = commandMapper.queryCommandPage(1, 0); + List actualCommand = commandMapper.selectList(new QueryWrapper<>()); Assertions.assertNotNull(actualCommand); } diff --git a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/enums/RegistryNodeType.java b/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/enums/RegistryNodeType.java index a1f3bb02b7..cbc2db6a63 100644 --- a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/enums/RegistryNodeType.java +++ b/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/enums/RegistryNodeType.java @@ -37,5 +37,4 @@ public enum RegistryNodeType { private final String name; private final String registryPath; - } diff --git a/dolphinscheduler-ui/src/layouts/content/use-dataList.ts b/dolphinscheduler-ui/src/layouts/content/use-dataList.ts index 69ebfa6e39..facf521db8 100644 --- a/dolphinscheduler-ui/src/layouts/content/use-dataList.ts +++ b/dolphinscheduler-ui/src/layouts/content/use-dataList.ts @@ -255,6 +255,10 @@ export function useDataList() { label: t('menu.worker'), key: '/monitor/worker' }, + { + label: t('menu.alert_server'), + key: '/monitor/alert_server' + }, { label: t('menu.db'), key: '/monitor/db' diff --git a/dolphinscheduler-ui/src/locales/en_US/menu.ts b/dolphinscheduler-ui/src/locales/en_US/menu.ts index dec594be07..d71f382ec0 100644 --- a/dolphinscheduler-ui/src/locales/en_US/menu.ts +++ b/dolphinscheduler-ui/src/locales/en_US/menu.ts @@ -40,6 +40,7 @@ export default { service_manage: 'Service Manage', master: 'Master', worker: 'Worker', + alert_server: 'Alert Server', db: 'DB', statistical_manage: 'Statistical Manage', statistics: 'Statistics', diff --git a/dolphinscheduler-ui/src/locales/en_US/monitor.ts b/dolphinscheduler-ui/src/locales/en_US/monitor.ts index 9a7550177a..c16c9a1961 100644 --- a/dolphinscheduler-ui/src/locales/en_US/monitor.ts +++ b/dolphinscheduler-ui/src/locales/en_US/monitor.ts @@ -35,6 +35,7 @@ export default { memory_usage: 'Memory Usage', disk_available: 'Disk Available', load_average: 'Load Average', + thread_pool_usage: 'Thread Pool Usage', create_time: 'Create Time', last_heartbeat_time: 'Last Heartbeat Time', directory_detail: 'Directory Detail', @@ -44,6 +45,11 @@ export default { worker_no_data_result_desc: 'Currently, there are no worker nodes exist, please create a worker node and refresh this page' }, + alert_server: { + alert_server_no_data_result_title: 'No Alert Server Nodes Exist', + alert_server_no_data_result_desc: + 'Currently, there are no alert server nodes exist, please create a alert server node and refresh this page' + }, db: { health_state: 'Health State', max_connections: 'Max Connections', diff --git a/dolphinscheduler-ui/src/locales/zh_CN/menu.ts b/dolphinscheduler-ui/src/locales/zh_CN/menu.ts index 2d38fa9e41..257541f3ad 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/menu.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/menu.ts @@ -41,6 +41,7 @@ export default { service_manage: '服务管理', master: 'Master', worker: 'Worker', + alert_server: 'Alert Server', db: 'DB', statistical_manage: '统计管理', statistics: 'Statistics', diff --git a/dolphinscheduler-ui/src/locales/zh_CN/monitor.ts b/dolphinscheduler-ui/src/locales/zh_CN/monitor.ts index dbae52fe07..0f21669307 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/monitor.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/monitor.ts @@ -35,6 +35,7 @@ export default { memory_usage: '内存使用量', disk_available: '磁盘可用容量', load_average: '平均负载量', + thread_pool_usage: '线程池使用量', create_time: '创建时间', last_heartbeat_time: '最后心跳时间', directory_detail: '目录详情', @@ -44,6 +45,11 @@ export default { worker_no_data_result_desc: '目前没有任何Worker节点,请先创建Worker节点,再访问该页面' }, + alert_server: { + alert_server_no_data_result_title: 'Alert Server节点不存在', + alert_server_no_data_result_desc: + '目前没有任何Alert Server节点,请先创建Alert Server节点,再访问该页面' + }, db: { health_state: '健康状态', max_connections: '最大连接数', diff --git a/dolphinscheduler-ui/src/router/modules/monitor.ts b/dolphinscheduler-ui/src/router/modules/monitor.ts index e2fa40b1c5..7e29517a5f 100644 --- a/dolphinscheduler-ui/src/router/modules/monitor.ts +++ b/dolphinscheduler-ui/src/router/modules/monitor.ts @@ -51,6 +51,17 @@ export default { auth: [] } }, + { + path: '/monitor/alert_server', + name: 'servers-alert-server', + component: components['monitor-servers-alert_server'], + meta: { + title: '服务管理-Alert Server', + activeMenu: 'monitor', + showSide: true, + auth: [] + } + }, { path: '/monitor/db', name: 'servers-db', diff --git a/dolphinscheduler-ui/src/service/modules/monitor/index.ts b/dolphinscheduler-ui/src/service/modules/monitor/index.ts index f0d3b50c23..bbf224eb5e 100644 --- a/dolphinscheduler-ui/src/service/modules/monitor/index.ts +++ b/dolphinscheduler-ui/src/service/modules/monitor/index.ts @@ -16,6 +16,7 @@ */ import { axios } from '@/service/service' +import type { ServerNodeType } from './types' export function queryDatabaseState(): any { return axios({ @@ -37,3 +38,10 @@ export function listWorker(): any { method: 'get' }) } + +export function listMonitorServerNode(nodeType: ServerNodeType): any { + return axios({ + url: `/monitor/${nodeType}`, + method: 'get' + }) +} diff --git a/dolphinscheduler-ui/src/service/modules/monitor/types.ts b/dolphinscheduler-ui/src/service/modules/monitor/types.ts index 371b36786d..0a689019ce 100644 --- a/dolphinscheduler-ui/src/service/modules/monitor/types.ts +++ b/dolphinscheduler-ui/src/service/modules/monitor/types.ts @@ -25,7 +25,9 @@ interface DatabaseRes { date: string } -interface MasterNode { +type ServerNodeType = 'MASTER' | 'WORKER' | 'ALERT_SERVER' + +interface ServerNode { id: number host: string port: number @@ -35,14 +37,23 @@ interface MasterNode { lastHeartbeatTime: string } -interface WorkerNode { - id: number - host: string - port: number - zkDirectories: Array - resInfo: string - createTime: string - lastHeartbeatTime: string +interface MasterNode extends ServerNode { + serverStatus?: 'NORMAL' | 'BUZY' +} + +interface WorkerNode extends ServerNode { + serverStatus?: 'NORMAL' | 'BUZY' + workerHostWeight?: number + threadPoolUsage?: number } -export { DatabaseRes, MasterNode, WorkerNode } +interface AlertNode extends MasterNode {} + +export { + DatabaseRes, + MasterNode, + WorkerNode, + ServerNodeType, + ServerNode, + AlertNode +} diff --git a/dolphinscheduler-ui/src/service/modules/projects-analysis/index.ts b/dolphinscheduler-ui/src/service/modules/projects-analysis/index.ts index 9f4b275c2a..ed651c2139 100644 --- a/dolphinscheduler-ui/src/service/modules/projects-analysis/index.ts +++ b/dolphinscheduler-ui/src/service/modules/projects-analysis/index.ts @@ -16,7 +16,7 @@ */ import { axios } from '@/service/service' -import { CodeReq, StateReq } from './types' +import { ListReq, CodeReq, StateReq } from './types' export function countCommandState(): any { return axios({ @@ -55,3 +55,19 @@ export function countTaskState(params: StateReq): any { params }) } + +export function queryListCommandPaging(params: ListReq): any { + return axios({ + url: '/projects/analysis/listCommand', + method: 'get', + params + }) +} + +export function queryListErrorCommandPaging(params: ListReq): any { + return axios({ + url: '/projects/analysis/listErrorCommand', + method: 'get', + params + }) +} diff --git a/dolphinscheduler-ui/src/service/modules/projects-analysis/types.ts b/dolphinscheduler-ui/src/service/modules/projects-analysis/types.ts index ca577143aa..aca1a190f3 100644 --- a/dolphinscheduler-ui/src/service/modules/projects-analysis/types.ts +++ b/dolphinscheduler-ui/src/service/modules/projects-analysis/types.ts @@ -66,6 +66,12 @@ interface CommandStateRes { commandState: string } +interface ListReq { + pageNo: number + pageSize: number + searchVal?: string +} + export { CodeReq, StateReq, @@ -73,5 +79,6 @@ export { WorkflowInstanceCountVo, TaskInstanceCountVo, TaskQueueRes, - CommandStateRes + CommandStateRes, + ListReq } diff --git a/dolphinscheduler-ui/src/views/monitor/servers/alert_server/index.module.scss b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/index.module.scss new file mode 100644 index 0000000000..7bde891f5b --- /dev/null +++ b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/index.module.scss @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + @mixin base { + font-size: 5vw; + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; +} + +.card { + @include base; +} + +.load-average { + @include base; + color: var(--n-color-target); +} + +.link-btn { + color: var(--n-color-target); + cursor: pointer; + + &:hover { + color: var(--n-color-target); + opacity: 0.8; + } +} diff --git a/dolphinscheduler-ui/src/views/monitor/servers/alert_server/index.tsx b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/index.tsx new file mode 100644 index 0000000000..a223fcb8a8 --- /dev/null +++ b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/index.tsx @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { defineComponent, onMounted, ref, toRefs } from 'vue' +import { NGrid, NGi, NCard, NNumberAnimation, NSpace, NTag } from 'naive-ui' +import { useI18n } from 'vue-i18n' +import { useServerNode } from './use-server-node' +import styles from './index.module.scss' +import Card from '@/components/card' +import Result from '@/components/result' +import Gauge from '@/components/chart/modules/Gauge' +import NodeModal from './node-modal' +import type { Ref } from 'vue' +import type { RowData } from 'naive-ui/es/data-table/src/interface' +import type { AlertNode } from '@/service/modules/monitor/types' +import { capitalize } from 'lodash' + +const alertServer = defineComponent({ + name: 'alertServer', + setup() { + const showModalRef = ref(false) + const { t } = useI18n() + const { variables, getTableData } = useServerNode() + const zkDirectoryRef: Ref> = ref([]) + + const clickDetails = (zkDirectories: string) => { + zkDirectoryRef.value = [{ directory: zkDirectories, index: 1 }] + showModalRef.value = true + } + + const onConfirmModal = () => { + showModalRef.value = false + } + + onMounted(() => { + getTableData() + }) + + return { + t, + ...toRefs(variables), + clickDetails, + onConfirmModal, + showModalRef, + zkDirectoryRef + } + }, + render() { + const { t, clickDetails, onConfirmModal, showModalRef, zkDirectoryRef } = + this + + const renderNodeServerStatusTag = (item: AlertNode) => { + const serverStatus = JSON.parse(item.resInfo)?.serverStatus + + if (!serverStatus) return '' + + return ( + + {capitalize(serverStatus)} + + ) + } + + return this.data.length < 1 ? ( + + ) : ( + <> + + {this.data.map((item: AlertNode) => { + return ( + + + + + {renderNodeServerStatusTag(item)} + + {`${t('monitor.master.host')}: ${ + item ? item.host : ' - ' + }`} + clickDetails(item.zkDirectory)} + > + {t('monitor.master.directory_detail')} + + + + {`${t('monitor.master.create_time')}: ${ + item ? item.createTime : ' - ' + }`} + {`${t('monitor.master.last_heartbeat_time')}: ${ + item ? item.lastHeartbeatTime : ' - ' + }`} + + + + + + +

+ {item && ( + + )} +
+ + + + +
+ {item && ( + + )} +
+
+
+ + +
+ {item && ( + + )} +
+
+
+ + +
+ {item && ( + + )} +
+
+
+ + + ) + })} + + + + ) + } +}) + +export default alertServer diff --git a/dolphinscheduler-ui/src/views/monitor/servers/alert_server/node-modal.tsx b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/node-modal.tsx new file mode 100644 index 0000000000..a8b3c14dcb --- /dev/null +++ b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/node-modal.tsx @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { defineComponent } from 'vue' +import { useI18n } from 'vue-i18n' +import { NDataTable } from 'naive-ui' +import Modal from '@/components/modal' +import type { PropType } from 'vue' +import type { + RowData, + TableColumns +} from 'naive-ui/es/data-table/src/interface' + +const props = { + showModal: { + type: Boolean as PropType, + default: false + }, + data: { + type: Array as PropType>, + default: () => [] + } +} + +const NodeModal = defineComponent({ + props, + emits: ['confirmModal'], + setup(props, ctx) { + const { t } = useI18n() + const columnsRef: TableColumns = [ + { title: '#', key: 'index', render: (row, index) => index + 1 }, + { title: t('monitor.master.directory'), key: 'directory' } + ] + + const onConfirm = () => { + ctx.emit('confirmModal') + } + + return { t, columnsRef, onConfirm } + }, + render() { + const { t, columnsRef, onConfirm } = this + + return ( + + {{ + default: () => ( + + ) + }} + + ) + } +}) + +export default NodeModal diff --git a/dolphinscheduler-ui/src/views/monitor/servers/alert_server/use-server-node.ts b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/use-server-node.ts new file mode 100644 index 0000000000..b964039ae1 --- /dev/null +++ b/dolphinscheduler-ui/src/views/monitor/servers/alert_server/use-server-node.ts @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { reactive } from 'vue' +import { useAsyncState } from '@vueuse/core' +import { listMonitorServerNode } from '@/service/modules/monitor' +import type { AlertNode } from '@/service/modules/monitor/types' + +export function useServerNode() { + const variables = reactive({ + data: [] + }) + const getTableData = () => { + const { state } = useAsyncState( + listMonitorServerNode('ALERT_SERVER').then((res: Array) => { + variables.data = res as any + }), + [] + ) + + return state + } + return { variables, getTableData } +} diff --git a/dolphinscheduler-ui/src/views/monitor/servers/master/index.tsx b/dolphinscheduler-ui/src/views/monitor/servers/master/index.tsx index c23e0baa3b..cf29109c27 100644 --- a/dolphinscheduler-ui/src/views/monitor/servers/master/index.tsx +++ b/dolphinscheduler-ui/src/views/monitor/servers/master/index.tsx @@ -16,7 +16,7 @@ */ import { defineComponent, onMounted, ref, toRefs } from 'vue' -import { NGrid, NGi, NCard, NNumberAnimation, NSpace } from 'naive-ui' +import { NGrid, NGi, NCard, NNumberAnimation, NSpace, NTag } from 'naive-ui' import { useI18n } from 'vue-i18n' import { useMaster } from './use-master' import styles from './index.module.scss' @@ -27,6 +27,7 @@ import MasterModal from './master-modal' import type { Ref } from 'vue' import type { RowData } from 'naive-ui/es/data-table/src/interface' import type { MasterNode } from '@/service/modules/monitor/types' +import { capitalize } from 'lodash' const master = defineComponent({ name: 'master', @@ -62,6 +63,18 @@ const master = defineComponent({ const { t, clickDetails, onConfirmModal, showModalRef, zkDirectoryRef } = this + const renderNodeServerStatusTag = (item: MasterNode) => { + const serverStatus = JSON.parse(item.resInfo)?.serverStatus + + if (!serverStatus) return '' + + return ( + + {capitalize(serverStatus)} + + ) + } + return this.data.length < 1 ? ( - + + {renderNodeServerStatusTag(item)} + {`${t('monitor.master.host')}: ${ item ? item.host : ' - ' }`} diff --git a/dolphinscheduler-ui/src/views/monitor/servers/master/use-master.ts b/dolphinscheduler-ui/src/views/monitor/servers/master/use-master.ts index bd1e55e4cd..cb234a3633 100644 --- a/dolphinscheduler-ui/src/views/monitor/servers/master/use-master.ts +++ b/dolphinscheduler-ui/src/views/monitor/servers/master/use-master.ts @@ -17,7 +17,7 @@ import { reactive } from 'vue' import { useAsyncState } from '@vueuse/core' -import { listMaster } from '@/service/modules/monitor' +import { listMonitorServerNode } from '@/service/modules/monitor' import type { MasterNode } from '@/service/modules/monitor/types' export function useMaster() { @@ -26,7 +26,7 @@ export function useMaster() { }) const getTableMaster = () => { const { state } = useAsyncState( - listMaster().then((res: Array) => { + listMonitorServerNode('MASTER').then((res: Array) => { variables.data = res as any }), [] diff --git a/dolphinscheduler-ui/src/views/monitor/servers/worker/index.tsx b/dolphinscheduler-ui/src/views/monitor/servers/worker/index.tsx index 35bddf8dc2..6971e78f1b 100644 --- a/dolphinscheduler-ui/src/views/monitor/servers/worker/index.tsx +++ b/dolphinscheduler-ui/src/views/monitor/servers/worker/index.tsx @@ -16,7 +16,7 @@ */ import { defineComponent, onMounted, ref, toRefs } from 'vue' -import { NGrid, NGi, NCard, NNumberAnimation, NSpace } from 'naive-ui' +import { NGrid, NGi, NCard, NNumberAnimation, NSpace, NTag } from 'naive-ui' import { useI18n } from 'vue-i18n' import { useWorker } from './use-worker' import styles from './index.module.scss' @@ -27,6 +27,7 @@ import WorkerModal from './worker-modal' import type { Ref } from 'vue' import type { RowData } from 'naive-ui/es/data-table/src/interface' import type { WorkerNode } from '@/service/modules/monitor/types' +import { capitalize } from 'lodash' const worker = defineComponent({ name: 'worker', @@ -36,12 +37,8 @@ const worker = defineComponent({ const { variables, getTableWorker } = useWorker() const zkDirectoryRef: Ref> = ref([]) - const clickDetails = (zkDirectories: Array) => { - zkDirectoryRef.value = zkDirectories.map((zkItem) => { - return { - directory: zkItem - } - }) + const clickDetails = (zkDirectories: string) => { + zkDirectoryRef.value = [{ directory: zkDirectories, index: 1 }] showModalRef.value = true } @@ -66,6 +63,18 @@ const worker = defineComponent({ const { t, clickDetails, onConfirmModal, showModalRef, zkDirectoryRef } = this + const renderNodeServerStatusTag = (item: WorkerNode) => { + const serverStatus = JSON.parse(item.resInfo)?.serverStatus + + if (!serverStatus) return '' + + return ( + + {capitalize(serverStatus)} + + ) + } + return this.data.length < 1 ? ( - + + {renderNodeServerStatusTag(item)} + {`${t('monitor.worker.host')}: ${ item ? item.host : ' - ' }`} clickDetails(item.zkDirectories)} + onClick={() => clickDetails(item.zkDirectory)} > {t('monitor.worker.directory_detail')} @@ -102,7 +118,7 @@ const worker = defineComponent({ - +
@@ -155,6 +171,33 @@ const worker = defineComponent({
+ + + +
+ {item && ( + <> + + / + + + )} +
+
+
) diff --git a/dolphinscheduler-ui/src/views/monitor/servers/worker/use-worker.ts b/dolphinscheduler-ui/src/views/monitor/servers/worker/use-worker.ts index 06ec70bea1..e6f028781d 100644 --- a/dolphinscheduler-ui/src/views/monitor/servers/worker/use-worker.ts +++ b/dolphinscheduler-ui/src/views/monitor/servers/worker/use-worker.ts @@ -17,7 +17,7 @@ import { reactive } from 'vue' import { useAsyncState } from '@vueuse/core' -import { listWorker } from '@/service/modules/monitor' +import { listMonitorServerNode } from '@/service/modules/monitor' import type { WorkerNode } from '@/service/modules/monitor/types' export function useWorker() { @@ -27,7 +27,7 @@ export function useWorker() { const getTableWorker = () => { const { state } = useAsyncState( - listWorker().then((res: Array) => { + listMonitorServerNode('WORKER').then((res: Array) => { variables.data = res as any }), [] diff --git a/dolphinscheduler-ui/src/views/monitor/statistics/statistics/index.tsx b/dolphinscheduler-ui/src/views/monitor/statistics/statistics/index.tsx index 5d50728598..6a6eaaf222 100644 --- a/dolphinscheduler-ui/src/views/monitor/statistics/statistics/index.tsx +++ b/dolphinscheduler-ui/src/views/monitor/statistics/statistics/index.tsx @@ -15,58 +15,44 @@ * limitations under the License. */ -import { defineComponent, ref } from 'vue' -import { NGrid, NGi, NNumberAnimation } from 'naive-ui' -import { useStatistics } from './use-statistics' -import { useI18n } from 'vue-i18n' -import Card from '@/components/card' -import styles from './index.module.scss' +import { defineComponent } from 'vue' +import { NGrid, NGi, NTabs, NTabPane, NCard } from 'naive-ui' +import ListCommandTable from './list-command-table' +import ListErrorCommandTable from './list-error-command-table' const statistics = defineComponent({ name: 'statistics', - setup() { - const { t } = useI18n() - const { getStatistics } = useStatistics() - const statisticsRef = ref(getStatistics()) + setup() {}, - return { t, statisticsRef } - }, render() { - const { t, statisticsRef } = this - return ( - - - -
- {statisticsRef.command.length > 0 && ( - item.normalCount) - .reduce((prev, next) => prev + next)} - /> - )} -
-
-
+ - -
- {statisticsRef.command.length > 0 && ( - item.errorCount) - .reduce((prev, next) => prev + next)} - /> - )} -
-
+ + + + + + + + + +
) diff --git a/dolphinscheduler-ui/src/views/monitor/statistics/statistics/list-command-table.tsx b/dolphinscheduler-ui/src/views/monitor/statistics/statistics/list-command-table.tsx new file mode 100644 index 0000000000..11c3e58e47 --- /dev/null +++ b/dolphinscheduler-ui/src/views/monitor/statistics/statistics/list-command-table.tsx @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + defineComponent, + onMounted, + toRefs, + watch, + reactive, + ref, + h +} from 'vue' +import { NSpace, NDataTable, NPagination } from 'naive-ui' +import { useI18n } from 'vue-i18n' +import Card from '@/components/card' +import { + COLUMN_WIDTH_CONFIG, + calculateTableWidth, + DefaultTableWidth +} from '@/common/column-width-config' +import { useAsyncState } from '@vueuse/core' +import { queryListCommandPaging } from '@/service/modules/projects-analysis' + +const ListCommandTable = defineComponent({ + name: 'list-command-table', + setup() { + const { t } = useI18n() + + const variables = reactive({ + columns: [], + tableWidth: DefaultTableWidth, + tableData: [], + page: ref(1), + pageSize: ref(10), + userName: ref(null), + totalPage: ref(1), + loadingRef: ref(false) + }) + + const createColumns = (variables: any) => { + variables.columns = [ + { + title: 'ID', + key: 'id', + ...COLUMN_WIDTH_CONFIG['index'] + }, + { + title: 'Command Type', + key: 'commandType', + ...COLUMN_WIDTH_CONFIG['userName'] + }, + { + title: 'Command Param', + key: 'commandParam', + ...COLUMN_WIDTH_CONFIG['linkName'] + }, + + { + title: 'Task Info', + key: 'id', + width: 300, + render: (row: any) => { + return h('div', [ + `Definition Code:${row.processDefinitionCode} `, + h('br'), + `Definition Version:${row.processDefinitionVersion} `, + h('br'), + `Instance Id:${row.processInstanceId} `, + h('br'), + `Instance Priority:${row.processInstancePriority} ` + ]) + } + }, + + { + title: 'Task Params', + key: 'id', + width: 300, + render: (row: any) => { + return h('div', [ + `DryRun:${row.dryRun} `, + h('br'), + `Environment Code:${row.environmentCode} `, + h('br'), + `Failure Strategy:${row.failureStrategy} `, + h('br'), + `Task Depend Type:${row.taskDependType} ` + ]) + } + }, + + { + title: 'Worker Info', + key: 'id', + width: 220, + render: (row: any) => { + return h('div', [ + `Worker Group:${row.workerGroup} `, + h('br'), + `Tenant Code:${row.tenantCode} `, + h('br'), + `Test Flag:${row.testFlag} ` + ]) + } + }, + + { + title: 'Warning Info', + key: 'id', + width: 200, + render: (row: any) => { + return h('div', [ + `Warning Group Id:${row.warningGroupId} `, + h('br'), + `Warning Type:${row.warningType} ` + ]) + } + }, + { + title: 'Executor Id', + key: 'executorId', + ...COLUMN_WIDTH_CONFIG['type'] + }, + { + title: 'Time', + key: 'startTime', + width: 280, + render: (row: any) => { + return h('div', [ + `Start Time:${row.startTime} `, + h('br'), + `Update Time:${row.updateTime} `, + h('br'), + `Schedule Time:${row.scheduleTime} ` + ]) + } + } + ] + + if (variables.tableWidth) { + variables.tableWidth = calculateTableWidth(variables.columns) + } + } + + const getTableData = () => { + if (variables.loadingRef) return + variables.loadingRef = true + const data = { + pageSize: variables.pageSize, + pageNo: variables.page + } + + const { state } = useAsyncState( + queryListCommandPaging(data).then((res: any) => { + variables.totalPage = res.totalPage + variables.tableData = res.totalList + variables.loadingRef = false + }), + {} + ) + + return state + } + + const onUpdatePageSize = () => { + variables.page = 1 + getTableData() + } + + onMounted(() => { + createColumns(variables) + getTableData() + }) + + watch(useI18n().locale, () => { + createColumns(variables) + }) + + return { + t, + ...toRefs(variables), + getTableData, + onUpdatePageSize + } + }, + render() { + const { getTableData, onUpdatePageSize, loadingRef } = this + + return ( + + + + + + + + + + + ) + } +}) + +export default ListCommandTable diff --git a/dolphinscheduler-ui/src/views/monitor/statistics/statistics/list-error-command-table.tsx b/dolphinscheduler-ui/src/views/monitor/statistics/statistics/list-error-command-table.tsx new file mode 100644 index 0000000000..04a2297299 --- /dev/null +++ b/dolphinscheduler-ui/src/views/monitor/statistics/statistics/list-error-command-table.tsx @@ -0,0 +1,237 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + defineComponent, + onMounted, + toRefs, + watch, + reactive, + ref, + h +} from 'vue' +import { NSpace, NDataTable, NPagination } from 'naive-ui' +import { useI18n } from 'vue-i18n' +import Card from '@/components/card' +import { + COLUMN_WIDTH_CONFIG, + calculateTableWidth, + DefaultTableWidth +} from '@/common/column-width-config' +import { useAsyncState } from '@vueuse/core' +import { queryListErrorCommandPaging } from '@/service/modules/projects-analysis' + +const ListErrorCommandTable = defineComponent({ + name: 'list-error-command-table', + setup() { + const { t } = useI18n() + + const variables = reactive({ + columns: [], + tableWidth: DefaultTableWidth, + tableData: [], + page: ref(1), + pageSize: ref(10), + userName: ref(null), + totalPage: ref(1), + loadingRef: ref(false) + }) + + const createColumns = (variables: any) => { + variables.columns = [ + { + title: 'ID', + key: 'id', + ...COLUMN_WIDTH_CONFIG['index'] + }, + { + title: 'Command Type', + key: 'commandType', + ...COLUMN_WIDTH_CONFIG['userName'] + }, + { + title: 'Command Param', + key: 'commandParam', + ...COLUMN_WIDTH_CONFIG['linkName'] + }, + + { + title: 'Task Info', + key: 'id', + width: 300, + render: (row: any) => { + return h('div', [ + `Definition Code:${row.processDefinitionCode} `, + h('br'), + `Definition Version:${row.processDefinitionVersion} `, + h('br'), + `Instance Id:${row.processInstanceId} `, + h('br'), + `Instance Priority:${row.processInstancePriority} ` + ]) + } + }, + + { + title: 'Task Params', + key: 'id', + width: 300, + render: (row: any) => { + return h('div', [ + `DryRun:${row.dryRun} `, + h('br'), + `Environment Code:${row.environmentCode} `, + h('br'), + `Failure Strategy:${row.failureStrategy} `, + h('br'), + `Task Depend Type:${row.taskDependType} ` + ]) + } + }, + + { + title: 'Worker Info', + key: 'id', + width: 220, + render: (row: any) => { + return h('div', [ + `Worker Group:${row.workerGroup} `, + h('br'), + `Tenant Code:${row.tenantCode} `, + h('br'), + `Test Flag:${row.testFlag} ` + ]) + } + }, + + { + title: 'Warning Info', + key: 'id', + width: 200, + render: (row: any) => { + return h('div', [ + `Warning Group Id:${row.warningGroupId} `, + h('br'), + `Warning Type:${row.warningType} ` + ]) + } + }, + { + title: 'Message', + key: 'message', + ...COLUMN_WIDTH_CONFIG['linkName'] + }, + { + title: 'Executor Id', + key: 'executorId', + ...COLUMN_WIDTH_CONFIG['type'] + }, + { + title: 'Time', + key: 'startTime', + width: 280, + render: (row: any) => { + return h('div', [ + `Start Time:${row.startTime || '-'} `, + h('br'), + `Update Time:${row.updateTime || '-'} `, + h('br'), + `Schedule Time:${row.scheduleTime || '-'} ` + ]) + } + } + ] + + if (variables.tableWidth) { + variables.tableWidth = calculateTableWidth(variables.columns) + } + } + + const getTableData = () => { + if (variables.loadingRef) return + variables.loadingRef = true + const data = { + pageSize: variables.pageSize, + pageNo: variables.page + } + + const { state } = useAsyncState( + queryListErrorCommandPaging(data).then((res: any) => { + variables.totalPage = res.totalPage + variables.tableData = res.totalList + variables.loadingRef = false + }), + {} + ) + + return state + } + + const onUpdatePageSize = () => { + variables.page = 1 + getTableData() + } + + onMounted(() => { + createColumns(variables) + getTableData() + }) + + watch(useI18n().locale, () => { + createColumns(variables) + }) + + return { + t, + ...toRefs(variables), + getTableData, + onUpdatePageSize + } + }, + render() { + const { getTableData, onUpdatePageSize, loadingRef } = this + + return ( + + + + + + + + + + + ) + } +}) + +export default ListErrorCommandTable