From aa93b52dd9f9541e7ae66d99e95eb9cfd98be02f Mon Sep 17 00:00:00 2001 From: v-zhangjc9 Date: Fri, 9 May 2025 17:23:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor(web):=20=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E6=89=93=E5=8C=85=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-web/client/src/index.tsx | 4 +- service-web/client/src/pages/Overview.tsx | 188 ++++++++++-------- service-web/client/vite.config.ts | 10 +- service-web/pom.xml | 23 +++ .../web/controller/OverviewController.java | 54 +++-- .../web/entity/overview/TableCountVO.java | 38 ++++ .../web/entity/overview/TaskCountVO.java | 55 +++++ .../web/entity/overview/VersionCountVO.java | 45 +++++ .../web/entity/overview/YarnCountVO.java | 76 +++++++ 9 files changed, 378 insertions(+), 115 deletions(-) create mode 100644 service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TableCountVO.java create mode 100644 service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TaskCountVO.java create mode 100644 service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/VersionCountVO.java create mode 100644 service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/YarnCountVO.java diff --git a/service-web/client/src/index.tsx b/service-web/client/src/index.tsx index 0c2832e..363ba8c 100644 --- a/service-web/client/src/index.tsx +++ b/service-web/client/src/index.tsx @@ -1,5 +1,5 @@ import {createRoot} from 'react-dom/client' -import {createBrowserRouter, RouterProvider} from 'react-router' +import {createHashRouter, RouterProvider} from 'react-router' import './components/Registry.ts' @@ -16,7 +16,7 @@ import Version from './pages/Version.tsx' import Yarn from './pages/Yarn.tsx' import YarnCluster from './pages/YarnCluster.tsx' -const routes = createBrowserRouter([ +const routes = createHashRouter([ { path: '/', Component: App, diff --git a/service-web/client/src/pages/Overview.tsx b/service-web/client/src/pages/Overview.tsx index cf7ce5b..3c5c5df 100644 --- a/service-web/client/src/pages/Overview.tsx +++ b/service-web/client/src/pages/Overview.tsx @@ -33,7 +33,7 @@ const versionDetailDialog = (variable: string, target: string) => { method: 'get', url: `${commonInfo.baseUrl}/overview/version_detail`, data: { - target: `${target}`, + target: target, version: '${version}', }, }, @@ -272,65 +272,78 @@ const Overview: React.FC = () => { ], }, {type: 'divider'}, - '表数量 (重点表数量, 普通表数量)', { - type: 'service', + type: 'crud', + title: '同步表数量', api: `${commonInfo.baseUrl}/overview`, + ...crudCommonOptions(), interval: 60000, - silentPolling: true, - body: [ + columns: [ { - type: 'tpl', - tpl: '逻辑表:${PADSTART(table_count, 4)} (${PADSTART(table_focus_count, 4)}, ${PADSTART(table_count - table_focus_count, 4)})', + name: 'type', + label: '表类型', }, - '
', { - type: 'tpl', - tpl: '湖底表:${PADSTART(hudi_count, 4)} (${PADSTART(hudi_focus_count, 4)}, ${PADSTART(hudi_count - hudi_focus_count, 4)})', + name: 'total', + label: '总表数', + width: 100, + align: 'center', }, - '
', { + name: 'focus', + label: '重点表', + className: 'text-danger font-bold', + width: 100, + align: 'center', + }, + { + label: '普通表', type: 'tpl', - tpl: '嗨福表:${PADSTART(hive_count, 4)} (${PADSTART(hive_focus_count, 4)}, ${PADSTART(hive_count - hive_focus_count, 4)})', + tpl: '${total - focus}', + width: 100, + align: 'center', }, ], }, - {type: 'divider'}, { - type: 'service', + type: 'crud', + title: '同步表数量', api: `${commonInfo.baseUrl}/overview/sync_running_status`, + ...crudCommonOptions(), interval: 10000, - silentPolling: true, - body: [ + columns: [ { - type: 'tpl', - tpl: '任务数${totalJob}', + name: 'type', + label: '类型', }, { - className: 'mx-2', - type: 'tpl', - tpl: '运行中${PADSTART(runningJob, 3)}', + name: 'total', + label: '任务数', + width: 100, + align: 'center', }, { - type: 'tpl', - tpl: '已停止${PADSTART(unRunningJob, 3)}', - }, - tableDetailDialog('unRunningJob', 'unRunningJobList'), - '
', - { - type: 'tpl', - tpl: '总表数${totalTable}', + name: 'running', + label: '运行中', + width: 100, + align: 'center', }, { - className: 'mx-2', - type: 'tpl', - tpl: '运行中${PADSTART(runningTable, 3)}', + name: 'stopped', + label: '已停止', + className: 'text-danger font-bold', + width: 100, + align: 'center', }, { - type: 'tpl', - tpl: '已停止${PADSTART(unRunningTable, 3)}', + type: 'operation', + label: '操作', + width: 100, + align: 'center', + buttons: [ + tableDetailDialog('stopped', 'list'), + ], }, - tableDetailDialog('unRunningTable', 'unRunningTableList'), ], }, {type: 'divider'}, @@ -360,61 +373,74 @@ const Overview: React.FC = () => { interval: 10000, silentPolling: true, body: [ - '版本:', { - type: 'tpl', - className: 'font-bold', - tpl: '${version}', + type: 'table', + title: '跨天情况 (${version})', + source: '${items}', + ...crudCommonOptions(), + headerToolbar: [ + '${version}' + ], + columns: [ + { + name: 'type', + label: '类型', + }, + { + name: 'unReceive', + label: '未接收', + width: 100, + align: 'center', + }, + { + type: 'operation', + label: '操作', + width: 100, + align: 'center', + buttons: [ + versionDetailDialog('unReceive', 'unReceive_${key}'), + ], + }, + { + name: 'unScheduled', + label: '未跨天', + className: 'text-danger font-bold', + width: 100, + align: 'center', + }, + { + type: 'operation', + label: '操作', + width: 100, + align: 'center', + buttons: [ + versionDetailDialog('unScheduled', 'unScheduled_${key}'), + ], + }, + ], }, - '
', - '未接收, 未跨天', - '
', - '重点表:', - { - type: 'tpl', - tpl: '${PADSTART(unReceive.focus, 3)}', - }, - versionDetailDialog('unReceive.focus', 'unReceive_focus'), - ',', - { - type: 'tpl', - tpl: '${PADSTART(unSchedule.focus, 3)}', - }, - versionDetailDialog('unSchedule.focus', 'unScheduled_focus'), - '
', - '普通表:', - { - type: 'tpl', - tpl: '${PADSTART(unReceive.normal, 3)}', - }, - versionDetailDialog('unReceive.normal', 'unReceive_normal'), - ',', - { - type: 'tpl', - tpl: '${PADSTART(unSchedule.normal, 3)}', - }, - versionDetailDialog('unSchedule.normal', 'unScheduled_normal'), ], }, - {type: 'divider'}, { - type: 'service', + type: 'crud', + title: '调度策略', api: `${commonInfo.baseUrl}/overview/schedule_jobs`, + ...crudCommonOptions(), interval: 60000, - silentPolling: true, - body: [ - '调度策略', + loadDataOnce: true, + columns: [ { - type: 'each', - name: 'items', - items: { - type: 'tpl', - tpl: '
${trigger} (${job})
', - }, + name: 'trigger', + label: 'Cron表达式', + className: 'font-mono', + width: 300, + }, + { + name: 'job', + label: '策略描述', }, ], }, - {type: 'divider'}, { type: 'crud', title: '监控指标运行进度', @@ -426,13 +452,13 @@ const Overview: React.FC = () => { { name: 'name', label: '名称', - width: 120, + width: 150, }, { name: 'running', label: '状态', type: 'mapping', - width: 50, + width: 70, map: { 'true': '运行中', 'false': '未运行', diff --git a/service-web/client/vite.config.ts b/service-web/client/vite.config.ts index ffc5e8a..72701dc 100644 --- a/service-web/client/vite.config.ts +++ b/service-web/client/vite.config.ts @@ -1,7 +1,13 @@ -import {defineConfig} from 'vite' import react from '@vitejs/plugin-react-swc' +import {defineConfig, UserConfig} from 'vite' // https://vite.dev/config/ -export default defineConfig({ +export default defineConfig(({mode}) => { + let config: UserConfig = { plugins: [react()], + } + if (mode === 'production') { + config.base = '/hudi_services/service_web' + } + return config }) diff --git a/service-web/pom.xml b/service-web/pom.xml index 187cb00..a2e16cc 100644 --- a/service-web/pom.xml +++ b/service-web/pom.xml @@ -28,6 +28,29 @@ + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + copy-web-dist + compile + + copy-resources + + + ${project.build.outputDirectory}/static + + + ${project.basedir}/client/dist + false + + + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/service-web/src/main/java/com/lanyuanxiaoyao/service/web/controller/OverviewController.java b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/controller/OverviewController.java index 5fbbed9..403d5a5 100644 --- a/service-web/src/main/java/com/lanyuanxiaoyao/service/web/controller/OverviewController.java +++ b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/controller/OverviewController.java @@ -8,27 +8,26 @@ import com.lanyuanxiaoyao.service.configuration.ExecutorProvider; import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias; import com.lanyuanxiaoyao.service.configuration.entity.monitor.MetricsProgress; import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnApplication; +import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue; import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue; import com.lanyuanxiaoyao.service.configuration.entity.zookeeper.ZookeeperNode; -import com.lanyuanxiaoyao.service.forest.service.InfoService; -import com.lanyuanxiaoyao.service.forest.service.MonitorService; -import com.lanyuanxiaoyao.service.forest.service.QueueService; -import com.lanyuanxiaoyao.service.forest.service.ScheduleService; -import com.lanyuanxiaoyao.service.forest.service.YarnService; -import com.lanyuanxiaoyao.service.forest.service.ZookeeperService; +import com.lanyuanxiaoyao.service.forest.service.*; import com.lanyuanxiaoyao.service.web.controller.base.AmisCrudResponse; import com.lanyuanxiaoyao.service.web.controller.base.AmisMapResponse; import com.lanyuanxiaoyao.service.web.controller.base.AmisResponse; import com.lanyuanxiaoyao.service.web.controller.base.BaseController; import com.lanyuanxiaoyao.service.web.entity.JobIdAndAliasVO; import com.lanyuanxiaoyao.service.web.entity.ScheduleTimeVO; +import com.lanyuanxiaoyao.service.web.entity.overview.TableCountVO; +import com.lanyuanxiaoyao.service.web.entity.overview.TaskCountVO; +import com.lanyuanxiaoyao.service.web.entity.overview.VersionCountVO; +import com.lanyuanxiaoyao.service.web.entity.overview.YarnCountVO; import java.time.Instant; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import org.eclipse.collections.api.factory.Lists; -import org.eclipse.collections.api.factory.Maps; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.MutableList; import org.slf4j.Logger; @@ -67,7 +66,7 @@ public class OverviewController extends BaseController { } @GetMapping("") - public AmisMapResponse overview() throws ExecutionException, InterruptedException { + public AmisCrudResponse overview() throws ExecutionException, InterruptedException { CompletableFuture tableCountFuture = CompletableFuture.supplyAsync(infoService::tableCount, ExecutorProvider.EXECUTORS); CompletableFuture tableFocusCountFuture = CompletableFuture.supplyAsync(infoService::tableFocusCount, ExecutorProvider.EXECUTORS); CompletableFuture hudiCountFuture = CompletableFuture.supplyAsync(infoService::hudiCount, ExecutorProvider.EXECUTORS); @@ -82,13 +81,12 @@ public class OverviewController extends BaseController { hiveCountFuture, hiveFocusCountFuture ).get(); - return AmisResponse.responseMapData() - .setData("table_count", tableCountFuture.get()) - .setData("table_focus_count", tableFocusCountFuture.get()) - .setData("hudi_count", hudiCountFuture.get()) - .setData("hudi_focus_count", hudiFocusCountFuture.get()) - .setData("hive_count", hiveCountFuture.get()) - .setData("hive_focus_count", hiveFocusCountFuture.get()); + ImmutableList list = Lists.immutable.of( + new TableCountVO("逻辑表", tableCountFuture.get(), tableFocusCountFuture.get()), + new TableCountVO("湖底表", hudiCountFuture.get(), hudiFocusCountFuture.get()), + new TableCountVO("嗨福表", hiveCountFuture.get(), hiveFocusCountFuture.get()) + ); + return AmisResponse.responseCrudData(list); } @GetMapping("yarn-job") @@ -99,7 +97,6 @@ public class OverviewController extends BaseController { .setData("name", cluster) .setData("total", applications.size()) .setData("running", applications.count(app -> StrUtil.equals(app.getState(), "RUNNING"))) - .setData("running", applications.count(app -> StrUtil.equals(app.getState(), "RUNNING"))) .setData("scheduling", applications.count(app -> StrUtil.equals(app.getState(), "ACCEPTED"))) .setData("failure", applications.count(app -> StrUtil.equals(app.getState(), "FAILED"))); } @@ -131,10 +128,13 @@ public class OverviewController extends BaseController { CompletableFuture unScheduledNormalTableCount = CompletableFuture.supplyAsync(() -> infoService.unScheduledNormalTableCount(version), ExecutorProvider.EXECUTORS); CompletableFuture unScheduledFocusTableCount = CompletableFuture.supplyAsync(() -> infoService.unScheduledFocusTableCount(version), ExecutorProvider.EXECUTORS); CompletableFuture.allOf(unReceiveNormalTableCount, unReceiveFocusCount, unScheduledNormalTableCount, unScheduledFocusTableCount).get(); + ImmutableList list = Lists.immutable.of( + new VersionCountVO("focus", "重点表", unReceiveFocusCount.get(), unScheduledFocusTableCount.get()), + new VersionCountVO("normal", "普通表", unReceiveNormalTableCount.get(), unScheduledNormalTableCount.get()) + ); return AmisResponse.responseMapData() .setData("version", version) - .setData("unReceive", Maps.immutable.of("normal", unReceiveNormalTableCount.get(), "focus", unReceiveFocusCount.get())) - .setData("unSchedule", Maps.immutable.of("normal", unScheduledNormalTableCount.get(), "focus", unScheduledFocusTableCount.get())); + .setData("items", list); } @GetMapping("version_detail") @@ -175,7 +175,7 @@ public class OverviewController extends BaseController { } @GetMapping("sync_running_status") - public AmisMapResponse syncRunningStatus() { + public AmisCrudResponse syncRunningStatus() { ImmutableList locks = zookeeperService.getChildren(NameHelper.ZK_SYNC_RUNNING_LOCK_PATH).collect(ZookeeperNode::getPath); MutableList runningJob = Lists.mutable.empty().asSynchronized(); MutableList unRunningJob = Lists.mutable.empty().asSynchronized(); @@ -203,17 +203,11 @@ public class OverviewController extends BaseController { unRunningTable.add(ia); } }); - return AmisResponse.responseMapData() - .setData("totalJob", ids.size()) - .setData("runningJob", runningJob.size()) - .setData("runningJobList", runningJob) - .setData("unRunningJob", unRunningJob.size()) - .setData("unRunningJobList", unRunningJob) - .setData("totalTable", idAliases.size()) - .setData("runningTable", runningTable.size()) - .setData("runningTableList", runningTable) - .setData("unRunningTable", unRunningTable.size()) - .setData("unRunningTableList", unRunningTable); + ImmutableList list = Lists.immutable.of( + new TaskCountVO("同步任务数", ids.size(), runningJob.size(), unRunningJob.size(), unRunningJob.toImmutable()), + new TaskCountVO("同步表数", idAliases.size(), runningTable.size(), unRunningTable.size(), unRunningTable.toImmutable()) + ); + return AmisResponse.responseCrudData(list); } @GetMapping("monitor_progress") diff --git a/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TableCountVO.java b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TableCountVO.java new file mode 100644 index 0000000..187b180 --- /dev/null +++ b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TableCountVO.java @@ -0,0 +1,38 @@ +package com.lanyuanxiaoyao.service.web.entity.overview; + +/** + * @author lanyuanxiaoyao + * @version 20250509 + */ +public class TableCountVO { + private final String type; + private final Long total; + private final Long focus; + + public TableCountVO(String type, Long total, Long focus) { + this.type = type; + this.total = total; + this.focus = focus; + } + + public String getType() { + return type; + } + + public Long getTotal() { + return total; + } + + public Long getFocus() { + return focus; + } + + @Override + public String toString() { + return "TableCountVO{" + + "type='" + type + '\'' + + ", total=" + total + + ", focus=" + focus + + '}'; + } +} diff --git a/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TaskCountVO.java b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TaskCountVO.java new file mode 100644 index 0000000..f0c1d74 --- /dev/null +++ b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/TaskCountVO.java @@ -0,0 +1,55 @@ +package com.lanyuanxiaoyao.service.web.entity.overview; + +import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias; +import org.eclipse.collections.api.list.ImmutableList; + +/** + * @author lanyuanxiaoyao + * @version 20250509 + */ +public class TaskCountVO { + private final String type; + private final Integer total; + private final Integer running; + private final Integer stopped; + private final ImmutableList list; + + public TaskCountVO(String type, Integer total, Integer running, Integer stopped, ImmutableList list) { + this.type = type; + this.total = total; + this.running = running; + this.stopped = stopped; + this.list = list; + } + + public String getType() { + return type; + } + + public Integer getTotal() { + return total; + } + + public Integer getRunning() { + return running; + } + + public Integer getStopped() { + return stopped; + } + + public ImmutableList getList() { + return list; + } + + @Override + public String toString() { + return "TaskCountVO{" + + "type='" + type + '\'' + + ", total=" + total + + ", running=" + running + + ", stopped=" + stopped + + ", list=" + list + + '}'; + } +} diff --git a/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/VersionCountVO.java b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/VersionCountVO.java new file mode 100644 index 0000000..616d55e --- /dev/null +++ b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/VersionCountVO.java @@ -0,0 +1,45 @@ +package com.lanyuanxiaoyao.service.web.entity.overview; + +/** + * @author lanyuanxiaoyao + * @version 20250509 + */ +public class VersionCountVO { + private final String key; + private final String type; + private final Long unReceive; + private final Long unScheduled; + + public VersionCountVO(String key, String type, Long unReceive, Long unScheduled) { + this.key = key; + this.type = type; + this.unReceive = unReceive; + this.unScheduled = unScheduled; + } + + public String getKey() { + return key; + } + + public String getType() { + return type; + } + + public Long getUnReceive() { + return unReceive; + } + + public Long getUnScheduled() { + return unScheduled; + } + + @Override + public String toString() { + return "VersionCountVO{" + + "key='" + key + '\'' + + ", type='" + type + '\'' + + ", unReceive=" + unReceive + + ", unScheduled=" + unScheduled + + '}'; + } +} diff --git a/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/YarnCountVO.java b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/YarnCountVO.java new file mode 100644 index 0000000..3f0c246 --- /dev/null +++ b/service-web/src/main/java/com/lanyuanxiaoyao/service/web/entity/overview/YarnCountVO.java @@ -0,0 +1,76 @@ +package com.lanyuanxiaoyao.service.web.entity.overview; + +import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue; +import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue; + +/** + * @author lanyuanxiaoyao + * @version 20250509 + */ +public class YarnCountVO { + private final String cluster; + private final Integer total; + private final Integer running; + private final Integer scheduling; + private final Integer failure; + private final YarnRootQueue root; + private final YarnQueue target; + private final Integer queue; + + public YarnCountVO(String cluster, Integer total, Integer running, Integer scheduling, Integer failure, YarnRootQueue root, YarnQueue target, Integer queue) { + this.cluster = cluster; + this.total = total; + this.running = running; + this.scheduling = scheduling; + this.failure = failure; + this.root = root; + this.target = target; + this.queue = queue; + } + + public String getCluster() { + return cluster; + } + + public Integer getTotal() { + return total; + } + + public Integer getRunning() { + return running; + } + + public Integer getScheduling() { + return scheduling; + } + + public Integer getFailure() { + return failure; + } + + public YarnRootQueue getRoot() { + return root; + } + + public YarnQueue getTarget() { + return target; + } + + public Integer getQueue() { + return queue; + } + + @Override + public String toString() { + return "YarnCountVO{" + + "cluster='" + cluster + '\'' + + ", total=" + total + + ", running=" + running + + ", scheduling=" + scheduling + + ", failure=" + failure + + ", root=" + root + + ", target=" + target + + ", queue=" + queue + + '}'; + } +}