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.JobAndMetas;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
||||||
import java.util.Map;
|
|
||||||
import org.eclipse.collections.api.list.ImmutableList;
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Info 接口
|
* Info 接口
|
||||||
*
|
*
|
||||||
@@ -21,6 +22,30 @@ import org.eclipse.collections.api.list.ImmutableList;
|
|||||||
*/
|
*/
|
||||||
@BaseRequest(baseURL = "http://service-info-query/info")
|
@BaseRequest(baseURL = "http://service-info-query/info")
|
||||||
public interface InfoService {
|
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")
|
@Get("/job_id_alias")
|
||||||
PageResponse<JobIdAndAlias> jobIdAndAlias(@Query Map<String, Object> queryMap);
|
PageResponse<JobIdAndAlias> jobIdAndAlias(@Query Map<String, Object> queryMap);
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,7 @@ public interface QueueService {
|
|||||||
|
|
||||||
@Get("/all/{name}")
|
@Get("/all/{name}")
|
||||||
ImmutableList<QueueItem<ScheduleJob>> all(@Var("name") String 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.JobIdAndAlias;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
||||||
import com.lanyuanxiaoyao.service.info.service.InfoService;
|
import com.lanyuanxiaoyao.service.info.service.InfoService;
|
||||||
import java.util.List;
|
|
||||||
import org.eclipse.collections.api.factory.Lists;
|
import org.eclipse.collections.api.factory.Lists;
|
||||||
import org.eclipse.collections.api.list.ImmutableList;
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
import org.slf4j.Logger;
|
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.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 信息接口
|
* 信息接口
|
||||||
*
|
*
|
||||||
@@ -36,6 +37,26 @@ public class InfoController {
|
|||||||
this.infoService = infoService;
|
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")
|
@GetMapping("/job_id_alias")
|
||||||
public PageResponse<JobIdAndAlias> jobIdAndAlias(
|
public PageResponse<JobIdAndAlias> jobIdAndAlias(
|
||||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||||
@@ -123,4 +144,24 @@ public class InfoController {
|
|||||||
public ImmutableList<String> updatedVersionTables() {
|
public ImmutableList<String> updatedVersionTables() {
|
||||||
return infoService.nonUpdatedVersionTables();
|
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.JobAndMetas;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||||
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
|
||||||
import java.util.List;
|
|
||||||
import org.eclipse.collections.api.factory.Lists;
|
import org.eclipse.collections.api.factory.Lists;
|
||||||
import org.eclipse.collections.api.list.ImmutableList;
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
import org.eclipse.collections.api.map.ImmutableMap;
|
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.stereotype.Service;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static com.eshore.odcp.hudi.connector.Constants.DATABASE_NAME;
|
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 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_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_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 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 final String TABLE_SYNC_STATE_ID = column(TABLE_SYNC_STATE, "id");
|
||||||
@@ -247,6 +250,7 @@ public class InfoService {
|
|||||||
.join(TABLE_VERSION)
|
.join(TABLE_VERSION)
|
||||||
.onEq(TABLE_INFO_FLINK_JOB_ID, Column.as(TABLE_VERSION_FLINK_JOB_ID))
|
.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_ALIAS, Column.as(TABLE_VERSION_ALIAS))
|
||||||
|
.andEq(TABLE_INFO_STATUS, "y")
|
||||||
.join(TABLE_SYNC_STATE)
|
.join(TABLE_SYNC_STATE)
|
||||||
.on(StrUtil.format("{} = CONCAT({}, '-', {})", TABLE_SYNC_STATE_ID, TABLE_INFO_FLINK_JOB_ID, TABLE_INFO_ALIAS))
|
.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)
|
.whereLike(ObjectUtil.isNotNull(flinkJobId), TABLE_INFO_FLINK_JOB_ID, flinkJobId)
|
||||||
@@ -338,4 +342,120 @@ public class InfoService {
|
|||||||
.withMetadata("unScheduled", scheduleCount.getOrDefault(false, 0));
|
.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.SqlBuilder;
|
||||||
import club.kingon.sql.builder.entry.Alias;
|
import club.kingon.sql.builder.entry.Alias;
|
||||||
import club.kingon.sql.builder.entry.Column;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.db.sql.SqlFormatter;
|
import cn.hutool.db.sql.SqlFormatter;
|
||||||
import org.eclipse.collections.api.factory.Lists;
|
|
||||||
|
|
||||||
import static com.eshore.odcp.hudi.connector.Constants.DATABASE_NAME;
|
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
|
* @date 2023-06-07
|
||||||
*/
|
*/
|
||||||
public class SqlBuilderTests {
|
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 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 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) {
|
private static String column(Alias table, String column) {
|
||||||
return StrUtil.format("{}.{}", table.getAlias(), column);
|
return StrUtil.format("{}.{}", table.getAlias(), column);
|
||||||
@@ -21,15 +32,15 @@ public class SqlBuilderTests {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
System.out.println(SqlFormatter.format(
|
System.out.println(SqlFormatter.format(
|
||||||
SqlBuilder
|
SqlBuilder.select(COUNT)
|
||||||
.select("count(*)")
|
|
||||||
.from(TABLE_INFO)
|
.from(TABLE_INFO)
|
||||||
.join(TABLE_VERSION)
|
.whereGe(TABLE_INFO_PRIORITY, 10000)
|
||||||
.onEq(column(TABLE_INFO, "flink_job_id"), Column.as(column(TABLE_VERSION, "flink_job_id")))
|
.andNotIn(
|
||||||
.andEq(column(TABLE_INFO, "alias"), Column.as(column(TABLE_VERSION, "alias")))
|
StrUtil.format("concat({}, {})", TABLE_INFO_FLINK_JOB_ID, TABLE_INFO_ALIAS),
|
||||||
.whereEq(false, "a", "b")
|
SqlBuilder.select(StrUtil.format("concat({}, {})", TABLE_VERSION_FLINK_JOB_ID, TABLE_VERSION_ALIAS))
|
||||||
.andEq("b", "c")
|
.from(TABLE_VERSION)
|
||||||
.andIn("d", Lists.immutable.empty())
|
.whereEq(TABLE_VERSION_VERSION, "20230611")
|
||||||
|
)
|
||||||
.build()
|
.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/running-tab.js"></script>
|
||||||
<script src="components/log-tab.js"></script>
|
<script src="components/log-tab.js"></script>
|
||||||
<script src="components/version-tab.js"></script>
|
<script src="components/version-tab.js"></script>
|
||||||
|
<script src="components/overview-tab.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function () {
|
(function () {
|
||||||
let amis = amisRequire('amis/embed')
|
let amis = amisRequire('amis/embed')
|
||||||
@@ -58,6 +59,7 @@
|
|||||||
tabs: [
|
tabs: [
|
||||||
// logTab(),
|
// logTab(),
|
||||||
// runningTab(),
|
// runningTab(),
|
||||||
|
overviewTab(),
|
||||||
tableTab(),
|
tableTab(),
|
||||||
queueTab(),
|
queueTab(),
|
||||||
versionTab(),
|
versionTab(),
|
||||||
|
|||||||
Reference in New Issue
Block a user