feature(web): 增加 Overview 页面
方便总览全局情况,跨页面查看信息多有不便
This commit is contained in:
@@ -10,9 +10,10 @@ import com.lanyuanxiaoyao.service.configuration.entity.PageResponse;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobAndMetas;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
||||
import java.util.Map;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Info 接口
|
||||
*
|
||||
@@ -21,6 +22,30 @@ import org.eclipse.collections.api.list.ImmutableList;
|
||||
*/
|
||||
@BaseRequest(baseURL = "http://service-info-query/info")
|
||||
public interface InfoService {
|
||||
@Get("/table_total")
|
||||
Long tableTotal();
|
||||
|
||||
@Get("/hudi_total")
|
||||
Long hudiTotal();
|
||||
|
||||
@Get("/focus_count")
|
||||
Long focusCount();
|
||||
|
||||
@Get("/normal_count")
|
||||
Long normalCount();
|
||||
|
||||
@Get("/un_scheduled_normal_table_count")
|
||||
Long unScheduledNormalTableCount(@Query("version") String version);
|
||||
|
||||
@Get("/un_scheduled_focus_table_count")
|
||||
Long unScheduledFocusTableCount(@Query("version") String version);
|
||||
|
||||
@Get("/un_receive_version_normal_table_count")
|
||||
Long unReceiveVersionNormalTableCount(@Query("version") String version);
|
||||
|
||||
@Get("/un_receive_version_focus_table_count")
|
||||
Long unReceiveVersionFocusTableCount(@Query("version") String version);
|
||||
|
||||
@Get("/job_id_alias")
|
||||
PageResponse<JobIdAndAlias> jobIdAndAlias(@Query Map<String, Object> queryMap);
|
||||
|
||||
|
||||
@@ -20,4 +20,7 @@ public interface QueueService {
|
||||
|
||||
@Get("/all/{name}")
|
||||
ImmutableList<QueueItem<ScheduleJob>> all(@Var("name") String name);
|
||||
|
||||
@Get("/size/{name}")
|
||||
Integer size(@Var("name") String name);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.lanyuanxiaoyao.service.configuration.entity.info.JobAndMetas;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
||||
import com.lanyuanxiaoyao.service.info.service.InfoService;
|
||||
import java.util.List;
|
||||
import org.eclipse.collections.api.factory.Lists;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
@@ -19,6 +18,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 信息接口
|
||||
*
|
||||
@@ -36,6 +37,26 @@ public class InfoController {
|
||||
this.infoService = infoService;
|
||||
}
|
||||
|
||||
@GetMapping("table_total")
|
||||
public Long tableTotal() {
|
||||
return infoService.tableTotal();
|
||||
}
|
||||
|
||||
@GetMapping("hudi_total")
|
||||
public Long hudiTotal() {
|
||||
return infoService.hudiTotal();
|
||||
}
|
||||
|
||||
@GetMapping("focus_count")
|
||||
public Long focusCount() {
|
||||
return infoService.focusCount();
|
||||
}
|
||||
|
||||
@GetMapping("normal_count")
|
||||
public Long normalCount() {
|
||||
return infoService.normalCount();
|
||||
}
|
||||
|
||||
@GetMapping("/job_id_alias")
|
||||
public PageResponse<JobIdAndAlias> jobIdAndAlias(
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@@ -123,4 +144,24 @@ public class InfoController {
|
||||
public ImmutableList<String> updatedVersionTables() {
|
||||
return infoService.nonUpdatedVersionTables();
|
||||
}
|
||||
|
||||
@GetMapping("/un_scheduled_normal_table_count")
|
||||
public Long unScheduledNormalTableCount(@RequestParam("version") String version) {
|
||||
return infoService.unScheduledNormalTableCount(version);
|
||||
}
|
||||
|
||||
@GetMapping("/un_scheduled_focus_table_count")
|
||||
public Long unScheduledFocusTableCount(@RequestParam("version") String version) {
|
||||
return infoService.unScheduledFocusTableCount(version);
|
||||
}
|
||||
|
||||
@GetMapping("/un_receive_version_normal_table_count")
|
||||
public Long unReceiveVersionNormalTableCount(@RequestParam("version") String version) {
|
||||
return infoService.unReceiveVersionNormalTableCount(version);
|
||||
}
|
||||
|
||||
@GetMapping("/un_receive_version_focus_table_count")
|
||||
public Long unReceiveVersionFocusTableCount(@RequestParam("version") String version) {
|
||||
return infoService.unReceiveVersionFocusTableCount(version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import com.lanyuanxiaoyao.service.configuration.entity.PageResponse;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobAndMetas;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
||||
import java.util.List;
|
||||
import org.eclipse.collections.api.factory.Lists;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
import org.eclipse.collections.api.map.ImmutableMap;
|
||||
@@ -29,6 +28,8 @@ import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.eshore.odcp.hudi.connector.Constants.DATABASE_NAME;
|
||||
|
||||
/**
|
||||
@@ -224,6 +225,8 @@ public class InfoService {
|
||||
private static final Alias TABLE_INFO = Alias.of(StrUtil.format("{}.tb_app_collect_table_info", DATABASE_NAME), "tacti");
|
||||
private static final String TABLE_INFO_FLINK_JOB_ID = column(TABLE_INFO, "flink_job_id");
|
||||
private static final String TABLE_INFO_ALIAS = column(TABLE_INFO, "alias");
|
||||
private static final String TABLE_INFO_PRIORITY = column(TABLE_INFO, "priority");
|
||||
private static final String TABLE_INFO_STATUS = column(TABLE_INFO, "status");
|
||||
|
||||
private static final Alias TABLE_SYNC_STATE = Alias.of(StrUtil.format("{}.tb_app_hudi_sync_state", DATABASE_NAME), "tahss");
|
||||
private static final String TABLE_SYNC_STATE_ID = column(TABLE_SYNC_STATE, "id");
|
||||
@@ -247,6 +250,7 @@ public class InfoService {
|
||||
.join(TABLE_VERSION)
|
||||
.onEq(TABLE_INFO_FLINK_JOB_ID, Column.as(TABLE_VERSION_FLINK_JOB_ID))
|
||||
.andEq(TABLE_INFO_ALIAS, Column.as(TABLE_VERSION_ALIAS))
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.join(TABLE_SYNC_STATE)
|
||||
.on(StrUtil.format("{} = CONCAT({}, '-', {})", TABLE_SYNC_STATE_ID, TABLE_INFO_FLINK_JOB_ID, TABLE_INFO_ALIAS))
|
||||
.whereLike(ObjectUtil.isNotNull(flinkJobId), TABLE_INFO_FLINK_JOB_ID, flinkJobId)
|
||||
@@ -338,4 +342,120 @@ public class InfoService {
|
||||
.withMetadata("unScheduled", scheduleCount.getOrDefault(false, 0));
|
||||
});
|
||||
}
|
||||
|
||||
@Cacheable(value = "un-receive-version-normal-table-count", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long unReceiveVersionNormalTableCount(String version) {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select(COUNT)
|
||||
.from(TABLE_INFO)
|
||||
.whereLt(TABLE_INFO_PRIORITY, 10000)
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.andNotIn(
|
||||
StrUtil.format("concat({}, {})", TABLE_INFO_FLINK_JOB_ID, TABLE_INFO_ALIAS),
|
||||
SqlBuilder.select(StrUtil.format("concat({}, {})", TABLE_VERSION_FLINK_JOB_ID, TABLE_VERSION_ALIAS))
|
||||
.from(TABLE_VERSION)
|
||||
.whereEq(TABLE_VERSION_VERSION, version)
|
||||
)
|
||||
.build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "un-receive-version-focus-table-count", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long unReceiveVersionFocusTableCount(String version) {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select(COUNT)
|
||||
.from(TABLE_INFO)
|
||||
.whereGe(TABLE_INFO_PRIORITY, 10000)
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.andNotIn(
|
||||
StrUtil.format("concat({}, {})", TABLE_INFO_FLINK_JOB_ID, TABLE_INFO_ALIAS),
|
||||
SqlBuilder.select(StrUtil.format("concat({}, {})", TABLE_VERSION_FLINK_JOB_ID, TABLE_VERSION_ALIAS))
|
||||
.from(TABLE_VERSION)
|
||||
.whereEq(TABLE_VERSION_VERSION, version)
|
||||
)
|
||||
.build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "un_scheduled_normal_table_count", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long unScheduledNormalTableCount(String version) {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select(COUNT)
|
||||
.from(TABLE_INFO)
|
||||
.join(TABLE_VERSION)
|
||||
.onEq(TABLE_INFO_FLINK_JOB_ID, Column.as(TABLE_VERSION_FLINK_JOB_ID))
|
||||
.andEq(TABLE_INFO_ALIAS, Column.as(TABLE_VERSION_ALIAS))
|
||||
.whereLt(TABLE_INFO_PRIORITY, 10000)
|
||||
.andEq(TABLE_VERSION_VERSION, version)
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "un_scheduled_focus_table_count", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long unScheduledFocusTableCount(String version) {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select(COUNT)
|
||||
.from(TABLE_INFO)
|
||||
.join(TABLE_VERSION)
|
||||
.onEq(TABLE_INFO_FLINK_JOB_ID, Column.as(TABLE_VERSION_FLINK_JOB_ID))
|
||||
.andEq(TABLE_INFO_ALIAS, Column.as(TABLE_VERSION_ALIAS))
|
||||
.whereGe(TABLE_INFO_PRIORITY, 10000)
|
||||
.andEq(TABLE_VERSION_VERSION, version)
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "table-total", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long tableTotal() {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select("count(distinct concat(src_schema, src_table))").from(TABLE_INFO).whereEq(TABLE_INFO_STATUS, "y").build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "hudi-total", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long hudiTotal() {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select("count(distinct tgt_hdfs_path) as count").from(TABLE_INFO).whereEq(TABLE_INFO_STATUS, "y").build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "focus-count", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long focusCount() {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select("count(distinct concat(src_schema, src_table))")
|
||||
.from(TABLE_INFO)
|
||||
.whereGe(TABLE_INFO_PRIORITY, 1000)
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
|
||||
@Cacheable(value = "normal-count", sync = true)
|
||||
@Retryable(Throwable.class)
|
||||
public Long normalCount() {
|
||||
return mysqlJdbcTemplate.queryForObject(
|
||||
SqlBuilder.select("count(distinct concat(src_schema, src_table))")
|
||||
.from(TABLE_INFO)
|
||||
.whereLt(TABLE_INFO_PRIORITY, 1000)
|
||||
.andEq(TABLE_INFO_STATUS, "y")
|
||||
.build(),
|
||||
Long.class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import club.kingon.sql.builder.SqlBuilder;
|
||||
import club.kingon.sql.builder.entry.Alias;
|
||||
import club.kingon.sql.builder.entry.Column;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.db.sql.SqlFormatter;
|
||||
import org.eclipse.collections.api.factory.Lists;
|
||||
|
||||
import static com.eshore.odcp.hudi.connector.Constants.DATABASE_NAME;
|
||||
|
||||
@@ -12,8 +10,21 @@ import static com.eshore.odcp.hudi.connector.Constants.DATABASE_NAME;
|
||||
* @date 2023-06-07
|
||||
*/
|
||||
public class SqlBuilderTests {
|
||||
private static final String COUNT = "count(*)";
|
||||
|
||||
private static final Alias TABLE_VERSION = Alias.of(StrUtil.format("{}.tb_app_collect_table_version", DATABASE_NAME), "tactv");
|
||||
private static final String TABLE_VERSION_FLINK_JOB_ID = column(TABLE_VERSION, "flink_job_id");
|
||||
private static final String TABLE_VERSION_ALIAS = column(TABLE_VERSION, "alias");
|
||||
private static final String TABLE_VERSION_VERSION = column(TABLE_VERSION, "version");
|
||||
private static final String TABLE_VERSION_SCHEDULED = column(TABLE_VERSION, "scheduled");
|
||||
|
||||
private static final Alias TABLE_INFO = Alias.of(StrUtil.format("{}.tb_app_collect_table_info", DATABASE_NAME), "tacti");
|
||||
private static final String TABLE_INFO_FLINK_JOB_ID = column(TABLE_INFO, "flink_job_id");
|
||||
private static final String TABLE_INFO_ALIAS = column(TABLE_INFO, "alias");
|
||||
private static final String TABLE_INFO_PRIORITY = column(TABLE_INFO, "priority");
|
||||
|
||||
private static final Alias TABLE_SYNC_STATE = Alias.of(StrUtil.format("{}.tb_app_hudi_sync_state", DATABASE_NAME), "tahss");
|
||||
private static final String TABLE_SYNC_STATE_ID = column(TABLE_SYNC_STATE, "id");
|
||||
|
||||
private static String column(Alias table, String column) {
|
||||
return StrUtil.format("{}.{}", table.getAlias(), column);
|
||||
@@ -21,15 +32,15 @@ public class SqlBuilderTests {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(SqlFormatter.format(
|
||||
SqlBuilder
|
||||
.select("count(*)")
|
||||
SqlBuilder.select(COUNT)
|
||||
.from(TABLE_INFO)
|
||||
.join(TABLE_VERSION)
|
||||
.onEq(column(TABLE_INFO, "flink_job_id"), Column.as(column(TABLE_VERSION, "flink_job_id")))
|
||||
.andEq(column(TABLE_INFO, "alias"), Column.as(column(TABLE_VERSION, "alias")))
|
||||
.whereEq(false, "a", "b")
|
||||
.andEq("b", "c")
|
||||
.andIn("d", Lists.immutable.empty())
|
||||
.whereGe(TABLE_INFO_PRIORITY, 10000)
|
||||
.andNotIn(
|
||||
StrUtil.format("concat({}, {})", TABLE_INFO_FLINK_JOB_ID, TABLE_INFO_ALIAS),
|
||||
SqlBuilder.select(StrUtil.format("concat({}, {})", TABLE_VERSION_FLINK_JOB_ID, TABLE_VERSION_ALIAS))
|
||||
.from(TABLE_VERSION)
|
||||
.whereEq(TABLE_VERSION_VERSION, "20230611")
|
||||
)
|
||||
.build()
|
||||
));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.lanyuanxiaoyao.service.web.controller;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.service.configuration.ExecutorProvider;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.AmisResponse;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnApplication;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue;
|
||||
import com.lanyuanxiaoyao.service.forest.service.InfoService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.QueueService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.YarnService;
|
||||
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.map.ImmutableMap;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* 概览
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @date 2023-06-12
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("overview")
|
||||
public class OverviewController extends BaseController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OverviewController.class);
|
||||
|
||||
private final InfoService infoService;
|
||||
private final YarnService yarnService;
|
||||
private final QueueService queueService;
|
||||
|
||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||
public OverviewController(InfoService infoService, YarnService yarnService, QueueService queueService) {
|
||||
this.infoService = infoService;
|
||||
this.yarnService = yarnService;
|
||||
this.queueService = queueService;
|
||||
}
|
||||
|
||||
@GetMapping("")
|
||||
public AmisResponse overview() throws ExecutionException, InterruptedException {
|
||||
CompletableFuture<Long> tableTotalFuture = CompletableFuture.supplyAsync(infoService::tableTotal, ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> hudiTotalFuture = CompletableFuture.supplyAsync(infoService::hudiTotal, ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> focusCountFuture = CompletableFuture.supplyAsync(infoService::focusCount, ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> normalCountFuture = CompletableFuture.supplyAsync(infoService::normalCount, ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture.allOf(
|
||||
tableTotalFuture,
|
||||
hudiTotalFuture,
|
||||
focusCountFuture,
|
||||
normalCountFuture
|
||||
);
|
||||
return responseData()
|
||||
.withData("table_total", tableTotalFuture.get())
|
||||
.withData("hudi_total", hudiTotalFuture.get())
|
||||
.withData("focus_count", focusCountFuture.get())
|
||||
.withData("normal_count", normalCountFuture.get());
|
||||
}
|
||||
|
||||
@GetMapping("yarn-job")
|
||||
private ImmutableMap<String, Object> yarnOverview(@RequestParam("cluster") String cluster, @RequestParam("search") String text) {
|
||||
boolean isSearch = StrUtil.isNotBlank(text);
|
||||
ImmutableList<YarnApplication> applications = yarnService.jobList(cluster).select(app -> !isSearch || StrUtil.contains(app.getName(), text));
|
||||
return Maps.immutable.ofAll(MapUtil.<String, Object>builder()
|
||||
.put("name", cluster)
|
||||
.put("total", applications.size())
|
||||
.put("running", applications.count(app -> StrUtil.equals(app.getState(), "RUNNING")))
|
||||
.put("scheduling", applications.count(app -> StrUtil.equals(app.getState(), "ACCEPTED")))
|
||||
.put("failure", applications.count(app -> StrUtil.equals(app.getState(), "FAILED")))
|
||||
.build());
|
||||
}
|
||||
|
||||
@GetMapping("yarn")
|
||||
public AmisResponse yarnOverview(@RequestParam("clusters") List<String> clusters, @RequestParam("search") String text) {
|
||||
ImmutableList<ImmutableMap<String, Object>> maps = Lists.immutable.ofAll(clusters)
|
||||
.asParallel(ExecutorProvider.EXECUTORS, 1)
|
||||
.collect(cluster -> yarnOverview(cluster, text))
|
||||
.toList()
|
||||
.toImmutable();
|
||||
long total = maps.sumOfInt(m -> (int) m.get("total"));
|
||||
long running = maps.sumOfInt(m -> (int) m.get("running"));
|
||||
long scheduling = maps.sumOfInt(m -> (int) m.get("scheduling"));
|
||||
long failure = maps.sumOfInt(m -> (int) m.get("failure"));
|
||||
return responseData()
|
||||
.withData("total", total)
|
||||
.withData("running", running)
|
||||
.withData("scheduling", scheduling)
|
||||
.withData("failure", failure)
|
||||
.withData("items", maps);
|
||||
}
|
||||
|
||||
@GetMapping("yarn-cluster")
|
||||
public AmisResponse yarnClusterOverview(@RequestParam("cluster") String cluster, @RequestParam("queue") String queue) {
|
||||
AmisResponse response = responseData();
|
||||
YarnRootQueue root = yarnService.cluster(cluster);
|
||||
response.withData("root", root);
|
||||
if (StrUtil.isNotBlank(queue)) {
|
||||
yarnService.queueList(cluster)
|
||||
.select(q -> StrUtil.equals(q.getQueueName(), queue))
|
||||
.getFirstOptional()
|
||||
.ifPresent(yarnQueue -> response.withData("target", yarnQueue));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@GetMapping("queue")
|
||||
public AmisResponse queueOverview(@RequestParam("queue") String queue) {
|
||||
return responseData()
|
||||
.withData("size", queueService.size(queue));
|
||||
}
|
||||
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
|
||||
@GetMapping("version")
|
||||
public AmisResponse versionOverview() throws ExecutionException, InterruptedException {
|
||||
String version = LocalDateTime.now().minusDays(1).format(FORMATTER);
|
||||
CompletableFuture<Long> unReceiveNormalTableCount = CompletableFuture.supplyAsync(() -> infoService.unReceiveVersionNormalTableCount(version), ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> unReceiveFocusCount = CompletableFuture.supplyAsync(() -> infoService.unReceiveVersionFocusTableCount(version), ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> unScheduledNormalTableCount = CompletableFuture.supplyAsync(() -> infoService.unScheduledNormalTableCount(version), ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> unScheduledFocusTableCount = CompletableFuture.supplyAsync(() -> infoService.unScheduledFocusTableCount(version), ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture.allOf(unReceiveNormalTableCount, unReceiveFocusCount, unScheduledNormalTableCount, unScheduledFocusTableCount);
|
||||
return responseData()
|
||||
.withData("version", version)
|
||||
.withData("unReceive", Maps.immutable.of("normal", unReceiveNormalTableCount.get(), "focus", unReceiveFocusCount.get()))
|
||||
.withData("unSchedule", Maps.immutable.of("normal", unScheduledNormalTableCount.get(), "focus", unScheduledFocusTableCount.get()));
|
||||
}
|
||||
}
|
||||
198
web/components/overview-tab.js
Normal file
198
web/components/overview-tab.js
Normal file
@@ -0,0 +1,198 @@
|
||||
function overviewYarnJob(cluster, search, queue, yarnQueue) {
|
||||
return {
|
||||
className: 'font-mono',
|
||||
type: 'service',
|
||||
api: `\${base}/overview/yarn-job?cluster=${cluster}&search=${search}`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'mr-1 font-bold',
|
||||
tpl: `${cluster}`,
|
||||
},
|
||||
queue === undefined ? {} : {
|
||||
type: 'service',
|
||||
className: 'inline ml-2',
|
||||
api: `\${base}/overview/queue?queue=compaction-queue-${cluster}`,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${PADSTART(size, 2)}',
|
||||
}
|
||||
]
|
||||
},
|
||||
overviewYarnCluster(cluster, yarnQueue),
|
||||
'(',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold">${PADSTART(total, 3)}</span>',
|
||||
},
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-cyan-300">${PADSTART(scheduling, 3)}</span>',
|
||||
},
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-success">${PADSTART(running, 3)}</span>',
|
||||
},
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-danger">${PADSTART(failure, 3)}</span>',
|
||||
},
|
||||
')',
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function color(number) {
|
||||
let color = 'text-success'
|
||||
if (number > 30) {
|
||||
color = 'text-primary'
|
||||
}
|
||||
if (number > 80) {
|
||||
color = 'text-danger'
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
function overviewYarnCluster(cluster, queue) {
|
||||
return {
|
||||
type: 'service',
|
||||
className: 'inline',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `\${base}/overview/yarn-cluster`,
|
||||
data: {
|
||||
cluster: cluster,
|
||||
queue: queue,
|
||||
},
|
||||
adaptor: function (payload, response) {
|
||||
let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity']).toFixed(0)
|
||||
let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity']).toFixed(0)
|
||||
return {
|
||||
...payload,
|
||||
data: {
|
||||
...payload.data,
|
||||
rootUsed: rootUsed,
|
||||
rootUsedColor: color(rootUsed),
|
||||
targetUsed: targetUsed,
|
||||
targetUsedColor: color(targetUsed),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
'(',
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'font-bold',
|
||||
tpl: '<span class="font-bold ${rootUsedColor}">${PADSTART(ROUND(rootUsed), 3)}%</span>',
|
||||
},
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold ${targetUsedColor}">${PADSTART(ROUND(targetUsed), 3)}%</span>',
|
||||
},
|
||||
')'
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
function overviewTab() {
|
||||
return {
|
||||
title: '概览',
|
||||
tab: [
|
||||
{
|
||||
type: 'service',
|
||||
// language=JavaScript
|
||||
dataProvider: 'const timer = setInterval(() => {\n setData({date: new Date().toLocaleString()})\n}, 1000)\nreturn () => {\n clearInterval(timer)\n}',
|
||||
body: [
|
||||
'当前时间:',
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'font-bold',
|
||||
tpl: '${date}'
|
||||
}
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/overview',
|
||||
interval: 60000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '逻辑表:<span class="font-bold mr-1">${table_total}</span>',
|
||||
},
|
||||
'<br>',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: 'Hudi表:<span class="font-bold mr-1">${hudi_total}</span>',
|
||||
},
|
||||
'<br>',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '重点表:<span class="font-bold mr-1">${focus_count}</span>',
|
||||
},
|
||||
'<br>',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '普通表:<span class="font-bold">${normal_count}</span>',
|
||||
},
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
overviewYarnJob('b5-sync', 'Sync', undefined, 'default'),
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: `\${base}/overview/queue?queue=compaction-queue-pre`,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: 'Pre:<span class="font-bold">${size}</span>',
|
||||
}
|
||||
]
|
||||
},
|
||||
'<span class="italic text-gray-500 my-2">集群 压缩队列任务数(集群总资源使用,队列资源使用)(总压缩任务数,调度中任务数,运行中任务数,失败任务数)</span>',
|
||||
overviewYarnJob('b1', 'Compaction', 'compaction-queue-b1', 'datalake'),
|
||||
overviewYarnJob('b5', 'Compaction', 'compaction-queue-b5', 'ten_iap.datalake'),
|
||||
overviewYarnJob('a4', 'Compaction', 'compaction-queue-a4', 'ten_iap.datalake'),
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/overview/version',
|
||||
body: [
|
||||
'版本:',
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'font-bold',
|
||||
tpl: '${version}',
|
||||
},
|
||||
'<br/>',
|
||||
'<span class="italic text-gray-500 my-2">未接收,未跨天</span>',
|
||||
'<br/>',
|
||||
'重点表:',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold font-mono">${PADSTART(unReceive.focus, 3)},${PADSTART(unSchedule.focus, 3)}</span>',
|
||||
},
|
||||
'<br/>',
|
||||
'普通表:',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold font-mono">${PADSTART(unReceive.normal, 3)},${PADSTART(unSchedule.normal, 3)}</span>',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@
|
||||
<script src="components/running-tab.js"></script>
|
||||
<script src="components/log-tab.js"></script>
|
||||
<script src="components/version-tab.js"></script>
|
||||
<script src="components/overview-tab.js"></script>
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
let amis = amisRequire('amis/embed')
|
||||
@@ -58,6 +59,7 @@
|
||||
tabs: [
|
||||
// logTab(),
|
||||
// runningTab(),
|
||||
overviewTab(),
|
||||
tableTab(),
|
||||
queueTab(),
|
||||
versionTab(),
|
||||
|
||||
Reference in New Issue
Block a user