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 +
+ '}';
+ }
+}