Compare commits

...

73 Commits

Author SHA1 Message Date
EricZeng
045f65204b Merge pull request #633 from didi/master
合并主分支
2022-09-29 13:09:19 +08:00
EricZeng
f414b47a78 1、补充升级至v3.0.0信息;2、增加v3.0.0变更内容;(#636)
1、补充升级至v3.0.0信息;2、增加v3.0.0变更内容;(#)
2022-09-29 13:08:32 +08:00
EricZeng
44f4e2f0f9 Merge pull request #635 from didi/dev
合并前端调整的内容
2022-09-29 11:50:25 +08:00
zengqiao
2361008bdf Merge branch 'dev' of github.com:didi/KnowStreaming into dev 2022-09-29 11:49:00 +08:00
zengqiao
7377ef3ec5 增加v3.0.0变更内容 2022-09-29 11:45:29 +08:00
lucasun
a28d064b7a Merge pull request #634 from GraceWalk/dev
前端 bug 修复 & 问题优化
2022-09-29 11:23:25 +08:00
GraceWalk
e2e57e8575 fix: 依赖版本更新 2022-09-29 11:15:47 +08:00
zengqiao
9d90bd2835 补充升级至v3.0.0信息 2022-09-29 11:04:49 +08:00
EricZeng
7445e68df4 Merge pull request #632 from didi/master
合并主分支
2022-09-29 10:53:54 +08:00
GraceWalk
ab42625ad2 fix: 数字展示格式化 2022-09-29 10:52:31 +08:00
GraceWalk
18789a0a53 fix: IconFont 组件改为从独立包引入 2022-09-29 10:51:52 +08:00
zengqiao
68a37bb56a Merge branch 'master' of github.com:didi/KnowStreaming 2022-09-29 10:49:46 +08:00
GraceWalk
3b33652c47 fix: Rebalance 卡片 icon 颜色调整 2022-09-29 10:48:52 +08:00
GraceWalk
1e0c4c3904 feat: Topic 详情消息 Value 列支持复制 2022-09-29 10:48:09 +08:00
zengqiao
04e223de16 修改协议文案 2022-09-29 10:48:00 +08:00
GraceWalk
c4a691aa8a fix: 多集群列表兼容集群无 ZK 情况 2022-09-29 10:44:28 +08:00
GraceWalk
ff9dde163a feat: 图表支持存储拖拽排序 & 补点逻辑优化 2022-09-29 10:42:44 +08:00
EricZeng
eb7efbd1a5 增加字段校验注解(#631)
增加字段校验注解(#631)
2022-09-29 09:59:02 +08:00
zengqiao
8c8c362c54 Merge branch 'dev' of github.com:didi/KnowStreaming into dev 2022-09-28 20:19:35 +08:00
zengqiao
66e119ad5d 增加字段校验注解 2022-09-28 20:16:06 +08:00
EricZeng
6dedc04a05 Merge pull request #630 from didi/dev
合并开发分支
2022-09-28 20:14:51 +08:00
EricZeng
0cf8bad0df Merge pull request #629 from didi/master
合并主分支
2022-09-28 20:06:26 +08:00
zengqiao
95c9582d8b 优化消费组详情指标为实时获取 2022-09-28 20:03:23 +08:00
EricZeng
7815126ff5 1、修复Group指标防重复不生效问题;2、修复自动创建ES索引模版失败问题; (#628)
* 修复自动创建ES索引模版失败问题

* 修复Group指标防重复不生效问题

Co-authored-by: zengqiao <zengqiao@didiglobal.com>
2022-09-28 19:55:30 +08:00
zengqiao
a5fa9de54b 修复Group指标防重复不生效问题 2022-09-28 19:52:11 +08:00
zengqiao
95f1a2c630 修复自动创建ES索引模版失败问题 2022-09-28 19:46:07 +08:00
zengqiao
1e256ae1fd 修复自动创建ES索引模版失败问题 2022-09-28 19:44:33 +08:00
zengqiao
9fc9c54fa1 bump version to 3.0.0 2022-09-28 11:20:16 +08:00
zengqiao
1b362b1e02 Merge branch 'master' of github.com:didi/KnowStreaming 2022-09-28 11:16:54 +08:00
EricZeng
04e3172cca [ISSUE-624]过滤掉不存在的Topic(#625)
[ISSUE-624]过滤掉不存在的Topic(#625)
2022-09-28 11:13:15 +08:00
EricZeng
1caab7f3f7 [ISSUE-624]过滤掉不存在的Topic(#624)
[ISSUE-624]过滤掉不存在的Topic(#624)
2022-09-28 10:41:39 +08:00
zengqiao
9d33c725ad [ISSUE-624]过滤掉不存在的Topic(#624)
同步Group元信息时,如果Topic已经不存在了,则过滤掉该Group+Topic信息
2022-09-28 10:39:33 +08:00
EricZeng
6ed1d38106 [ISSUE-598]Fix start_time not set when create reassign job in MySQL-8 (#623)
[ISSUE-598]Fix start_time not set when create reassign job in MySQL-8 (#623 )
2022-09-28 10:26:56 +08:00
zengqiao
0f07ddedaf [ISSUE-598]Fix start_time not set when create reassign job in MySQL-8 2022-09-28 10:24:32 +08:00
EricZeng
289945b471 Merge pull request #622 from didi/dev
后端补充Kafka集群运行模式字段信息
2022-09-28 10:08:17 +08:00
zengqiao
f331a6d144 后端补充Kafka集群运行模式字段信息 2022-09-27 18:43:22 +08:00
EricZeng
0c8c12a651 Merge pull request #621 from didi/dev
指标发送ES类按照指标类别拆分
2022-09-27 18:38:05 +08:00
zengqiao
028c3bb2fa 指标发送ES类按照指标类别拆分 2022-09-27 10:19:18 +08:00
EricZeng
d7a5a0d405 健康巡检任务按照类型进行拆分
健康巡检任务按照类型进行拆分
2022-09-27 10:17:12 +08:00
zengqiao
5ef5f6e531 健康巡检任务按照类型进行拆分 2022-09-26 20:10:49 +08:00
EricZeng
1d205734b3 Merge pull request #619 from didi/dev
集群信息中,补充ZK配置字段
2022-09-26 19:50:26 +08:00
Peng
5edd43884f Update README.md 2022-09-26 18:43:25 +08:00
zengqiao
c1992373bc 集群信息中,补充ZK配置字段 2022-09-26 11:10:38 +08:00
EricZeng
ed562f9c8a Merge pull request #618 from didi/dev
DB中Group信息的更新方式,由replace调整为insert或update
2022-09-26 10:02:24 +08:00
zengqiao
b4d44ef8c7 DB中Group信息的更新方式,由replace调整为insert或update 2022-09-23 17:02:25 +08:00
EricZeng
ad0c16a1b4 升级Helm版本及增加Docker相关文件
升级Helm版本及增加Docker相关文件
2022-09-23 16:17:00 +08:00
wangdongfang-aden
7eabe66853 Merge pull request #616 from wangdongfang-aden/dev
添加docker-compose部署和更新helm
2022-09-23 14:50:22 +08:00
wangdongfang-aden
3983d73695 Update Chart.yaml 2022-09-23 14:47:40 +08:00
wangdongfang-aden
161d4c4562 Update 单机部署手册.md 2022-09-23 14:46:27 +08:00
wangdongfang-aden
9a1e89564e Update 单机部署手册.md 2022-09-23 14:44:49 +08:00
wangdongfang-aden
0c18c5b4f6 Update 单机部署手册.md 2022-09-23 14:43:23 +08:00
wangdongfang-aden
3e12ba34f7 Update docker-compose.yml 2022-09-23 14:33:05 +08:00
wangdongfang-aden
e71e29391b Delete ks-start.sh 2022-09-23 14:26:24 +08:00
wangdongfang-aden
9b7b9a7af0 Delete es_template_create.sh 2022-09-23 14:26:16 +08:00
wangdongfang-aden
a23819c308 Create ks-start.sh 2022-09-23 14:19:35 +08:00
wangdongfang-aden
6cb1825d96 Create es_template_create.sh 2022-09-23 14:19:10 +08:00
wangdongfang-aden
77b8c758dc Create initsql 2022-09-23 14:18:17 +08:00
wangdongfang-aden
e5a582cfad Create my.cnf 2022-09-23 14:17:25 +08:00
wangdongfang-aden
ec83db267e Create init.sh 2022-09-23 14:17:02 +08:00
wangdongfang-aden
bfd026cae7 Create dockerfile 2022-09-23 14:16:28 +08:00
wangdongfang-aden
35f1dd8082 Create dockerfile 2022-09-23 14:14:47 +08:00
wangdongfang-aden
7ed0e7dd23 Create dockerfile 2022-09-23 14:14:02 +08:00
wangdongfang-aden
1a3cbf7a9d Create knowstreaming.conf 2022-09-23 14:07:04 +08:00
wangdongfang-aden
d9e4abc3de Create ks-start.sh 2022-09-23 14:05:59 +08:00
wangdongfang-aden
a4186085d3 Create es_template_create.sh 2022-09-23 14:05:05 +08:00
wangdongfang-aden
26b1846bb4 Create docker-compose.yml 2022-09-23 14:03:14 +08:00
wangdongfang-aden
1aa89527a6 helm update 3.0.0-beta.3 2022-09-23 11:36:46 +08:00
wangdongfang-aden
eac76d7ad0 helm update 3.0.0-beta.3 2022-09-23 11:36:01 +08:00
wangdongfang-aden
cea0cd56f6 Merge pull request #607 from haoqi123/dev
[单机部署手册.md]docker-compose部署方式添加注释描述
2022-09-23 10:27:04 +08:00
EricZeng
c4b897f282 bump version to 3.0.0-beta.4
bump version to 3.0.0-beta.4
2022-09-23 10:24:52 +08:00
zengqiao
47389dbabb bump version to 3.0.0-beta.4 2022-09-23 10:17:58 +08:00
haoqi
a2f8b1a851 1. [单机部署手册.md]docker-compose部署方式添加注释描述 2022-09-22 19:46:21 +08:00
haoqi
26916f6632 1. [单机部署手册.md]docker-compose部署方式添加注释描述
2. 更改docker-compose中ui对外访问port为80
2022-09-21 12:55:43 +08:00
104 changed files with 3302 additions and 660 deletions

View File

@@ -13,7 +13,7 @@ Before sending pull request to this project, please read and follow guidelines b
Add device mode, API version, related log, screenshots and other related information in your pull request if possible. Add device mode, API version, related log, screenshots and other related information in your pull request if possible.
NOTE: We assume all your contribution can be licensed under the [Apache License 2.0](LICENSE). NOTE: We assume all your contribution can be licensed under the [AGPL-3.0](LICENSE).
## Issues ## Issues

View File

@@ -133,6 +133,8 @@ PS: 提问请尽量把问题一次性描述清楚,并告知环境信息情况
**`2、微信群`** **`2、微信群`**
微信加群:添加`mike_zhangliang``PenceXie`的微信号备注KnowStreaming加群。 微信加群:添加`mike_zhangliang``PenceXie`的微信号备注KnowStreaming加群。
<br/>
<img width="116" alt="wx" src="https://user-images.githubusercontent.com/71620349/192257217-c4ebc16c-3ad9-485d-a914-5911d3a4f46b.png">
## Star History ## Star History

View File

@@ -1,5 +1,32 @@
## v3.0.0
**Bug修复**
- 修复 Group 指标防重复采集不生效问题
- 修复自动创建 ES 索引模版失败问题
- 修复 Group+Topic 列表中存在已删除Topic的问题
- 修复使用 MySQL-8 ,因兼容问题, start_time 信息为 NULL 时,会导致创建任务失败的问题
- 修复 Group 信息表更新时,出现死锁的问题
- 修复图表补点逻辑与图表时间范围不适配的问题
**体验优化**
- 按照资源类别,拆分健康巡检任务
- 优化 Group 详情页的指标为实时获取
- 图表拖拽排序支持用户级存储
- 多集群列表 ZK 信息展示兼容无 ZK 情况
- Topic 详情消息预览支持复制功能
- 部分内容大数字支持千位分割符展示
**新增**
- 集群信息中,新增 Zookeeper 客户端配置字段
- 集群信息中,新增 Kafka 集群运行模式字段
- 新增 docker-compose 的部署方式
## v3.0.0-beta.3 ## v3.0.0-beta.3
**文档** **文档**

View File

@@ -74,11 +74,11 @@ sh deploy_KnowStreaming-offline.sh
```bash ```bash
# 相关镜像在Docker Hub都可以下载 # 相关镜像在Docker Hub都可以下载
# 快速安装(NAMESPACE需要更改为已存在的安装启动需要几分钟初始化请稍等~) # 快速安装(NAMESPACE需要更改为已存在的安装启动需要几分钟初始化请稍等~)
helm install -n [NAMESPACE] [NAME] http://download.knowstreaming.com/charts/knowstreaming-manager-0.1.3.tgz helm install -n [NAMESPACE] [NAME] http://download.knowstreaming.com/charts/knowstreaming-manager-0.1.5.tgz
# 获取KnowStreaming前端ui的service. 默认nodeport方式. # 获取KnowStreaming前端ui的service. 默认nodeport方式.
# (http://nodeIP:nodeport默认用户名密码admin/admin2022_) # (http://nodeIP:nodeport默认用户名密码admin/admin2022_)
# `v3.0.0-beta.2`版本开始,默认账号密码为`admin` / `admin` # `v3.0.0-beta.2`版本开始helm chart包版本0.1.4开始),默认账号密码为`admin` / `admin`
# 添加仓库 # 添加仓库
helm repo add knowstreaming http://download.knowstreaming.com/charts helm repo add knowstreaming http://download.knowstreaming.com/charts
@@ -90,13 +90,54 @@ helm pull knowstreaming/knowstreaming-manager
&nbsp; &nbsp;
#### 2.1.3.2、Docker Compose #### 2.1.3.2、Docker Compose
```yml **环境依赖**
version: "3"
- [Docker](https://docs.docker.com/engine/install/)
- [Docker Compose](https://docs.docker.com/compose/install/)
**安装命令**
```bash
# `v3.0.0-beta.2`版本开始(docker镜像为0.2.0版本开始),默认账号密码为`admin` / `admin`
# https://hub.docker.com/u/knowstreaming 在此处寻找最新镜像版本
# mysql与es可以使用自己搭建的服务,调整对应配置即可
# 复制docker-compose.yml到指定位置后执行下方命令即可启动
docker-compose up -d
```
**验证安装**
```shell
docker-compose ps
# 验证启动 - 状态为 UP 则表示成功
Name Command State Ports
----------------------------------------------------------------------------------------------------
elasticsearch-single /usr/local/bin/docker-entr ... Up 9200/tcp, 9300/tcp
knowstreaming-init /bin/bash /es_template_cre ... Up
knowstreaming-manager /bin/sh /ks-start.sh Up 80/tcp
knowstreaming-mysql /entrypoint.sh mysqld Up (health: starting) 3306/tcp, 33060/tcp
knowstreaming-ui /docker-entrypoint.sh ngin ... Up 0.0.0.0:80->80/tcp
# 稍等一分钟左右 knowstreaming-init 会退出表示es初始化完成可以访问页面
Name Command State Ports
-------------------------------------------------------------------------------------------
knowstreaming-init /bin/bash /es_template_cre ... Exit 0
knowstreaming-mysql /entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp
```
**访问**
```http request
http://127.0.0.1:80/
```
**docker-compose.yml**
```yml
version: "2"
services: services:
# *不要调整knowstreaming-manager服务名称ui中会用到
knowstreaming-manager: knowstreaming-manager:
image: knowstreaming/knowstreaming-manager:0.2.0-test image: knowstreaming/knowstreaming-manager:latest
container_name: knowstreaming-manager container_name: knowstreaming-manager
privileged: true privileged: true
restart: always restart: always
@@ -110,33 +151,36 @@ services:
- /ks-start.sh - /ks-start.sh
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
# mysql服务地址
SERVER_MYSQL_ADDRESS: knowstreaming-mysql:3306 SERVER_MYSQL_ADDRESS: knowstreaming-mysql:3306
# mysql数据库名
SERVER_MYSQL_DB: know_streaming SERVER_MYSQL_DB: know_streaming
# mysql用户名
SERVER_MYSQL_USER: root SERVER_MYSQL_USER: root
# mysql用户密码
SERVER_MYSQL_PASSWORD: admin2022_ SERVER_MYSQL_PASSWORD: admin2022_
# es服务地址
SERVER_ES_ADDRESS: elasticsearch-single:9200 SERVER_ES_ADDRESS: elasticsearch-single:9200
# 服务JVM参数
JAVA_OPTS: -Xmx1g -Xms1g JAVA_OPTS: -Xmx1g -Xms1g
# 对于kafka中ADVERTISED_LISTENERS填写的hostname可以通过该方式完成
# extra_hosts: # extra_hosts:
# - "hostname:x.x.x.x" # - "hostname:x.x.x.x"
# 服务日志路径
# volumes: # volumes:
# - /ks/manage/log:/logs # - /ks/manage/log:/logs
knowstreaming-ui: knowstreaming-ui:
image: knowstreaming/knowstreaming-ui:0.2.0-test1 image: knowstreaming/knowstreaming-ui:latest
container_name: knowstreaming-ui container_name: knowstreaming-ui
restart: always restart: always
ports: ports:
- '18092:80' - '80:80'
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
depends_on: depends_on:
- knowstreaming-manager - knowstreaming-manager
# extra_hosts: # extra_hosts:
# - "hostname:x.x.x.x" # - "hostname:x.x.x.x"
elasticsearch-single: elasticsearch-single:
image: docker.io/library/elasticsearch:7.6.2 image: docker.io/library/elasticsearch:7.6.2
container_name: elasticsearch-single container_name: elasticsearch-single
@@ -149,14 +193,19 @@ services:
# - '9300:9300' # - '9300:9300'
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
# es的JVM参数
ES_JAVA_OPTS: -Xms512m -Xmx512m ES_JAVA_OPTS: -Xms512m -Xmx512m
# 单节点配置,多节点集群参考 https://www.elastic.co/guide/en/elasticsearch/reference/7.6/docker.html#docker-compose-file
discovery.type: single-node discovery.type: single-node
# 数据持久化路径
# volumes: # volumes:
# - /ks/es/data:/usr/share/elasticsearch/data # - /ks/es/data:/usr/share/elasticsearch/data
# es初始化服务与manager使用同一镜像
# 首次启动es需初始化模版和索引,后续会自动创建
knowstreaming-init: knowstreaming-init:
image: knowstreaming/knowstreaming-manager:0.2.0-test image: knowstreaming/knowstreaming-manager:latest
container_name: knowstreaming_init container_name: knowstreaming-init
depends_on: depends_on:
- elasticsearch-single - elasticsearch-single
command: command:
@@ -164,22 +213,26 @@ services:
- /es_template_create.sh - /es_template_create.sh
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
# es服务地址
SERVER_ES_ADDRESS: elasticsearch-single:9200 SERVER_ES_ADDRESS: elasticsearch-single:9200
knowstreaming-mysql: knowstreaming-mysql:
image: knowstreaming/knowstreaming-mysql:0.2.0-test image: knowstreaming/knowstreaming-mysql:latest
container_name: knowstreaming-mysql container_name: knowstreaming-mysql
restart: always restart: always
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
# root 用户密码
MYSQL_ROOT_PASSWORD: admin2022_ MYSQL_ROOT_PASSWORD: admin2022_
# 初始化时创建的数据库名称
MYSQL_DATABASE: know_streaming MYSQL_DATABASE: know_streaming
# 通配所有host,可以访问远程
MYSQL_ROOT_HOST: '%' MYSQL_ROOT_HOST: '%'
expose: expose:
- 3306 - 3306
# ports: # ports:
# - '3306:3306' # - '3306:3306'
# 数据持久化路径
# volumes: # volumes:
# - /ks/mysql/data:/data/mysql # - /ks/mysql/data:/data/mysql
``` ```

View File

@@ -1,12 +1,28 @@
## 6.2、版本升级手册 ## 6.2、版本升级手册
注意:如果想升级至具体版本,需要将你当前版本至你期望使用版本的变更统统执行一遍,然后才能正常使用。 注意:
- 如果想升级至具体版本,需要将你当前版本至你期望使用版本的变更统统执行一遍,然后才能正常使用。
- 如果中间某个版本没有升级信息,则表示该版本直接替换安装包即可从前一个版本升级至当前版本。
### 6.2.0、升级至 `master` 版本 ### 6.2.0、升级至 `master` 版本
暂无 暂无
### 6.2.1、升级至 `v3.0.0-beta.2`版本
### 6.2.1、升级至 `v3.0.0` 版本
**SQL 变更**
```sql
ALTER TABLE `ks_km_physical_cluster`
ADD COLUMN `zk_properties` TEXT NULL COMMENT 'ZK配置' AFTER `jmx_properties`;
```
---
### 6.2.2、升级至 `v3.0.0-beta.2`版本
**配置变更** **配置变更**
@@ -77,7 +93,7 @@ ALTER TABLE `logi_security_oplog`
--- ---
### 6.2.2、升级至 `v3.0.0-beta.1`版本 ### 6.2.3、升级至 `v3.0.0-beta.1`版本
**SQL 变更** **SQL 变更**
@@ -96,7 +112,7 @@ ALTER COLUMN `operation_methods` set default '';
--- ---
### 6.2.3、`2.x`版本 升级至 `v3.0.0-beta.0`版本 ### 6.2.4、`2.x`版本 升级至 `v3.0.0-beta.0`版本
**升级步骤:** **升级步骤:**

View File

@@ -272,15 +272,11 @@ public class GroupManagerImpl implements GroupManager {
// 获取Group指标信息 // 获取Group指标信息
Result<List<GroupMetrics>> groupMetricsResult = groupMetricService.listPartitionLatestMetricsFromES( Result<List<GroupMetrics>> groupMetricsResult = groupMetricService.collectGroupMetricsFromKafka(clusterPhyId, groupName, latestMetricNames == null ? Arrays.asList() : latestMetricNames);
clusterPhyId,
groupName,
topicName,
latestMetricNames == null? Arrays.asList(): latestMetricNames
);
// 转换Group指标 // 转换Group指标
List<GroupMetrics> esGroupMetricsList = groupMetricsResult.hasData()? groupMetricsResult.getData(): new ArrayList<>(); List<GroupMetrics> esGroupMetricsList = groupMetricsResult.hasData() ? groupMetricsResult.getData().stream().filter(elem -> topicName.equals(elem.getTopic())).collect(Collectors.toList()) : new ArrayList<>();
Map<Integer, GroupMetrics> esMetricsMap = new HashMap<>(); Map<Integer, GroupMetrics> esMetricsMap = new HashMap<>();
for (GroupMetrics groupMetrics: esGroupMetricsList) { for (GroupMetrics groupMetrics: esGroupMetricsList) {
esMetricsMap.put(groupMetrics.getPartitionId(), groupMetrics); esMetricsMap.put(groupMetrics.getPartitionId(), groupMetrics);

View File

@@ -1,121 +0,0 @@
package com.xiaojukeji.know.streaming.km.collector.metric;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.*;
import com.xiaojukeji.know.streaming.km.common.bean.po.BaseESPO;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.*;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import com.xiaojukeji.know.streaming.km.common.utils.EnvUtil;
import com.xiaojukeji.know.streaming.km.common.utils.NamedThreadFactory;
import com.xiaojukeji.know.streaming.km.persistence.es.dao.BaseMetricESDAO;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.*;
@Component
public class MetricESSender implements ApplicationListener<BaseMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
private static final int THRESHOLD = 100;
private ThreadPoolExecutor esExecutor = new ThreadPoolExecutor(10, 20, 6000, TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>(1000),
new NamedThreadFactory("KM-Collect-MetricESSender-ES"),
(r, e) -> LOGGER.warn("class=MetricESSender||msg=KM-Collect-MetricESSender-ES Deque is blocked, taskCount:{}" + e.getTaskCount()));
@PostConstruct
public void init(){
LOGGER.info("class=MetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(BaseMetricEvent event) {
if(event instanceof BrokerMetricEvent) {
BrokerMetricEvent brokerMetricEvent = (BrokerMetricEvent)event;
send2es(BROKER_INDEX,
ConvertUtil.list2List(brokerMetricEvent.getBrokerMetrics(), BrokerMetricPO.class)
);
} else if(event instanceof ClusterMetricEvent) {
ClusterMetricEvent clusterMetricEvent = (ClusterMetricEvent)event;
send2es(CLUSTER_INDEX,
ConvertUtil.list2List(clusterMetricEvent.getClusterMetrics(), ClusterMetricPO.class)
);
} else if(event instanceof TopicMetricEvent) {
TopicMetricEvent topicMetricEvent = (TopicMetricEvent)event;
send2es(TOPIC_INDEX,
ConvertUtil.list2List(topicMetricEvent.getTopicMetrics(), TopicMetricPO.class)
);
} else if(event instanceof PartitionMetricEvent) {
PartitionMetricEvent partitionMetricEvent = (PartitionMetricEvent)event;
send2es(PARTITION_INDEX,
ConvertUtil.list2List(partitionMetricEvent.getPartitionMetrics(), PartitionMetricPO.class)
);
} else if(event instanceof GroupMetricEvent) {
GroupMetricEvent groupMetricEvent = (GroupMetricEvent)event;
send2es(GROUP_INDEX,
ConvertUtil.list2List(groupMetricEvent.getGroupMetrics(), GroupMetricPO.class)
);
} else if(event instanceof ReplicaMetricEvent) {
ReplicaMetricEvent replicaMetricEvent = (ReplicaMetricEvent)event;
send2es(REPLICATION_INDEX,
ConvertUtil.list2List(replicaMetricEvent.getReplicationMetrics(), ReplicationMetricPO.class)
);
}
}
/**
* 根据不同监控维度来发送
*/
private boolean send2es(String index, List<? extends BaseESPO> statsList){
if (CollectionUtils.isEmpty(statsList)) {
return true;
}
if (!EnvUtil.isOnline()) {
LOGGER.info("class=MetricESSender||method=send2es||ariusStats={}||size={}",
index, statsList.size());
}
BaseMetricESDAO baseMetricESDao = BaseMetricESDAO.getByStatsType(index);
if (Objects.isNull( baseMetricESDao )) {
LOGGER.error("class=MetricESSender||method=send2es||errMsg=fail to find {}", index);
return false;
}
int size = statsList.size();
int num = (size) % THRESHOLD == 0 ? (size / THRESHOLD) : (size / THRESHOLD + 1);
if (size < THRESHOLD) {
esExecutor.execute(
() -> baseMetricESDao.batchInsertStats(statsList)
);
return true;
}
for (int i = 1; i < num + 1; i++) {
int end = (i * THRESHOLD) > size ? size : (i * THRESHOLD);
int start = (i - 1) * THRESHOLD;
esExecutor.execute(
() -> baseMetricESDao.batchInsertStats(statsList.subList(start, end))
);
}
return true;
}
}

View File

@@ -0,0 +1,72 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.po.BaseESPO;
import com.xiaojukeji.know.streaming.km.common.utils.EnvUtil;
import com.xiaojukeji.know.streaming.km.common.utils.NamedThreadFactory;
import com.xiaojukeji.know.streaming.km.persistence.es.dao.BaseMetricESDAO;
import org.apache.commons.collections.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public abstract class AbstractMetricESSender {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
private static final int THRESHOLD = 100;
private static final ThreadPoolExecutor esExecutor = new ThreadPoolExecutor(
10,
20,
6000,
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>(1000),
new NamedThreadFactory("KM-Collect-MetricESSender-ES"),
(r, e) -> LOGGER.warn("class=MetricESSender||msg=KM-Collect-MetricESSender-ES Deque is blocked, taskCount:{}" + e.getTaskCount())
);
/**
* 根据不同监控维度来发送
*/
protected boolean send2es(String index, List<? extends BaseESPO> statsList){
if (CollectionUtils.isEmpty(statsList)) {
return true;
}
if (!EnvUtil.isOnline()) {
LOGGER.info("class=MetricESSender||method=send2es||ariusStats={}||size={}",
index, statsList.size());
}
BaseMetricESDAO baseMetricESDao = BaseMetricESDAO.getByStatsType(index);
if (Objects.isNull( baseMetricESDao )) {
LOGGER.error("class=MetricESSender||method=send2es||errMsg=fail to find {}", index);
return false;
}
int size = statsList.size();
int num = (size) % THRESHOLD == 0 ? (size / THRESHOLD) : (size / THRESHOLD + 1);
if (size < THRESHOLD) {
esExecutor.execute(
() -> baseMetricESDao.batchInsertStats(statsList)
);
return true;
}
for (int i = 1; i < num + 1; i++) {
int end = (i * THRESHOLD) > size ? size : (i * THRESHOLD);
int start = (i - 1) * THRESHOLD;
esExecutor.execute(
() -> baseMetricESDao.batchInsertStats(statsList.subList(start, end))
);
}
return true;
}
}

View File

@@ -0,0 +1,28 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.BrokerMetricEvent;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.BrokerMetricPO;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.BROKER_INDEX;
@Component
public class BrokerMetricESSender extends AbstractMetricESSender implements ApplicationListener<BrokerMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
@PostConstruct
public void init(){
LOGGER.info("class=BrokerMetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(BrokerMetricEvent event) {
send2es(BROKER_INDEX, ConvertUtil.list2List(event.getBrokerMetrics(), BrokerMetricPO.class));
}
}

View File

@@ -0,0 +1,29 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.ClusterMetricEvent;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.ClusterMetricPO;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.CLUSTER_INDEX;
@Component
public class ClusterMetricESSender extends AbstractMetricESSender implements ApplicationListener<ClusterMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
@PostConstruct
public void init(){
LOGGER.info("class=ClusterMetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(ClusterMetricEvent event) {
send2es(CLUSTER_INDEX, ConvertUtil.list2List(event.getClusterMetrics(), ClusterMetricPO.class));
}
}

View File

@@ -0,0 +1,29 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.GroupMetricEvent;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.GroupMetricPO;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.GROUP_INDEX;
@Component
public class GroupMetricESSender extends AbstractMetricESSender implements ApplicationListener<GroupMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
@PostConstruct
public void init(){
LOGGER.info("class=GroupMetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(GroupMetricEvent event) {
send2es(GROUP_INDEX, ConvertUtil.list2List(event.getGroupMetrics(), GroupMetricPO.class));
}
}

View File

@@ -0,0 +1,28 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.PartitionMetricEvent;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.PartitionMetricPO;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.PARTITION_INDEX;
@Component
public class PartitionMetricESSender extends AbstractMetricESSender implements ApplicationListener<PartitionMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
@PostConstruct
public void init(){
LOGGER.info("class=PartitionMetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(PartitionMetricEvent event) {
send2es(PARTITION_INDEX, ConvertUtil.list2List(event.getPartitionMetrics(), PartitionMetricPO.class));
}
}

View File

@@ -0,0 +1,28 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.ReplicaMetricEvent;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.ReplicationMetricPO;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.REPLICATION_INDEX;
@Component
public class ReplicaMetricESSender extends AbstractMetricESSender implements ApplicationListener<ReplicaMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
@PostConstruct
public void init(){
LOGGER.info("class=GroupMetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(ReplicaMetricEvent event) {
send2es(REPLICATION_INDEX, ConvertUtil.list2List(event.getReplicationMetrics(), ReplicationMetricPO.class));
}
}

View File

@@ -0,0 +1,29 @@
package com.xiaojukeji.know.streaming.km.collector.sink;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.event.metric.*;
import com.xiaojukeji.know.streaming.km.common.bean.po.metrice.*;
import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import static com.xiaojukeji.know.streaming.km.common.constant.ESIndexConstant.TOPIC_INDEX;
@Component
public class TopicMetricESSender extends AbstractMetricESSender implements ApplicationListener<TopicMetricEvent> {
protected static final ILog LOGGER = LogFactory.getLog("METRIC_LOGGER");
@PostConstruct
public void init(){
LOGGER.info("class=TopicMetricESSender||method=init||msg=init finished");
}
@Override
public void onApplicationEvent(TopicMetricEvent event) {
send2es(TOPIC_INDEX, ConvertUtil.list2List(event.getTopicMetrics(), TopicMetricPO.class));
}
}

View File

@@ -3,6 +3,7 @@ package com.xiaojukeji.know.streaming.km.common.bean.dto.cluster;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.xiaojukeji.know.streaming.km.common.bean.dto.BaseDTO; import com.xiaojukeji.know.streaming.km.common.bean.dto.BaseDTO;
import com.xiaojukeji.know.streaming.km.common.bean.entity.config.JmxConfig; import com.xiaojukeji.know.streaming.km.common.bean.entity.config.JmxConfig;
import com.xiaojukeji.know.streaming.km.common.bean.entity.config.ZKConfig;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@@ -34,4 +35,8 @@ public class ClusterPhyBaseDTO extends BaseDTO {
@NotNull(message = "jmxProperties不允许为空") @NotNull(message = "jmxProperties不允许为空")
@ApiModelProperty(value="Jmx配置") @ApiModelProperty(value="Jmx配置")
protected JmxConfig jmxProperties; protected JmxConfig jmxProperties;
// TODO 前端页面增加时,需要加一个不为空的限制
@ApiModelProperty(value="ZK配置")
protected ZKConfig zkProperties;
} }

View File

@@ -7,6 +7,9 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/** /**
* @author didi * @author didi
*/ */
@@ -22,6 +25,7 @@ public class MetricDetailDTO extends BaseDTO {
@ApiModelProperty("指标是否显示") @ApiModelProperty("指标是否显示")
private Boolean set; private Boolean set;
@NotNull(message = "MetricDetailDTO的rank字段应不为空")
@ApiModelProperty("指标优先级") @ApiModelProperty("指标优先级")
private Integer rank; private Integer rank;

View File

@@ -7,6 +7,7 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -19,6 +20,7 @@ public class UserMetricConfigDTO extends BaseDTO {
@ApiModelProperty("指标展示设置项key指标名value是否展现(true展现/false不展现)") @ApiModelProperty("指标展示设置项key指标名value是否展现(true展现/false不展现)")
private Map<String, Boolean> metricsSet; private Map<String, Boolean> metricsSet;
@Valid
@ApiModelProperty("指标自定义属性列表") @ApiModelProperty("指标自定义属性列表")
private List<MetricDetailDTO> metricDetailDTOList; private List<MetricDetailDTO> metricDetailDTOList;
} }

View File

@@ -53,9 +53,16 @@ public class ClusterPhy implements Comparable<ClusterPhy>, EntifyIdInterface {
/** /**
* jmx配置 * jmx配置
* @see com.xiaojukeji.know.streaming.km.common.bean.entity.config.JmxConfig
*/ */
private String jmxProperties; private String jmxProperties;
/**
* zk配置
* @see com.xiaojukeji.know.streaming.km.common.bean.entity.config.ZKConfig
*/
private String zkProperties;
/** /**
* 开启ACL * 开启ACL
* @see com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterAuthTypeEnum * @see com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterAuthTypeEnum

View File

@@ -0,0 +1,31 @@
package com.xiaojukeji.know.streaming.km.common.bean.entity.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Properties;
/**
* @author zengqiao
* @date 22/02/24
*/
@Data
@ApiModel(description = "ZK配置")
public class ZKConfig implements Serializable {
@ApiModelProperty(value="ZK的jmx配置")
private JmxConfig jmxConfig;
@ApiModelProperty(value="ZK是否开启secure", example = "false")
private Boolean openSecure = false;
@ApiModelProperty(value="ZK的Session超时时间", example = "15000")
private Long sessionTimeoutUnitMs = 15000L;
@ApiModelProperty(value="ZK的Request超时时间", example = "5000")
private Long requestTimeoutUnitMs = 5000L;
@ApiModelProperty(value="ZK的Request超时时间")
private Properties otherProps = new Properties();
}

View File

@@ -41,6 +41,11 @@ public class ClusterPhyPO extends BasePO {
*/ */
private String jmxProperties; private String jmxProperties;
/**
* zk配置
*/
private String zkProperties;
/** /**
* 认证类型 * 认证类型
* @see com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterAuthTypeEnum * @see com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterAuthTypeEnum

View File

@@ -31,9 +31,15 @@ public class ClusterPhyBaseVO extends BaseTimeVO {
@ApiModelProperty(value="Jmx配置", example = "{}") @ApiModelProperty(value="Jmx配置", example = "{}")
protected String jmxProperties; protected String jmxProperties;
@ApiModelProperty(value="ZK配置", example = "{}")
protected String zkProperties;
@ApiModelProperty(value="描述", example = "测试") @ApiModelProperty(value="描述", example = "测试")
protected String description; protected String description;
@ApiModelProperty(value="集群的kafka版本", example = "2.5.1") @ApiModelProperty(value="集群的kafka版本", example = "2.5.1")
protected String kafkaVersion; protected String kafkaVersion;
@ApiModelProperty(value="集群的运行模式", example = "2raft模式其他是ZK模式")
private Integer runState;
} }

View File

@@ -19,6 +19,11 @@ public class ClusterConverter {
ClusterPhyPO clusterPhyPO = ConvertUtil.obj2Obj(dto, ClusterPhyPO.class); ClusterPhyPO clusterPhyPO = ConvertUtil.obj2Obj(dto, ClusterPhyPO.class);
clusterPhyPO.setClientProperties(ConvertUtil.obj2Json(dto.getClientProperties())); clusterPhyPO.setClientProperties(ConvertUtil.obj2Json(dto.getClientProperties()));
clusterPhyPO.setJmxProperties(ConvertUtil.obj2Json(dto.getJmxProperties())); clusterPhyPO.setJmxProperties(ConvertUtil.obj2Json(dto.getJmxProperties()));
if (ValidateUtils.isNull(dto.getZkProperties())) {
clusterPhyPO.setZkProperties("");
} else {
clusterPhyPO.setZkProperties(ConvertUtil.obj2Json(dto.getZkProperties()));
}
clusterPhyPO.setRunState( clusterPhyPO.setRunState(
ValidateUtils.isBlank(dto.getZookeeper())? ValidateUtils.isBlank(dto.getZookeeper())?
ClusterRunStateEnum.RUN_RAFT.getRunState() : ClusterRunStateEnum.RUN_RAFT.getRunState() :
@@ -32,6 +37,11 @@ public class ClusterConverter {
ClusterPhyPO clusterPhyPO = ConvertUtil.obj2Obj(dto, ClusterPhyPO.class); ClusterPhyPO clusterPhyPO = ConvertUtil.obj2Obj(dto, ClusterPhyPO.class);
clusterPhyPO.setClientProperties(ConvertUtil.obj2Json(dto.getClientProperties())); clusterPhyPO.setClientProperties(ConvertUtil.obj2Json(dto.getClientProperties()));
clusterPhyPO.setJmxProperties(ConvertUtil.obj2Json(dto.getJmxProperties())); clusterPhyPO.setJmxProperties(ConvertUtil.obj2Json(dto.getJmxProperties()));
if (ValidateUtils.isNull(dto.getZkProperties())) {
clusterPhyPO.setZkProperties("");
} else {
clusterPhyPO.setZkProperties(ConvertUtil.obj2Json(dto.getZkProperties()));
}
clusterPhyPO.setRunState( clusterPhyPO.setRunState(
ValidateUtils.isBlank(dto.getZookeeper())? ValidateUtils.isBlank(dto.getZookeeper())?
ClusterRunStateEnum.RUN_RAFT.getRunState() : ClusterRunStateEnum.RUN_RAFT.getRunState() :

View File

@@ -1387,6 +1387,16 @@
"@jridgewell/sourcemap-codec": "^1.4.10" "@jridgewell/sourcemap-codec": "^1.4.10"
} }
}, },
"@knowdesign/icons": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@knowdesign/icons/-/icons-1.0.1.tgz",
"integrity": "sha512-EI3s25BJt+Slv7/t6B3K3zv7I6TKkk2Wf1y68zuxK80MMkWf8lqqUtyAZbFDoPUfXAjw6vHktMBH44gbMHMRFA==",
"requires": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons": "^4.7.0",
"react": "16.12.0"
}
},
"@nodelib/fs.scandir": { "@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -7463,9 +7473,9 @@
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
}, },
"is-lite": { "is-lite": {
"version": "0.8.2", "version": "0.9.2",
"resolved": "https://registry.npmmirror.com/is-lite/-/is-lite-0.8.2.tgz", "resolved": "https://registry.npmmirror.com/is-lite/-/is-lite-0.9.2.tgz",
"integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw==" "integrity": "sha512-qZuxbaEiKLOKhX4sbHLfhFN9iA3YciuZLb37/DfXCpWnz8p7qNL2lwkpxYMXfjlS8eEEjpULPZxAUI8N6FYvYQ=="
}, },
"is-negative-zero": { "is-negative-zero": {
"version": "2.0.2", "version": "2.0.2",
@@ -7769,9 +7779,11 @@
"rc-dialog": "~8.6.0", "rc-dialog": "~8.6.0",
"rc-drawer": "^4.4.3", "rc-drawer": "^4.4.3",
"rc-dropdown": "~3.2.0", "rc-dropdown": "~3.2.0",
"rc-field-form": "~1.21.0",
"rc-image": "~5.2.5", "rc-image": "~5.2.5",
"rc-input-number": "~7.3.6", "rc-input-number": "~7.3.6",
"rc-mentions": "~1.6.1", "rc-mentions": "~1.6.1",
"rc-menu": "~9.0.12",
"rc-motion": "^2.4.4", "rc-motion": "^2.4.4",
"rc-notification": "~4.5.7", "rc-notification": "~4.5.7",
"rc-pagination": "~3.1.9", "rc-pagination": "~3.1.9",
@@ -7783,9 +7795,11 @@
"rc-slider": "~9.7.4", "rc-slider": "~9.7.4",
"rc-steps": "~4.1.0", "rc-steps": "~4.1.0",
"rc-switch": "~3.2.0", "rc-switch": "~3.2.0",
"rc-table": "~7.19.0",
"rc-tabs": "~11.10.0", "rc-tabs": "~11.10.0",
"rc-textarea": "~0.3.0", "rc-textarea": "~0.3.0",
"rc-tooltip": "~5.1.1", "rc-tooltip": "~5.1.1",
"rc-tree": "~5.3.0",
"rc-tree-select": "~4.8.0", "rc-tree-select": "~4.8.0",
"rc-trigger": "^5.2.10", "rc-trigger": "^5.2.10",
"rc-upload": "~4.3.0", "rc-upload": "~4.3.0",
@@ -7823,81 +7837,10 @@
"scroll-into-view-if-needed": "^2.2.25" "scroll-into-view-if-needed": "^2.2.25"
}, },
"dependencies": { "dependencies": {
"async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"intl-format-cache": {
"version": "2.2.9",
"resolved": "https://registry.npmmirror.com/intl-format-cache/-/intl-format-cache-2.2.9.tgz",
"integrity": "sha512-Zv/u8wRpekckv0cLkwpVdABYST4hZNTDaX7reFetrYTJwxExR2VyTqQm+l0WmL0Qo8Mjb9Tf33qnfj0T7pjxdQ=="
},
"intl-messageformat": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/intl-messageformat/-/intl-messageformat-2.2.0.tgz",
"integrity": "sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw==",
"requires": {
"intl-messageformat-parser": "1.4.0"
}
},
"intl-messageformat-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz",
"integrity": "sha512-/XkqFHKezO6UcF4Av2/Lzfrez18R0jyw7kRFhSeB/YRakdrgSc9QfFZUwNJI9swMwMoNPygK1ArC5wdFSjPw+A=="
},
"rc-field-form": {
"version": "1.27.1",
"resolved": "https://registry.npmmirror.com/rc-field-form/-/rc-field-form-1.27.1.tgz",
"integrity": "sha512-RShegnwFu6TH8tl2olCxn+B4Wyh5EiQH8c/7wucbkLNyue05YiH5gomUAg1vbZjp71yFKwegClctsEG5CNBWAA==",
"requires": {
"@babel/runtime": "^7.18.0",
"async-validator": "^4.1.0",
"rc-util": "^5.8.0"
}
},
"rc-menu": {
"version": "9.6.4",
"resolved": "https://registry.npmmirror.com/rc-menu/-/rc-menu-9.6.4.tgz",
"integrity": "sha512-6DiNAjxjVIPLZXHffXxxcyE15d4isRL7iQ1ru4MqYDH2Cqc5bW96wZOdMydFtGLyDdnmEQ9jVvdCE9yliGvzkw==",
"requires": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
"rc-motion": "^2.4.3",
"rc-overflow": "^1.2.0",
"rc-trigger": "^5.1.2",
"rc-util": "^5.12.0",
"shallowequal": "^1.1.0"
}
},
"rc-table": {
"version": "7.25.3",
"resolved": "https://registry.npmmirror.com/rc-table/-/rc-table-7.25.3.tgz",
"integrity": "sha512-McsLJ2rg8EEpRBRYN4Pf9gT7ZNYnjvF9zrBpUBBbUX/fxk+eGi5ff1iPIhMyiHsH71/BmTUzX9nc9XqupD0nMg==",
"requires": {
"@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
"rc-resize-observer": "^1.1.0",
"rc-util": "^5.22.5",
"shallowequal": "^1.1.0"
}
},
"rc-tree": {
"version": "5.6.9",
"resolved": "https://registry.npmmirror.com/rc-tree/-/rc-tree-5.6.9.tgz",
"integrity": "sha512-si8aGuWQ2/sh2Ibk+WdUdDeAxoviT/+kDY+NLtJ+RhqfySqPFqWM5uHTwgFRrWUvKCqEeE/PjCYuuhHrK7Y7+A==",
"requires": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
"rc-motion": "^2.0.1",
"rc-util": "^5.16.1",
"rc-virtual-list": "^3.4.8"
}
},
"rc-util": { "rc-util": {
"version": "5.24.2", "version": "5.24.4",
"resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.24.2.tgz", "resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.24.4.tgz",
"integrity": "sha512-MWd0ZEV7xSwN4HM9jz9BwpnMzwCPjYJ7K90lePsrdgAkrmm8U7b4BOTIsv/84BQsaF7N3ejNkcrZ3AfEwc9HXA==", "integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
"requires": { "requires": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"react-is": "^16.12.0", "react-is": "^16.12.0",
@@ -10289,6 +10232,33 @@
"rc-editor-core": "~0.8.3" "rc-editor-core": "~0.8.3"
} }
}, },
"rc-field-form": {
"version": "1.21.2",
"resolved": "https://registry.npmmirror.com/rc-field-form/-/rc-field-form-1.21.2.tgz",
"integrity": "sha512-LR/bURt/Tf5g39mb0wtMtQuWn42d/7kEzpzlC5fNC7yaRVmLTtlPP4sBBlaViETM9uZQKLoaB0Pt9Mubhm9gow==",
"requires": {
"@babel/runtime": "^7.8.4",
"async-validator": "^4.0.2",
"rc-util": "^5.8.0"
},
"dependencies": {
"async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"rc-util": {
"version": "5.24.4",
"resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.24.4.tgz",
"integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
"requires": {
"@babel/runtime": "^7.18.3",
"react-is": "^16.12.0",
"shallowequal": "^1.1.0"
}
}
}
},
"rc-form": { "rc-form": {
"version": "2.4.12", "version": "2.4.12",
"resolved": "https://registry.npmmirror.com/rc-form/-/rc-form-2.4.12.tgz", "resolved": "https://registry.npmmirror.com/rc-form/-/rc-form-2.4.12.tgz",
@@ -10389,6 +10359,32 @@
} }
} }
}, },
"rc-menu": {
"version": "9.0.14",
"resolved": "https://registry.npmmirror.com/rc-menu/-/rc-menu-9.0.14.tgz",
"integrity": "sha512-CIox5mZeLDAi32SlHrV7UeSjv7tmJJhwRyxQtZCKt351w3q59XlL4WMFOmtT9gwIfP9h0XoxdBZUMe/xzkp78A==",
"requires": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
"rc-motion": "^2.4.3",
"rc-overflow": "^1.2.0",
"rc-trigger": "^5.1.2",
"rc-util": "^5.12.0",
"shallowequal": "^1.1.0"
},
"dependencies": {
"rc-util": {
"version": "5.24.4",
"resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.24.4.tgz",
"integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
"requires": {
"@babel/runtime": "^7.18.3",
"react-is": "^16.12.0",
"shallowequal": "^1.1.0"
}
}
}
},
"rc-motion": { "rc-motion": {
"version": "2.6.2", "version": "2.6.2",
"resolved": "https://registry.npmmirror.com/rc-motion/-/rc-motion-2.6.2.tgz", "resolved": "https://registry.npmmirror.com/rc-motion/-/rc-motion-2.6.2.tgz",
@@ -10641,6 +10637,30 @@
} }
} }
}, },
"rc-table": {
"version": "7.19.2",
"resolved": "https://registry.npmmirror.com/rc-table/-/rc-table-7.19.2.tgz",
"integrity": "sha512-NdpnoM50MK02H5/hGOsObfxCvGFUG5cHB9turE5BKJ81T5Ycbq193w5tLhnpILXe//Oanzr47MdMxkUnVGP+qg==",
"requires": {
"@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
"rc-resize-observer": "^1.0.0",
"rc-util": "^5.14.0",
"shallowequal": "^1.1.0"
},
"dependencies": {
"rc-util": {
"version": "5.24.4",
"resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.24.4.tgz",
"integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
"requires": {
"@babel/runtime": "^7.18.3",
"react-is": "^16.12.0",
"shallowequal": "^1.1.0"
}
}
}
},
"rc-tabs": { "rc-tabs": {
"version": "11.10.8", "version": "11.10.8",
"resolved": "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-11.10.8.tgz", "resolved": "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-11.10.8.tgz",
@@ -10713,6 +10733,30 @@
"rc-trigger": "^5.0.0" "rc-trigger": "^5.0.0"
} }
}, },
"rc-tree": {
"version": "5.3.8",
"resolved": "https://registry.npmmirror.com/rc-tree/-/rc-tree-5.3.8.tgz",
"integrity": "sha512-YuobEryPymqPmHFUOvsoOrYdm24psaj0CrGEUuDUQUeG/nNcTGw6FA2YmF4NsEaNBvNSJUSzwfZnFHrKa/xv0A==",
"requires": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
"rc-motion": "^2.0.1",
"rc-util": "^5.16.1",
"rc-virtual-list": "^3.4.1"
},
"dependencies": {
"rc-util": {
"version": "5.24.4",
"resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.24.4.tgz",
"integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
"requires": {
"@babel/runtime": "^7.18.3",
"react-is": "^16.12.0",
"shallowequal": "^1.1.0"
}
}
}
},
"rc-tree-select": { "rc-tree-select": {
"version": "4.8.0", "version": "4.8.0",
"resolved": "https://registry.npmmirror.com/rc-tree-select/-/rc-tree-select-4.8.0.tgz", "resolved": "https://registry.npmmirror.com/rc-tree-select/-/rc-tree-select-4.8.0.tgz",
@@ -11002,6 +11046,13 @@
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react-proptype-conditional-require": "^1.0.4", "react-proptype-conditional-require": "^1.0.4",
"tree-changes": "^0.9.1" "tree-changes": "^0.9.1"
},
"dependencies": {
"is-lite": {
"version": "0.8.2",
"resolved": "https://registry.npmmirror.com/is-lite/-/is-lite-0.8.2.tgz",
"integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw=="
}
} }
}, },
"react-freeze": { "react-freeze": {
@@ -11111,19 +11162,19 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"react-joyride": { "react-joyride": {
"version": "2.5.2", "version": "2.5.3",
"resolved": "https://registry.npmmirror.com/react-joyride/-/react-joyride-2.5.2.tgz", "resolved": "https://registry.npmmirror.com/react-joyride/-/react-joyride-2.5.3.tgz",
"integrity": "sha512-wsSYX3PhVrdzdd0/fv5f6ySGvb7QyAzleQv/x9IH+x+SXO6b5MUJUkefS+189bgLPkuHMwtSRcPE/oMupfmCVQ==", "integrity": "sha512-DKKvb/JAAsHm0x/RWO3WI6NOtTMHDso5v8MTauxTSz2dFs7Tu1rWg1BDBWmEMj6pUCvem7hblFbCiDAcvhs8tQ==",
"requires": { "requires": {
"deepmerge": "^4.2.2", "deepmerge": "^4.2.2",
"exenv": "^1.2.2", "exenv": "^1.2.2",
"is-lite": "^0.8.2", "is-lite": "^0.9.2",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react-floater": "^0.7.6", "react-floater": "^0.7.6",
"react-is": "^16.13.1", "react-is": "^16.13.1",
"scroll": "^3.0.1", "scroll": "^3.0.1",
"scrollparent": "^2.0.1", "scrollparent": "^2.0.1",
"tree-changes": "^0.9.1" "tree-changes": "^0.9.2"
} }
}, },
"react-lifecycles-compat": { "react-lifecycles-compat": {
@@ -13131,12 +13182,19 @@
"integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g=="
}, },
"tree-changes": { "tree-changes": {
"version": "0.9.1", "version": "0.9.3",
"resolved": "https://registry.npmmirror.com/tree-changes/-/tree-changes-0.9.1.tgz", "resolved": "https://registry.npmmirror.com/tree-changes/-/tree-changes-0.9.3.tgz",
"integrity": "sha512-Un6R1T6eUStAVbN4G+2djuXEk271mDY78ptxZUUo+TVcwvHZeUgk+pwXZjOZLAJ9n0+p47KUijeuNJSmpuG6Dw==", "integrity": "sha512-vvvS+O6kEeGRzMglTKbc19ltLWNtmNt1cpBoSYLj/iEcPVvpJasemKOlxBrmZaCtDJoF+4bwv3m01UKYi8mukQ==",
"requires": { "requires": {
"@gilbarbara/deep-equal": "^0.1.1", "@gilbarbara/deep-equal": "^0.1.1",
"is-lite": "^0.8.2" "is-lite": "^0.8.2"
},
"dependencies": {
"is-lite": {
"version": "0.8.2",
"resolved": "https://registry.npmmirror.com/is-lite/-/is-lite-0.8.2.tgz",
"integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw=="
}
} }
}, },
"ts-loader": { "ts-loader": {

View File

@@ -35,6 +35,7 @@
"dependencies": { "dependencies": {
"@ant-design/compatible": "^1.0.8", "@ant-design/compatible": "^1.0.8",
"@ant-design/icons": "^4.6.2", "@ant-design/icons": "^4.6.2",
"@knowdesign/icons": "^1.0.1",
"@types/react": "^17.0.39", "@types/react": "^17.0.39",
"@types/react-copy-to-clipboard": "^5.0.2", "@types/react-copy-to-clipboard": "^5.0.2",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
@@ -57,10 +58,9 @@
"react-cron-antd": "^1.1.2", "react-cron-antd": "^1.1.2",
"react-dom": "16.12.0", "react-dom": "16.12.0",
"react-intl": "^3.2.1", "react-intl": "^3.2.1",
"react-joyride": "^2.5.0", "react-joyride": "^2.5.3",
"single-spa": "5.9.3", "single-spa": "5.9.3",
"single-spa-react": "2.14.0", "single-spa-react": "2.14.0",
"tree-changes": "0.9.1",
"webpack-bundle-analyzer": "^4.5.0" "webpack-bundle-analyzer": "^4.5.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -3,7 +3,8 @@ import '@babel/polyfill';
import React, { useState, useEffect, useLayoutEffect } from 'react'; import React, { useState, useEffect, useLayoutEffect } from 'react';
import { BrowserRouter, Switch, Route, useLocation, useHistory } from 'react-router-dom'; import { BrowserRouter, Switch, Route, useLocation, useHistory } from 'react-router-dom';
import { get as lodashGet } from 'lodash'; import { get as lodashGet } from 'lodash';
import { DProLayout, AppContainer, IconFont, Menu, Utils, Page403, Page404, Page500, Modal } from 'knowdesign'; import { DProLayout, AppContainer, Menu, Utils, Page403, Page404, Page500, Modal } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import dantdZhCN from 'knowdesign/es/locale/zh_CN'; import dantdZhCN from 'knowdesign/es/locale/zh_CN';
import dantdEnUS from 'knowdesign/es/locale/en_US'; import dantdEnUS from 'knowdesign/es/locale/en_US';
import { DotChartOutlined } from '@ant-design/icons'; import { DotChartOutlined } from '@ant-design/icons';

View File

@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import CardBar from './index'; import CardBar from './index';
import { IconFont, Tag, Utils, Tooltip, Popover, AppContainer } from 'knowdesign'; import { Tag, Utils, Tooltip, Popover, AppContainer } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import api from '@src/api'; import api from '@src/api';
import StateChart from './StateChart'; import StateChart from './StateChart';
import ClusterNorms from '@src/pages/LoadRebalance/ClusterNorms'; import ClusterNorms from '@src/pages/LoadRebalance/ClusterNorms';
@@ -138,15 +139,15 @@ const LoadRebalanceCardBar = (props: any) => {
// content={ // content={
// <div style={{ color: '#495057' }}> // <div style={{ color: '#495057' }}>
// <div> // <div>
// <IconFont className="cutomIcon" type="icon-chaoguo" /> // <IconFont className="cutomIcon cutomIcon-red" type="icon-chaoguo" />
// 超过均衡区间的有: {cpu?.bigNu || 0} // 超过均衡区间的有: {cpu?.bigNu || 0}
// </div> // </div>
// <div style={{ margin: '6px 0' }}> // <div style={{ margin: '6px 0' }}>
// <IconFont className="cutomIcon" type="icon-qujian" /> // <IconFont className="cutomIcon cutomIcon-green" type="icon-qujian" />
// 在均衡区间内的有: {cpu?.betweenNu || 0} // 在均衡区间内的有: {cpu?.betweenNu || 0}
// </div> // </div>
// <div> // <div>
// <IconFont className="cutomIcon" type="icon-diyu" /> // <IconFont className="cutomIcon cutomIcon-red" type="icon-diyu" />
// 低于均衡区间的有: {cpu?.smallNu || 0} // 低于均衡区间的有: {cpu?.smallNu || 0}
// </div> // </div>
// </div> // </div>
@@ -202,15 +203,15 @@ const LoadRebalanceCardBar = (props: any) => {
content={ content={
<div style={{ color: '#495057' }}> <div style={{ color: '#495057' }}>
<div> <div>
<IconFont className="cutomIcon" type="icon-chaoguo" /> <IconFont className="cutomIcon cutomIcon-red" type="icon-chaoguo" />
: {disk?.bigNu || 0} : {disk?.bigNu || 0}
</div> </div>
<div style={{ margin: '6px 0' }}> <div style={{ margin: '6px 0' }}>
<IconFont className="cutomIcon" type="icon-qujian" /> <IconFont className="cutomIcon cutomIcon-green" type="icon-qujian" />
: {disk?.betweenNu || 0} : {disk?.betweenNu || 0}
</div> </div>
<div> <div>
<IconFont className="cutomIcon" type="icon-diyu" /> <IconFont className="cutomIcon cutomIcon-red" type="icon-diyu" />
: {disk?.smallNu || 0} : {disk?.smallNu || 0}
</div> </div>
</div> </div>
@@ -267,15 +268,15 @@ const LoadRebalanceCardBar = (props: any) => {
content={ content={
<div style={{ color: '#495057' }}> <div style={{ color: '#495057' }}>
<div> <div>
<IconFont className="cutomIcon" type="icon-chaoguo" /> <IconFont className="cutomIcon cutomIcon-red" type="icon-chaoguo" />
: {bytesIn?.bigNu || 0} : {bytesIn?.bigNu || 0}
</div> </div>
<div style={{ margin: '6px 0' }}> <div style={{ margin: '6px 0' }}>
<IconFont className="cutomIcon" type="icon-qujian" /> <IconFont className="cutomIcon cutomIcon-green" type="icon-qujian" />
: {bytesIn?.betweenNu || 0} : {bytesIn?.betweenNu || 0}
</div> </div>
<div> <div>
<IconFont className="cutomIcon" type="icon-diyu" /> <IconFont className="cutomIcon cutomIcon-red" type="icon-diyu" />
: {bytesIn?.smallNu || 0} : {bytesIn?.smallNu || 0}
</div> </div>
</div> </div>
@@ -332,15 +333,15 @@ const LoadRebalanceCardBar = (props: any) => {
content={ content={
<div style={{ color: '#495057' }}> <div style={{ color: '#495057' }}>
<div> <div>
<IconFont className="cutomIcon" type="icon-chaoguo" /> <IconFont className="cutomIcon cutomIcon-red" type="icon-chaoguo" />
: {bytesOut?.bigNu || 0} : {bytesOut?.bigNu || 0}
</div> </div>
<div style={{ margin: '6px 0' }}> <div style={{ margin: '6px 0' }}>
<IconFont className="cutomIcon" type="icon-qujian" /> <IconFont className="cutomIcon cutomIcon-green" type="icon-qujian" />
: {bytesOut?.betweenNu || 0} : {bytesOut?.betweenNu || 0}
</div> </div>
<div> <div>
<IconFont className="cutomIcon" type="icon-diyu" /> <IconFont className="cutomIcon cutomIcon-red" type="icon-diyu" />
: {bytesOut?.smallNu || 0} : {bytesOut?.smallNu || 0}
</div> </div>
</div> </div>

View File

@@ -59,7 +59,7 @@ const EchartsExample = (props: any) => {
normal: { normal: {
color: (params: any) => { color: (params: any) => {
// 定义一个颜色数组colorList // 定义一个颜色数组colorList
const colorList = ['#00C0A2', '#CED4DA', '#FF7066']; const colorList = ['#FF7066', '#00C0A2', '#FF7066'];
return colorList[params.dataIndex]; return colorList[params.dataIndex];
}, },
}, },

View File

@@ -2,7 +2,8 @@ import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import CardBar from '@src/components/CardBar'; import CardBar from '@src/components/CardBar';
import { healthDataProps } from '.'; import { healthDataProps } from '.';
import { IconFont, Utils } from 'knowdesign'; import { Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import api from '@src/api'; import api from '@src/api';
import { healthScoreCondition } from './const'; import { healthScoreCondition } from './const';
import { hashDataParse } from '@src/constants/common'; import { hashDataParse } from '@src/constants/common';

View File

@@ -203,11 +203,19 @@
background: rgba(33, 37, 41, 0.04); background: rgba(33, 37, 41, 0.04);
} }
.cutomIcon { .anticon.cutomIcon {
display: inline-block; display: inline-block;
margin-right: 2px; margin-right: 2px;
} }
.anticon.cutomIcon-red {
color: #ff7066;
}
.anticon.cutomIcon-green {
color: #00c0a2;
}
.rebalance-tooltip { .rebalance-tooltip {
.dcloud-tooltip-inner { .dcloud-tooltip-inner {
min-height: 20px; min-height: 20px;

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { Drawer, IconFont, Select, Spin, Table } from 'knowdesign'; import { Drawer, Select, Spin, Table } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { Utils, Progress } from 'knowdesign'; import { Utils, Progress } from 'knowdesign';
import './index.less'; import './index.less';
import api from '@src/api'; import api from '@src/api';
@@ -110,8 +111,8 @@ const CardBar = (props: CardBarProps) => {
const promise = record const promise = record
? Utils.request(path) ? Utils.request(path)
: Utils.request(path, { : Utils.request(path, {
params: { dimensionCode: sceneObj.code }, params: { dimensionCode: sceneObj.code },
}); });
promise.then((data: any[]) => { promise.then((data: any[]) => {
setHealthCheckDetailList(data); setHealthCheckDetailList(data);
}); });

View File

@@ -0,0 +1,32 @@
.content-with-copy {
display: flex;
align-items: center;
.content {
flex: 1;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
}
.copy-icon {
width: 20px;
height: 20px;
padding-top: 2px;
border-radius: 50%;
margin-left: 4px;
font-size: 16px;
color: #adb5bc;
opacity: 0;
&:hover {
background: rgba(33, 37, 41, 0.04);
color: #74788d;
}
}
}
.dcloud-table-cell-row-hover {
.copy-icon {
opacity: 1;
}
}

View File

@@ -0,0 +1,35 @@
import { CheckCircleFilled } from '@ant-design/icons';
import { Tooltip } from 'knowdesign';
import React, { useState } from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
import { IconFont } from '@knowdesign/icons';
import './index.less';
const ContentWithCopy = (props: { content: string }) => {
const { content } = props;
const [visible, setVisible] = useState(false);
return (
<CopyToClipboard text={content}>
<div className="content-with-copy">
<Tooltip title={content}>
<span className="content">{content}</span>
</Tooltip>
{content && (
<Tooltip
title={
<span>
<CheckCircleFilled style={{ color: '#00b365' }} />
</span>
}
visible={visible}
onVisibleChange={() => setVisible(false)}
>
<IconFont className="copy-icon" type="icon-fuzhi" onClick={() => setVisible(true)} />
</Tooltip>
)}
</div>
</CopyToClipboard>
);
};
export default ContentWithCopy;

View File

@@ -1,5 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Input, IconFont } from 'knowdesign'; import { Input } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import './style/index.less'; import './style/index.less';
interface IObjectProps { interface IObjectProps {

View File

@@ -2,9 +2,10 @@ import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, use
import { AppContainer, Drawer, Spin, Table, SingleChart, Utils, Tooltip } from 'knowdesign'; import { AppContainer, Drawer, Spin, Table, SingleChart, Utils, Tooltip } from 'knowdesign';
import moment from 'moment'; import moment from 'moment';
import api, { MetricType } from '@src/api'; import api, { MetricType } from '@src/api';
import { MetricDefaultChartDataType, MetricChartDataType, formatChartData } from '@src/constants/chartConfig';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { MetricDefaultChartDataType, MetricChartDataType, formatChartData, getDetailChartConfig } from './config'; import { getDetailChartConfig } from './config';
import { UNIT_MAP } from '@src/constants/chartConfig'; import { UNIT_MAP } from '@src/constants/chartConfig';
import RenderEmpty from '../RenderEmpty'; import RenderEmpty from '../RenderEmpty';
@@ -50,8 +51,6 @@ interface DataZoomEventProps {
const DATA_ZOOM_DEFAULT_SCALE = 0.25; const DATA_ZOOM_DEFAULT_SCALE = 0.25;
// 单次向服务器请求数据的范围(默认 6 小时,超过后采集频率间隔会变长),单位: ms // 单次向服务器请求数据的范围(默认 6 小时,超过后采集频率间隔会变长),单位: ms
const DEFAULT_REQUEST_TIME_RANGE = 6 * 60 * 60 * 1000; const DEFAULT_REQUEST_TIME_RANGE = 6 * 60 * 60 * 1000;
// 采样间隔,影响前端补点逻辑,单位: ms
const DEFAULT_POINT_INTERVAL = 60 * 1000;
// 向服务器每轮请求的数量 // 向服务器每轮请求的数量
const DEFAULT_REQUEST_COUNT = 6; const DEFAULT_REQUEST_COUNT = 6;
// 进入详情页默认展示的时间范围 // 进入详情页默认展示的时间范围
@@ -376,8 +375,6 @@ const ChartDetail = (props: ChartDetailProps) => {
global.getMetricDefine || {}, global.getMetricDefine || {},
metricType, metricType,
timeRange, timeRange,
DEFAULT_POINT_INTERVAL,
false,
chartInfo.current.transformUnit chartInfo.current.transformUnit
) as MetricChartDataType[]; ) as MetricChartDataType[];
// 增量填充图表数据 // 增量填充图表数据
@@ -540,14 +537,7 @@ const ChartDetail = (props: ChartDetailProps) => {
if (res?.length) { if (res?.length) {
// 格式化图表需要的数据 // 格式化图表需要的数据
const formattedMetricData = ( const formattedMetricData = (
formatChartData( formatChartData(res, global.getMetricDefine || {}, metricType, curTimeRange) as MetricChartDataType[]
res,
global.getMetricDefine || {},
metricType,
curTimeRange,
DEFAULT_POINT_INTERVAL,
false
) as MetricChartDataType[]
)[0]; )[0];
// 填充图表数据 // 填充图表数据
let initFullTimeRange = curTimeRange; let initFullTimeRange = curTimeRange;

View File

@@ -1,150 +1,4 @@
import { getUnit, getDataNumberUnit, getBasicChartConfig, CHART_COLOR_LIST } from '@src/constants/chartConfig'; import { getBasicChartConfig, CHART_COLOR_LIST } from '@src/constants/chartConfig';
import { MetricType } from '@src/api';
import { MetricsDefine } from '@src/pages/CommonConfig';
export interface MetricInfo {
name: string;
desc: string;
type: number;
set: boolean;
support: boolean;
}
// 接口返回图表原始数据类型
export interface MetricDefaultChartDataType {
metricName: string;
metricLines: {
name: string;
createTime: number;
updateTime: number;
metricPoints: {
aggType: string;
timeStamp: number;
value: number;
createTime: number;
updateTime: number;
}[];
}[];
}
// 格式化后图表数据类型
export interface MetricChartDataType {
metricName: string;
metricUnit: string;
metricLines: {
name: string;
data: (string | number)[][];
}[];
dragKey?: number;
}
// 补点
export const supplementaryPoints = (
lines: MetricChartDataType['metricLines'],
timeRange: readonly [number, number],
interval: number,
extraCallback?: (point: [number, 0]) => any[]
) => {
lines.forEach(({ data }) => {
// 获取未补点前线条的点的个数
let len = data.length;
// 记录当前处理到的点的下标值
let i = 0;
for (; i < len; i++) {
if (i === 0) {
let firstPointTimestamp = data[0][0] as number;
while (firstPointTimestamp - interval > timeRange[0]) {
const prevPointTimestamp = firstPointTimestamp - interval;
data.unshift(extraCallback ? extraCallback([prevPointTimestamp, 0]) : [prevPointTimestamp, 0]);
firstPointTimestamp = prevPointTimestamp;
len++;
i++;
}
}
if (i === len - 1) {
let lastPointTimestamp = data[i][0] as number;
while (lastPointTimestamp + interval < timeRange[1]) {
const nextPointTimestamp = lastPointTimestamp + interval;
data.push(extraCallback ? extraCallback([nextPointTimestamp, 0]) : [nextPointTimestamp, 0]);
lastPointTimestamp = nextPointTimestamp;
}
break;
}
{
let timestamp = data[i][0] as number;
while (timestamp + interval < data[i + 1][0]) {
const nextPointTimestamp = timestamp + interval;
data.splice(i + 1, 0, extraCallback ? extraCallback([nextPointTimestamp, 0]) : [nextPointTimestamp, 0]);
timestamp = nextPointTimestamp;
len++;
i++;
}
}
}
});
};
// 格式化图表数据
export const formatChartData = (
metricData: MetricDefaultChartDataType[],
getMetricDefine: (type: MetricType, metric: string) => MetricsDefine[keyof MetricsDefine],
metricType: MetricType,
timeRange: readonly [number, number],
supplementaryInterval: number,
needDrag = false,
transformUnit: [string, number] = undefined
): MetricChartDataType[] => {
return metricData.map(({ metricName, metricLines }) => {
const curMetricInfo = (getMetricDefine && getMetricDefine(metricType, metricName)) || null;
const isByteUnit = curMetricInfo?.unit?.toLowerCase().includes('byte');
let maxValue = -1;
const PointsMapMethod = ({ timeStamp, value }: { timeStamp: number; value: string | number }) => {
let parsedValue: string | number = Number(value);
if (Number.isNaN(parsedValue)) {
parsedValue = value;
} else {
// 为避免出现过小的数字影响图表展示效果,图表值统一只保留到小数点后三位
parsedValue = parseFloat(parsedValue.toFixed(3));
if (maxValue < parsedValue) maxValue = parsedValue;
}
return [timeStamp, parsedValue];
};
const chartData = Object.assign(
{
metricName,
metricUnit: curMetricInfo?.unit || '',
metricLines: metricLines
.sort((a, b) => Number(a.name < b.name) - 0.5)
.map(({ name, metricPoints }) => ({
name,
data: metricPoints.map(PointsMapMethod),
})),
},
needDrag ? { dragKey: 999 } : {}
);
chartData.metricLines.forEach(({ data }) => data.sort((a, b) => (a[0] as number) - (b[0] as number)));
supplementaryPoints(chartData.metricLines, timeRange, supplementaryInterval);
// 将所有图表点的值按单位进行转换
if (maxValue > 0) {
const [unitName, unitSize]: [string, number] = transformUnit || isByteUnit ? getUnit(maxValue) : getDataNumberUnit(maxValue);
chartData.metricUnit = isByteUnit
? chartData.metricUnit.toLowerCase().replace('byte', unitName)
: `${unitName}${chartData.metricUnit}`;
chartData.metricLines.forEach(({ data }) => data.forEach((point: any) => (point[1] /= unitSize)));
}
return chartData;
});
};
const seriesCallback = (lines: { name: string; data: [number, string | number][] }[]) => { const seriesCallback = (lines: { name: string; data: [number, string | number][] }[]) => {
const len = CHART_COLOR_LIST.length; const len = CHART_COLOR_LIST.length;

View File

@@ -1,14 +1,21 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { arrayMoveImmutable } from 'array-move'; import { arrayMoveImmutable } from 'array-move';
import { Utils, Empty, IconFont, Spin, AppContainer, SingleChart, Tooltip } from 'knowdesign'; import { Utils, Empty, Spin, AppContainer, SingleChart, Tooltip } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import api, { MetricType } from '@src/api'; import api, { MetricType } from '@src/api';
import {
MetricInfo,
MetricDefaultChartDataType,
MetricChartDataType,
formatChartData,
resolveMetricsRank,
} from '@src/constants/chartConfig';
import SingleChartHeader, { KsHeaderOptions } from '../SingleChartHeader'; import SingleChartHeader, { KsHeaderOptions } from '../SingleChartHeader';
import DragGroup from '../DragGroup'; import DragGroup from '../DragGroup';
import ChartDetail from './ChartDetail'; import ChartDetail from './ChartDetail';
import { MetricInfo, MetricDefaultChartDataType, MetricChartDataType, formatChartData, getChartConfig } from './config'; import { getChartConfig } from './config';
import './index.less'; import './index.less';
import { MAX_TIME_RANGE_WITH_SMALL_POINT_INTERVAL } from '@src/constants/common';
interface IcustomScope { interface IcustomScope {
label: string; label: string;
@@ -39,8 +46,8 @@ const DashboardDragChart = (props: PropsType): JSX.Element => {
const [curHeaderOptions, setCurHeaderOptions] = useState<ChartFilterOptions>(); const [curHeaderOptions, setCurHeaderOptions] = useState<ChartFilterOptions>();
const [metricChartData, setMetricChartData] = useState<MetricChartDataType[]>([]); // 指标图表数据列表 const [metricChartData, setMetricChartData] = useState<MetricChartDataType[]>([]); // 指标图表数据列表
const [gridNum, setGridNum] = useState<number>(12); // 图表列布局 const [gridNum, setGridNum] = useState<number>(12); // 图表列布局
const metricRankList = useRef<string[]>([]);
const chartDetailRef = useRef(null); const chartDetailRef = useRef(null);
const chartDragOrder = useRef([]);
const curFetchingTimestamp = useRef(0); const curFetchingTimestamp = useRef(0);
// 获取节点范围列表 // 获取节点范围列表
@@ -60,23 +67,33 @@ const DashboardDragChart = (props: PropsType): JSX.Element => {
setScopeList(list); setScopeList(list);
}; };
// 更新 rank
const updateRank = (metricList: MetricInfo[]) => {
const { list, listInfo, shouldUpdate } = resolveMetricsRank(metricList);
metricRankList.current = list;
if (shouldUpdate) {
setMetricList(listInfo);
}
};
// 获取指标列表 // 获取指标列表
const getMetricList = () => { const getMetricList = () => {
Utils.request(api.getDashboardMetricList(clusterId, dashboardType)).then((res: MetricInfo[] | null) => { Utils.request(api.getDashboardMetricList(clusterId, dashboardType)).then((res: MetricInfo[] | null) => {
if (!res) return; if (!res) return;
const showMetrics = res.filter((metric) => metric.support); const supportMetrics = res.filter((metric) => metric.support);
const selectedMetrics = showMetrics.filter((metric) => metric.set).map((metric) => metric.name); const selectedMetrics = supportMetrics.filter((metric) => metric.set).map((metric) => metric.name);
setMetricsList(showMetrics); updateRank([...supportMetrics]);
setMetricsList(supportMetrics);
setSelectedMetricNames(selectedMetrics); setSelectedMetricNames(selectedMetrics);
}); });
}; };
// 更新指标 // 更新指标
const setMetricList = (metricsSet: { [name: string]: boolean }) => { const setMetricList = (metricDetailDTOList: { metric: string; rank: number; set: boolean }[]) => {
return Utils.request(api.getDashboardMetricList(clusterId, dashboardType), { return Utils.request(api.getDashboardMetricList(clusterId, dashboardType), {
method: 'POST', method: 'POST',
data: { data: {
metricsSet, metricDetailDTOList,
}, },
}); });
}; };
@@ -84,10 +101,11 @@ const DashboardDragChart = (props: PropsType): JSX.Element => {
// 根据筛选项获取图表信息 // 根据筛选项获取图表信息
const getMetricChartData = () => { const getMetricChartData = () => {
!curHeaderOptions.isAutoReload && setLoading(true); !curHeaderOptions.isAutoReload && setLoading(true);
const [startTime, endTime] = curHeaderOptions.rangeTime;
const [startTime, endTime] = curHeaderOptions.rangeTime;
const curTimestamp = Date.now(); const curTimestamp = Date.now();
curFetchingTimestamp.current = curTimestamp; curFetchingTimestamp.current = curTimestamp;
Utils.post(api.getDashboardMetricChartData(clusterId, dashboardType), { Utils.post(api.getDashboardMetricChartData(clusterId, dashboardType), {
startTime, startTime,
endTime, endTime,
@@ -108,36 +126,20 @@ const DashboardDragChart = (props: PropsType): JSX.Element => {
setMetricChartData([]); setMetricChartData([]);
} else { } else {
// 格式化图表需要的数据 // 格式化图表需要的数据
const supplementaryInterval = (endTime - startTime > MAX_TIME_RANGE_WITH_SMALL_POINT_INTERVAL ? 10 : 1) * 60 * 1000;
const formattedMetricData = formatChartData( const formattedMetricData = formatChartData(
res, res,
global.getMetricDefine || {}, global.getMetricDefine || {},
dashboardType, dashboardType,
curHeaderOptions.rangeTime, curHeaderOptions.rangeTime
supplementaryInterval,
true
) as MetricChartDataType[]; ) as MetricChartDataType[];
// 处理图表的拖拽顺 // 指标排
if (chartDragOrder.current && chartDragOrder.current.length) { formattedMetricData.sort((a, b) => metricRankList.current.indexOf(a.metricName) - metricRankList.current.indexOf(b.metricName));
// 根据当前拖拽顺序排列图表数据
formattedMetricData.forEach((metric) => {
const i = chartDragOrder.current.indexOf(metric.metricName);
metric.dragKey = i === -1 ? 999 : i;
});
formattedMetricData.sort((a, b) => a.dragKey - b.dragKey);
}
// 更新当前拖拽顺序(处理新增或减少图表的情况)
chartDragOrder.current = formattedMetricData.map((data) => data.metricName);
setMetricChartData(formattedMetricData); setMetricChartData(formattedMetricData);
} }
setLoading(false); setLoading(false);
}, },
() => { () => curFetchingTimestamp.current === curTimestamp && setLoading(false)
if (curFetchingTimestamp.current === curTimestamp) {
setLoading(false);
}
}
); );
}; };
@@ -163,11 +165,19 @@ const DashboardDragChart = (props: PropsType): JSX.Element => {
// 指标选中项更新回调 // 指标选中项更新回调
const indicatorChangeCallback = (newMetricNames: (string | number)[]) => { const indicatorChangeCallback = (newMetricNames: (string | number)[]) => {
const updateMetrics: { [name: string]: boolean } = {}; const updateMetrics: { metric: string; set: boolean; rank: number }[] = [];
// 需要选中的指标 // 需要选中的指标
newMetricNames.forEach((name) => !selectedMetricNames.includes(name) && (updateMetrics[name] = true)); newMetricNames.forEach(
(name) =>
!selectedMetricNames.includes(name) &&
updateMetrics.push({ metric: name as string, set: true, rank: metricsList.find(({ name: metric }) => metric === name)?.rank })
);
// 取消选中的指标 // 取消选中的指标
selectedMetricNames.forEach((name) => !newMetricNames.includes(name) && (updateMetrics[name] = false)); selectedMetricNames.forEach(
(name) =>
!newMetricNames.includes(name) &&
updateMetrics.push({ metric: name as string, set: false, rank: metricsList.find(({ name: metric }) => metric === name)?.rank })
);
const requestPromise = Object.keys(updateMetrics).length ? setMetricList(updateMetrics) : Promise.resolve(); const requestPromise = Object.keys(updateMetrics).length ? setMetricList(updateMetrics) : Promise.resolve();
requestPromise.then( requestPromise.then(
@@ -186,7 +196,11 @@ const DashboardDragChart = (props: PropsType): JSX.Element => {
// 拖拽结束回调,更新图表顺序,并触发图表的 onDrag 事件( 设置为 false ),允许同步展示图表的 tooltip // 拖拽结束回调,更新图表顺序,并触发图表的 onDrag 事件( 设置为 false ),允许同步展示图表的 tooltip
const dragEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => { const dragEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
busInstance.emit('onDrag', false); busInstance.emit('onDrag', false);
chartDragOrder.current = arrayMoveImmutable(chartDragOrder.current, oldIndex, newIndex); const originFrom = metricRankList.current.indexOf(metricChartData[oldIndex].metricName);
const originTarget = metricRankList.current.indexOf(metricChartData[newIndex].metricName);
const newList = arrayMoveImmutable(metricRankList.current, originFrom, originTarget);
metricRankList.current = newList;
setMetricList(newList.map((metric, rank) => ({ metric, rank, set: metricsList.find(({ name }) => metric === name)?.set || false })));
setMetricChartData(arrayMoveImmutable(metricChartData, oldIndex, newIndex)); setMetricChartData(arrayMoveImmutable(metricChartData, oldIndex, newIndex));
}; };

View File

@@ -1,4 +1,5 @@
import { Col, IconFont, Row } from 'knowdesign'; import { Col, Row } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import React from 'react'; import React from 'react';
import { SortableContainer, SortableContainerProps, SortableHandle, SortableElement, SortableElementProps } from 'react-sortable-hoc'; import { SortableContainer, SortableContainerProps, SortableHandle, SortableElement, SortableElementProps } from 'react-sortable-hoc';
import './index.less'; import './index.less';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Drawer, Button, Space, Divider, AppContainer, ProTable, IconFont } from 'knowdesign'; import { Drawer, Button, Space, Divider, AppContainer, ProTable } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { IindicatorSelectModule } from './index'; import { IindicatorSelectModule } from './index';
import './style/indicator-drawer.less'; import './style/indicator-drawer.less';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Radio, Input, Popover, Space, Checkbox, Row, Col, Button, IconFont } from 'knowdesign'; import { Radio, Input, Popover, Space, Checkbox, Row, Col, Button } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { InodeScopeModule } from './index'; import { InodeScopeModule } from './index';
import './style/node-scope.less'; import './style/node-scope.less';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Tooltip, Select, IconFont, Utils, Divider, Button } from 'knowdesign'; import { Tooltip, Select, Utils, Divider, Button } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import moment from 'moment'; import moment from 'moment';
import { DRangeTime } from 'knowdesign'; import { DRangeTime } from 'knowdesign';
import IndicatorDrawer from './IndicatorDrawer'; import IndicatorDrawer from './IndicatorDrawer';

View File

@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { ArrowLeftOutlined } from '@ant-design/icons'; import { ArrowLeftOutlined } from '@ant-design/icons';
import { Button, Divider, Drawer, IconFont, Select, Space, Table, Utils } from 'knowdesign'; import { Button, Divider, Drawer, Select, Space, Table, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import Api, { MetricType } from '@src/api/index'; import Api, { MetricType } from '@src/api/index';
const { Option } = Select; const { Option } = Select;

View File

@@ -18,9 +18,9 @@ import {
Space, Space,
Divider, Divider,
Transfer, Transfer,
IconFont,
Tooltip, Tooltip,
} from 'knowdesign'; } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import './index.less'; import './index.less';
import Api, { MetricType } from '@src/api/index'; import Api, { MetricType } from '@src/api/index';
import moment from 'moment'; import moment from 'moment';

View File

@@ -1,5 +1,44 @@
import moment from 'moment'; import moment from 'moment';
import { MetricType } from '@src/api';
import { MetricsDefine } from '@src/pages/CommonConfig';
export interface MetricInfo {
name: string;
desc: string;
type: number;
set: boolean;
rank: number | null;
support: boolean;
}
// 接口返回图表原始数据类型
export interface MetricDefaultChartDataType {
metricName: string;
metricLines: {
name: string;
createTime: number;
updateTime: number;
metricPoints: {
aggType: string;
timeStamp: number;
value: number;
createTime: number;
updateTime: number;
}[];
}[];
}
// 格式化后图表数据类型
export interface MetricChartDataType {
metricName: string;
metricUnit: string;
metricLines: {
name: string;
data: (string | number)[][];
}[];
}
// 图表颜色库
export const CHART_COLOR_LIST = [ export const CHART_COLOR_LIST = [
'#556ee6', '#556ee6',
'#94BEF2', '#94BEF2',
@@ -16,27 +55,176 @@ export const CHART_COLOR_LIST = [
'#C9E795', '#C9E795',
]; ];
// 图表存储单位换算
export const UNIT_MAP = { export const UNIT_MAP = {
TB: Math.pow(1024, 4), TB: Math.pow(1024, 4),
GB: Math.pow(1024, 3), GB: Math.pow(1024, 3),
MB: Math.pow(1024, 2), MB: Math.pow(1024, 2),
KB: 1024, KB: 1024,
}; };
export const getUnit = (value: number) => Object.entries(UNIT_MAP).find(([, size]) => value / size >= 1) || ['Byte', 1];
// 图表数字单位换算
export const DATA_NUMBER_MAP = { export const DATA_NUMBER_MAP = {
十亿: Math.pow(1000, 3), 十亿: Math.pow(1000, 3),
百万: Math.pow(1000, 2), 百万: Math.pow(1000, 2),
: 1000, : 1000,
}; };
export const getUnit = (value: number) => Object.entries(UNIT_MAP).find(([, size]) => value / size >= 1) || ['Byte', 1];
export const getDataNumberUnit = (value: number) => Object.entries(DATA_NUMBER_MAP).find(([, size]) => value / size >= 1) || ['', 1]; export const getDataNumberUnit = (value: number) => Object.entries(DATA_NUMBER_MAP).find(([, size]) => value / size >= 1) || ['', 1];
// 图表补点间隔计算
export const SUPPLEMENTARY_INTERVAL_MAP = {
'0': 60 * 1000,
// 6 小时10 分钟间隔
'21600000': 10 * 60 * 1000,
// 24 小时1 小时间隔
'86400000': 60 * 60 * 1000,
};
export const getSupplementaryInterval = (range: number) => {
return Object.entries(SUPPLEMENTARY_INTERVAL_MAP)
.reverse()
.find(([curRange]) => range > Number(curRange))[1];
};
// 处理图表排序
export const resolveMetricsRank = (metricList: MetricInfo[]) => {
const isRanked = metricList.some(({ rank }) => rank !== null);
let shouldUpdate = false;
let list: string[] = [];
if (isRanked) {
const rankedMetrics = metricList.filter(({ rank }) => rank !== null).sort((a, b) => a.rank - b.rank);
const unRankedMetrics = metricList.filter(({ rank }) => rank === null);
// 如果有新增/删除指标的情况,需要触发更新
if (unRankedMetrics.length || rankedMetrics.some(({ rank }, i) => rank !== i)) {
shouldUpdate = true;
}
list = [...rankedMetrics.map(({ name }) => name), ...unRankedMetrics.map(({ name }) => name).sort()];
} else {
shouldUpdate = true;
// 按字母先后顺序初始化指标排序
list = metricList.map(({ name }) => name).sort();
}
return {
list,
listInfo: list.map((metric, rank) => ({ metric, rank, set: metricList.find(({ name }) => metric === name)?.set || false })),
shouldUpdate,
};
};
// 补点
export const supplementaryPoints = (
lines: MetricChartDataType['metricLines'],
timeRange: readonly [number, number],
extraCallback?: (point: [number, 0]) => any[]
): void => {
const interval = getSupplementaryInterval(timeRange[1] - timeRange[0]);
lines.forEach(({ data }) => {
// 获取未补点前线条的点的个数
let len = data.length;
// 记录当前处理到的点的下标值
let i = 0;
for (; i < len; i++) {
if (i === 0) {
let firstPointTimestamp = data[0][0] as number;
while (firstPointTimestamp - interval > timeRange[0]) {
const prevPointTimestamp = firstPointTimestamp - interval;
data.unshift(extraCallback ? extraCallback([prevPointTimestamp, 0]) : [prevPointTimestamp, 0]);
firstPointTimestamp = prevPointTimestamp;
len++;
i++;
}
}
if (i === len - 1) {
let lastPointTimestamp = data[i][0] as number;
while (lastPointTimestamp + interval < timeRange[1]) {
const nextPointTimestamp = lastPointTimestamp + interval;
data.push(extraCallback ? extraCallback([nextPointTimestamp, 0]) : [nextPointTimestamp, 0]);
lastPointTimestamp = nextPointTimestamp;
}
break;
}
{
let timestamp = data[i][0] as number;
while (timestamp + interval < data[i + 1][0]) {
const nextPointTimestamp = timestamp + interval;
data.splice(i + 1, 0, extraCallback ? extraCallback([nextPointTimestamp, 0]) : [nextPointTimestamp, 0]);
timestamp = nextPointTimestamp;
len++;
i++;
}
}
}
});
};
// 格式化图表数据
export const formatChartData = (
// 图表源数据
metricData: MetricDefaultChartDataType[],
// 获取指标单位
getMetricDefine: (type: MetricType, metric: string) => MetricsDefine[keyof MetricsDefine],
// 指标类型
metricType: MetricType,
// 图表时间范围,用于补点
timeRange: readonly [number, number],
transformUnit: [string, number] = undefined
): MetricChartDataType[] => {
return metricData.map(({ metricName, metricLines }) => {
const curMetricInfo = (getMetricDefine && getMetricDefine(metricType, metricName)) || null;
const isByteUnit = curMetricInfo?.unit?.toLowerCase().includes('byte');
let maxValue = -1;
const PointsMapMethod = ({ timeStamp, value }: { timeStamp: number; value: string | number }) => {
let parsedValue: string | number = Number(value);
if (Number.isNaN(parsedValue)) {
parsedValue = value;
} else {
// 为避免出现过小的数字影响图表展示效果,图表值统一保留小数点后三位
parsedValue = parseFloat(parsedValue.toFixed(3));
if (maxValue < parsedValue) maxValue = parsedValue;
}
return [timeStamp, parsedValue];
};
// 初始化返回结构
const chartData = {
metricName,
metricUnit: curMetricInfo?.unit || '',
metricLines: metricLines
.sort((a, b) => Number(a.name < b.name) - 0.5)
.map(({ name, metricPoints }) => ({
name,
data: metricPoints.map(PointsMapMethod),
})),
};
// 按时间先后进行对图表点排序
chartData.metricLines.forEach(({ data }) => data.sort((a, b) => (a[0] as number) - (b[0] as number)));
// 图表值单位转换
if (maxValue > 0) {
const [unitName, unitSize]: [string, number] = transformUnit || isByteUnit ? getUnit(maxValue) : getDataNumberUnit(maxValue);
chartData.metricUnit = isByteUnit
? chartData.metricUnit.toLowerCase().replace('byte', unitName)
: `${unitName}${chartData.metricUnit}`;
chartData.metricLines.forEach(({ data }) => data.forEach((point: any) => (point[1] /= unitSize)));
}
// 补点
supplementaryPoints(chartData.metricLines, timeRange);
return chartData;
});
};
// 图表 tooltip 基础展示样式 // 图表 tooltip 基础展示样式
const tooltipFormatter = (date: any, arr: any, tooltip: any) => { const tooltipFormatter = (date: any, arr: any, tooltip: any) => {
// 从大到小排序
// arr = arr.sort((a: any, b: any) => b.value - a.value);
const str = arr const str = arr
.map( .map(
(item: any) => `<div style="margin: 3px 0;"> (item: any) => `<div style="margin: 3px 0;">
@@ -121,9 +309,6 @@ export const getBasicChartConfig = (props: any = {}) => {
itemWidth: 8, itemWidth: 8,
itemGap: 8, itemGap: 8,
textStyle: { textStyle: {
// width: 85,
// overflow: 'truncate',
// ellipsis: '...',
fontSize: 11, fontSize: 11,
color: '#74788D', color: '#74788D',
}, },

View File

@@ -37,9 +37,6 @@ export const SMALL_DRAWER_WIDTH = 480;
export const MIDDLE_DRAWER_WIDTH = 728; export const MIDDLE_DRAWER_WIDTH = 728;
export const LARGE_DRAWER_WIDTH = 1080; export const LARGE_DRAWER_WIDTH = 1080;
// 小间隔1 分钟)图表点的最大请求时间范围,单位: ms
export const MAX_TIME_RANGE_WITH_SMALL_POINT_INTERVAL = 6 * 60 * 60 * 1000;
export const primaryColor = '#556EE6'; export const primaryColor = '#556EE6';
export const numberToFixed = (value: number, num = 2) => { export const numberToFixed = (value: number, num = 2) => {

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useParams, useHistory, useLocation } from 'react-router-dom'; import { useParams, useHistory, useLocation } from 'react-router-dom';
import { ProTable, Utils, AppContainer, SearchInput, IconFont } from 'knowdesign'; import { ProTable, Utils, AppContainer, SearchInput } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import API from '../../api'; import API from '../../api';
import { getControllerChangeLogListColumns, defaultPagination } from './config'; import { getControllerChangeLogListColumns, defaultPagination } from './config';
import BrokerDetail from '../BrokerDetail'; import BrokerDetail from '../BrokerDetail';

View File

@@ -1,5 +1,6 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Drawer, Form, Input, Space, Button, Checkbox, Utils, Row, Col, IconFont, Divider, message } from 'knowdesign'; import { Drawer, Form, Input, Space, Button, Checkbox, Utils, Row, Col, Divider, message } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import Api from '@src/api'; import Api from '@src/api';
export const ConfigurationEdit = (props: any) => { export const ConfigurationEdit = (props: any) => {

View File

@@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Utils, IconFont, Tooltip } from 'knowdesign'; import { Utils, Tooltip } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
export const getConfigurationColmns = (arg: any) => { export const getConfigurationColmns = (arg: any) => {
const columns: any = [ const columns: any = [
{ {

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect, memo } from 'react'; import React, { useState, useEffect, memo } from 'react';
import { useParams, useHistory, useLocation } from 'react-router-dom'; import { useParams, useHistory, useLocation } from 'react-router-dom';
import { ProTable, Drawer, Utils, AppContainer, SearchInput, IconFont } from 'knowdesign'; import { ProTable, Drawer, Utils, AppContainer, SearchInput } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import API from '../../api'; import API from '../../api';
import { getBrokerListColumns, defaultPagination } from './config'; import { getBrokerListColumns, defaultPagination } from './config';
import { tableHeaderPrefix } from '@src/constants/common'; import { tableHeaderPrefix } from '@src/constants/common';

View File

@@ -1,15 +1,15 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useParams, useHistory } from 'react-router-dom'; import { useParams, useHistory } from 'react-router-dom';
import CopyToClipboard from 'react-copy-to-clipboard'; import { AppContainer, Divider, Drawer, ProTable, Select, SingleChart, Space, Tooltip, Utils } from 'knowdesign';
import { AppContainer, Divider, Drawer, IconFont, ProTable, Select, SingleChart, Space, Tooltip, Utils } from 'knowdesign'; import { IconFont } from '@knowdesign/icons';
import { DRangeTime } from 'knowdesign'; import { DRangeTime } from 'knowdesign';
import { CHART_COLOR_LIST, getBasicChartConfig } from '@src/constants/chartConfig'; import { CHART_COLOR_LIST, getBasicChartConfig } from '@src/constants/chartConfig';
import Api from '@src/api/index'; import Api from '@src/api/index';
import { hashDataParse } from '@src/constants/common'; import { hashDataParse } from '@src/constants/common';
import { ClustersPermissionMap } from '../CommonConfig'; import { ClustersPermissionMap } from '../CommonConfig';
import ResetOffsetDrawer from './ResetOffsetDrawer'; import ResetOffsetDrawer from './ResetOffsetDrawer';
import { CheckCircleFilled } from '@ant-design/icons';
import SwitchTab from '@src/components/SwitchTab'; import SwitchTab from '@src/components/SwitchTab';
import ContentWithCopy from '@src/components/CopyContent';
const { Option } = Select; const { Option } = Select;
@@ -44,33 +44,6 @@ const metricWithType = [
{ metricName: 'Lag', metricType: 102 }, { metricName: 'Lag', metricType: 102 },
]; ];
const ContentWithCopy = (props: { content: string }) => {
const { content } = props;
const [visible, setVisible] = useState(false);
return (
<CopyToClipboard text={content}>
<div className="content-with-copy">
<Tooltip title={content}>
<span className="content">{content}</span>
</Tooltip>
{content && (
<Tooltip
title={
<span>
<CheckCircleFilled style={{ color: '#00b365' }} />
</span>
}
visible={visible}
onVisibleChange={() => setVisible(false)}
>
<IconFont className="copy-icon" type="icon-fuzhi" onClick={() => setVisible(true)} />
</Tooltip>
)}
</div>
</CopyToClipboard>
);
};
export default (props: any) => { export default (props: any) => {
const { scene } = props; const { scene } = props;
const params = useParams<{ const params = useParams<{
@@ -104,6 +77,9 @@ export default (props: any) => {
title: 'Topic Partition', title: 'Topic Partition',
dataIndex: 'partitionId', dataIndex: 'partitionId',
key: 'partitionId', key: 'partitionId',
lineClampOne: true,
needTooltip: true,
width: 180,
render: (v: string, record: any) => { render: (v: string, record: any) => {
return `${record.topicName}-${v}`; return `${record.topicName}-${v}`;
}, },

View File

@@ -1,6 +1,7 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { AppContainer, Divider, Form, IconFont, Input, ProTable, Select, Utils } from 'knowdesign'; import { AppContainer, Divider, Form, Input, ProTable, Select, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import './index.less'; import './index.less';
import Api from '@src/api/index'; import Api from '@src/api/index';
import { getOperatingStateListParams } from './interface'; import { getOperatingStateListParams } from './interface';

View File

@@ -1,6 +1,7 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Alert, Badge, Dropdown, IconFont, ProTable, Space, Table, Utils } from 'knowdesign'; import { Alert, Badge, Dropdown, ProTable, Space, Table, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import Api from '@src/api'; import Api from '@src/api';
import { getTaskDetailsColumns, getMoveBalanceColumns } from './config'; import { getTaskDetailsColumns, getMoveBalanceColumns } from './config';

View File

@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import moment from 'moment'; import moment from 'moment';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { Button, Drawer, Utils, Descriptions, Tabs, Input, IconFont, message, Spin, InputNumber } from 'knowdesign'; import { Button, Drawer, Utils, Descriptions, Tabs, Input, message, Spin, InputNumber } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import TaskDetails from './TeskDetails'; import TaskDetails from './TeskDetails';
import NodeTraffic from './NodeTraffic'; import NodeTraffic from './NodeTraffic';
import RebalancePlan from './RebalancePlan'; import RebalancePlan from './RebalancePlan';

View File

@@ -89,12 +89,9 @@ export const getJobsListColumns = (arg?: any) => {
title: '任务执行对象', title: '任务执行对象',
dataIndex: 'target', dataIndex: 'target',
key: 'target', key: 'target',
width: 232,
render(t: any, r: any) { render(t: any, r: any) {
return ( return <TagsWithHide placement="bottom" list={t.split(',')} expandTagContent={(num: any) => `共有${num}`} />;
<div style={{ width: '232px' }}>
<TagsWithHide placement="bottom" list={t.split(',')} expandTagContent={(num: any) => `共有${num}`} />
</div>
);
}, },
}, },
{ {

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect, memo } from 'react'; import React, { useState, useEffect, memo } from 'react';
import { useParams, useHistory, useLocation } from 'react-router-dom'; import { useParams, useHistory, useLocation } from 'react-router-dom';
import { ProTable, Drawer, Utils, AppContainer, Form, Select, Input, Button, message, Modal, IconFont, Divider } from 'knowdesign'; import { ProTable, Drawer, Utils, AppContainer, Form, Select, Input, Button, message, Modal, Divider } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import API from '../../api'; import API from '../../api';
import { getJobsListColumns, defaultPagination, runningStatus, jobType } from './config'; import { getJobsListColumns, defaultPagination, runningStatus, jobType } from './config';
import JobsCheck from '@src/components/CardBar/JobsCheck'; import JobsCheck from '@src/components/CardBar/JobsCheck';

View File

@@ -12,10 +12,9 @@ import {
Transfer, Transfer,
Select, Select,
message, message,
IconFont,
Tooltip, Tooltip,
} from 'knowdesign'; } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import CronInput from './CronInput'; import CronInput from './CronInput';
import BalanceEditTable from './BalanceEditTable'; import BalanceEditTable from './BalanceEditTable';
import PlanDrawer from './PlanDrawer'; import PlanDrawer from './PlanDrawer';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Button, Popover, IconFont, Row, Col, Select } from 'knowdesign'; import { Button, Popover, Row, Col, Select } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
const balancePrefix = 'custom-popover-balance'; const balancePrefix = 'custom-popover-balance';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Utils, Drawer, Button, Form, Space, Divider, AppContainer, Input, Transfer, message, IconFont, InputNumber } from 'knowdesign'; import { Utils, Drawer, Button, Form, Space, Divider, AppContainer, Input, Transfer, message, InputNumber } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import api from '../../api'; import api from '../../api';
import './style/BalanceDrawer.less'; import './style/BalanceDrawer.less';

View File

@@ -1,5 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { message, Drawer, Button, Space, Divider, AppContainer, IconFont } from 'knowdesign'; import { message, Drawer, Button, Space, Divider, AppContainer } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import RebalancePlan from '../Jobs/RebalancePlan'; import RebalancePlan from '../Jobs/RebalancePlan';
interface PropsType extends React.HTMLAttributes<HTMLDivElement> { interface PropsType extends React.HTMLAttributes<HTMLDivElement> {

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Select, Form, Utils, AppContainer, Input, Button, ProTable, Badge, Tag, SearchInput, IconFont, Divider } from 'knowdesign'; import { Select, Form, Utils, AppContainer, Input, Button, ProTable, Badge, Tag, SearchInput, Divider } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import BalanceDrawer from './BalanceDrawer'; import BalanceDrawer from './BalanceDrawer';
import HistoryDrawer from './HistoryDrawer'; import HistoryDrawer from './HistoryDrawer';
import DBreadcrumb from 'knowdesign/es/extend/d-breadcrumb'; import DBreadcrumb from 'knowdesign/es/extend/d-breadcrumb';
@@ -133,7 +134,7 @@ const LoadBalance: React.FC = (props: any) => {
key: 'disk_spec', key: 'disk_spec',
width: '150px', width: '150px',
render: (text: any, row: any) => { render: (text: any, row: any) => {
return text !== null ? `${text}GB` : '-'; return text !== null ? `${text.toLocaleString()}GB` : '-';
}, },
}, },
{ {
@@ -145,7 +146,10 @@ const LoadBalance: React.FC = (props: any) => {
return text !== null ? ( return text !== null ? (
<span> <span>
<Badge status={row?.disk_status === 0 ? 'success' : 'error'} /> <Badge status={row?.disk_status === 0 ? 'success' : 'error'} />
{`${getSizeAndUnit(text, 'B').valueWithUnit} (${((row.disk_avg * 100) / Utils.transGBToB(row.disk_spec)).toFixed(2)}%)`} {`${getSizeAndUnit(text, 'B').valueWithUnit.toLocaleString()} (${(
(row.disk_avg * 100) /
Utils.transGBToB(row.disk_spec)
).toFixed(2)}%)`}
</span> </span>
) : ( ) : (
'-' '-'
@@ -158,7 +162,7 @@ const LoadBalance: React.FC = (props: any) => {
key: 'bytesIn_spec', key: 'bytesIn_spec',
width: '150px', width: '150px',
render: (text: any, row: any) => { render: (text: any, row: any) => {
return text !== null ? `${text}MB/s` : '-'; return text !== null ? `${text.toLocaleString()}MB/s` : '-';
}, },
}, },
{ {
@@ -170,7 +174,10 @@ const LoadBalance: React.FC = (props: any) => {
return text !== null ? ( return text !== null ? (
<span> <span>
<Badge status={row?.bytesIn_status === 0 ? 'success' : 'error'} /> <Badge status={row?.bytesIn_status === 0 ? 'success' : 'error'} />
{`${getSizeAndUnit(text, 'B/s').valueWithUnit} (${((row.bytesIn_avg * 100) / (row.bytesIn_spec * 1024 * 1024)).toFixed(2)}%)`} {`${getSizeAndUnit(text, 'B/s').valueWithUnit.toLocaleString()} (${(
(row.bytesIn_avg * 100) /
(row.bytesIn_spec * 1024 * 1024)
).toFixed(2)}%)`}
</span> </span>
) : ( ) : (
'-' '-'
@@ -183,7 +190,7 @@ const LoadBalance: React.FC = (props: any) => {
key: 'bytesOut_spec', key: 'bytesOut_spec',
width: '150px', width: '150px',
render: (text: any, row: any) => { render: (text: any, row: any) => {
return text !== null ? `${text}MB/s` : '-'; return text !== null ? `${text.toLocaleString()}MB/s` : '-';
}, },
}, },
{ {
@@ -196,7 +203,10 @@ const LoadBalance: React.FC = (props: any) => {
return text !== null ? ( return text !== null ? (
<span> <span>
<Badge status={row?.bytesOut_status === 0 ? 'success' : 'error'} /> <Badge status={row?.bytesOut_status === 0 ? 'success' : 'error'} />
{`${getSizeAndUnit(text, 'B/s').valueWithUnit} (${((row.bytesOut_avg * 100) / (row.bytesOut_spec * 1024 * 1024)).toFixed(2)}%)`} {`${getSizeAndUnit(text, 'B/s').valueWithUnit.toLocaleString()} (${(
(row.bytesOut_avg * 100) /
(row.bytesOut_spec * 1024 * 1024)
).toFixed(2)}%)`}
</span> </span>
) : ( ) : (
'-' '-'

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Slider, Input, Select, Checkbox, Button, Utils, Spin, IconFont, AppContainer } from 'knowdesign'; import { Slider, Input, Select, Checkbox, Button, Utils, Spin, AppContainer } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import API from '@src/api'; import API from '@src/api';
import TourGuide, { MultiPageSteps } from '@src/components/TourGuide'; import TourGuide, { MultiPageSteps } from '@src/components/TourGuide';
import './index.less'; import './index.less';

View File

@@ -1,4 +1,5 @@
import { AppContainer, Divider, Form, IconFont, Input, List, message, Modal, Progress, Spin, Tooltip, Utils } from 'knowdesign'; import { AppContainer, Divider, Form, Input, List, message, Modal, Progress, Spin, Tooltip, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import moment from 'moment'; import moment from 'moment';
import API from '@src/api'; import API from '@src/api';
import React, { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import React, { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
@@ -16,6 +17,10 @@ import { SearchParams } from './HomePage';
const DEFAULT_PAGE_SIZE = 10; const DEFAULT_PAGE_SIZE = 10;
enum ClusterRunState {
Raft = 2,
}
const DeleteCluster = React.forwardRef((_, ref) => { const DeleteCluster = React.forwardRef((_, ref) => {
const intl = useIntl(); const intl = useIntl();
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -245,6 +250,7 @@ const ClusterList = (props: { searchParams: SearchParams; showAccessCluster: any
metricPoints.push(line); metricPoints.push(line);
}); });
const runState = itemData.runState;
const { const {
Brokers: brokers, Brokers: brokers,
Zookeepers: zks, Zookeepers: zks,
@@ -345,18 +351,21 @@ const ClusterList = (props: { searchParams: SearchParams; showAccessCluster: any
</div> </div>
<div className="indicator-left-item-value">{brokers}</div> <div className="indicator-left-item-value">{brokers}</div>
</div> </div>
<div className="indicator-left-item"> {/* 2: raft 模式 无zk */}
<div className="indicator-left-item-title"> {runState !== ClusterRunState.Raft && (
<span <div className="indicator-left-item">
className="indicator-left-item-title-dot" <div className="indicator-left-item-title">
style={{ <span
background: zookeepersAvailable === -1 ? '#e9e7e7' : zookeepersAvailable === 0 ? '#FF7066' : '#34C38F', className="indicator-left-item-title-dot"
}} style={{
></span> background: zookeepersAvailable === -1 ? '#e9e7e7' : zookeepersAvailable === 0 ? '#FF7066' : '#34C38F',
ZK }}
></span>
ZK
</div>
<div className="indicator-left-item-value">{zookeepersAvailable === -1 ? '-' : zks}</div>
</div> </div>
<div className="indicator-left-item-value">{zookeepersAvailable === -1 ? '-' : zks}</div> )}
</div>
</div> </div>
<div className="indicator-right"> <div className="indicator-right">
{metricPoints.map((row, index) => { {metricPoints.map((row, index) => {

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Button, Form, Input, Select, Modal, message, ProTable, AppContainer, DKSBreadcrumb, Utils, IconFont, Divider } from 'knowdesign'; import { Button, Form, Input, Select, Modal, message, ProTable, AppContainer, DKSBreadcrumb, Utils, Divider } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import ACLsCardBar from '@src/components/CardBar/ACLsCardBar'; import ACLsCardBar from '@src/components/CardBar/ACLsCardBar';
import api from '@src/api'; import api from '@src/api';
import { tableHeaderPrefix } from '@src/constants/common'; import { tableHeaderPrefix } from '@src/constants/common';

View File

@@ -14,9 +14,9 @@ import {
Utils, Utils,
Checkbox, Checkbox,
Tooltip, Tooltip,
IconFont,
Alert, Alert,
} from 'knowdesign'; } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { CloseOutlined, EyeInvisibleOutlined, EyeOutlined, LoadingOutlined } from '@ant-design/icons'; import { CloseOutlined, EyeInvisibleOutlined, EyeOutlined, LoadingOutlined } from '@ant-design/icons';
import './index.less'; import './index.less';
import api from '@src/api'; import api from '@src/api';

View File

@@ -1,30 +1,26 @@
import { Col, Row, SingleChart, IconFont, Utils, Modal, Spin, Empty, AppContainer, Tooltip } from 'knowdesign'; import { Col, Row, SingleChart, Utils, Modal, Spin, Empty, AppContainer, Tooltip } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { arrayMoveImmutable } from 'array-move';
import api from '@src/api'; import api from '@src/api';
import { getChartConfig } from './config';
import './index.less';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { import {
MetricDefaultChartDataType, MetricDefaultChartDataType,
MetricChartDataType, MetricChartDataType,
formatChartData, formatChartData,
supplementaryPoints, supplementaryPoints,
} from '@src/components/DashboardDragChart/config'; resolveMetricsRank,
MetricInfo,
} from '@src/constants/chartConfig';
import { MetricType } from '@src/api'; import { MetricType } from '@src/api';
import { getDataNumberUnit, getUnit } from '@src/constants/chartConfig'; import { getDataNumberUnit, getUnit } from '@src/constants/chartConfig';
import SingleChartHeader, { KsHeaderOptions } from '@src/components/SingleChartHeader'; import SingleChartHeader, { KsHeaderOptions } from '@src/components/SingleChartHeader';
import { MAX_TIME_RANGE_WITH_SMALL_POINT_INTERVAL } from '@src/constants/common';
import RenderEmpty from '@src/components/RenderEmpty'; import RenderEmpty from '@src/components/RenderEmpty';
import DragGroup from '@src/components/DragGroup'; import DragGroup from '@src/components/DragGroup';
import { getChartConfig } from './config';
import './index.less';
type ChartFilterOptions = Omit<KsHeaderOptions, 'gridNum'>; type ChartFilterOptions = Omit<KsHeaderOptions, 'gridNum'>;
interface MetricInfo {
type: number;
name: string;
desc: string;
set: boolean;
support: boolean;
}
interface MessagesInDefaultData { interface MessagesInDefaultData {
aggType: string | null; aggType: string | null;
@@ -71,8 +67,7 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
const [curHeaderOptions, setCurHeaderOptions] = useState<ChartFilterOptions>(); const [curHeaderOptions, setCurHeaderOptions] = useState<ChartFilterOptions>();
const [defaultChartLoading, setDefaultChartLoading] = useState<boolean>(true); const [defaultChartLoading, setDefaultChartLoading] = useState<boolean>(true);
const [chartLoading, setChartLoading] = useState<boolean>(true); const [chartLoading, setChartLoading] = useState<boolean>(true);
const [showChartDetailModal, setShowChartDetailModal] = useState<boolean>(false); const metricRankList = useRef<string[]>([]);
const [chartDetail, setChartDetail] = useState<any>();
const curFetchingTimestamp = useRef({ const curFetchingTimestamp = useRef({
messagesIn: 0, messagesIn: 0,
other: 0, other: 0,
@@ -91,36 +86,53 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
}); });
}; };
// 更新 rank
const updateRank = (metricList: MetricInfo[]) => {
const { list, listInfo, shouldUpdate } = resolveMetricsRank(metricList);
metricRankList.current = list;
if (shouldUpdate) {
updateMetricList(listInfo);
}
};
// 获取指标列表 // 获取指标列表
const getMetricList = () => { const getMetricList = () => {
Utils.request(api.getDashboardMetricList(clusterId, MetricType.Cluster)).then((res: MetricInfo[] | null) => { Utils.request(api.getDashboardMetricList(clusterId, MetricType.Cluster)).then((res: MetricInfo[] | null) => {
if (!res) return; if (!res) return;
const showMetrics = res.filter((metric) => metric.support); const supportMetrics = res.filter((metric) => metric.support);
const selectedMetrics = showMetrics.filter((metric) => metric.set).map((metric) => metric.name); const selectedMetrics = supportMetrics.filter((metric) => metric.set).map((metric) => metric.name);
!selectedMetrics.includes(DEFAULT_METRIC) && selectedMetrics.push(DEFAULT_METRIC); !selectedMetrics.includes(DEFAULT_METRIC) && selectedMetrics.push(DEFAULT_METRIC);
setMetricList(showMetrics); updateRank([...supportMetrics]);
setMetricList(supportMetrics);
setSelectedMetricNames(selectedMetrics); setSelectedMetricNames(selectedMetrics);
}); });
}; };
// 更新指标 // 更新指标
const updateMetricList = (metricsSet: { [name: string]: boolean }) => { const updateMetricList = (metricDetailDTOList: { metric: string; rank: number; set: boolean }[]) => {
return Utils.request(api.getDashboardMetricList(clusterId, MetricType.Cluster), { return Utils.request(api.getDashboardMetricList(clusterId, MetricType.Cluster), {
method: 'POST', method: 'POST',
data: { data: {
metricsSet, metricDetailDTOList,
}, },
}); });
}; };
// 指标选中项更新回调 // 指标选中项更新回调
const indicatorChangeCallback = (newMetricNames: (string | number)[]) => { const indicatorChangeCallback = (newMetricNames: (string | number)[]) => {
const updateMetrics: { [name: string]: boolean } = {}; const updateMetrics: { metric: string; set: boolean; rank: number }[] = [];
// 需要选中的指标 // 需要选中的指标
newMetricNames.forEach((name) => !selectedMetricNames.includes(name) && (updateMetrics[name] = true)); newMetricNames.forEach(
(name) =>
!selectedMetricNames.includes(name) &&
updateMetrics.push({ metric: name as string, set: true, rank: metricList.find(({ name: metric }) => metric === name)?.rank })
);
// 取消选中的指标 // 取消选中的指标
selectedMetricNames.forEach((name) => !newMetricNames.includes(name) && (updateMetrics[name] = false)); selectedMetricNames.forEach(
(name) =>
!newMetricNames.includes(name) &&
updateMetrics.push({ metric: name as string, set: false, rank: metricList.find(({ name: metric }) => metric === name)?.rank })
);
const requestPromise = Object.keys(updateMetrics).length ? updateMetricList(updateMetrics) : Promise.resolve(); const requestPromise = Object.keys(updateMetrics).length ? updateMetricList(updateMetrics) : Promise.resolve();
requestPromise.then( requestPromise.then(
() => getMetricList(), () => getMetricList(),
@@ -156,15 +168,16 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
return; return;
} }
const supplementaryInterval = (endTime - startTime > MAX_TIME_RANGE_WITH_SMALL_POINT_INTERVAL ? 10 : 1) * 60 * 1000;
const formattedMetricData: MetricChartDataType[] = formatChartData( const formattedMetricData: MetricChartDataType[] = formatChartData(
res, res,
global.getMetricDefine || {}, global.getMetricDefine || {},
MetricType.Cluster, MetricType.Cluster,
curHeaderOptions.rangeTime, curHeaderOptions.rangeTime
supplementaryInterval
); );
formattedMetricData.forEach((data) => (data.metricLines[0].name = data.metricName)); formattedMetricData.forEach((data) => (data.metricLines[0].name = data.metricName));
// 指标排序
formattedMetricData.sort((a, b) => metricRankList.current.indexOf(a.metricName) - metricRankList.current.indexOf(b.metricName));
setMetricDataList(formattedMetricData); setMetricDataList(formattedMetricData);
setChartLoading(false); setChartLoading(false);
}, },
@@ -242,9 +255,7 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
...info, ...info,
value: 0, value: 0,
})); }));
const supplementaryInterval = supplementaryPoints([line], curHeaderOptions.rangeTime, (point) => {
(curHeaderOptions.rangeTime[1] - curHeaderOptions.rangeTime[0] > MAX_TIME_RANGE_WITH_SMALL_POINT_INTERVAL ? 10 : 1) * 60 * 1000;
supplementaryPoints([line], curHeaderOptions.rangeTime, supplementaryInterval, (point) => {
point.push(extraMetrics as any); point.push(extraMetrics as any);
return point; return point;
}); });
@@ -263,6 +274,22 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
targetNode && targetNode.addEventListener('click', () => busInstance.emit('chartResize')); targetNode && targetNode.addEventListener('click', () => busInstance.emit('chartResize'));
}; };
// 拖拽开始回调,触发图表的 onDrag 事件( 设置为 true ),禁止同步展示图表的 tooltip
const dragStart = () => {
busInstance.emit('onDrag', true);
};
// 拖拽结束回调,更新图表顺序,并触发图表的 onDrag 事件( 设置为 false ),允许同步展示图表的 tooltip
const dragEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
busInstance.emit('onDrag', false);
const originFrom = metricRankList.current.indexOf(metricDataList[oldIndex].metricName);
const originTarget = metricRankList.current.indexOf(metricDataList[newIndex].metricName);
const newList = arrayMoveImmutable(metricRankList.current, originFrom, originTarget);
metricRankList.current = newList;
updateMetricList(newList.map((metric, rank) => ({ metric, rank, set: metricList.find(({ name }) => metric === name)?.set || false })));
setMetricDataList(arrayMoveImmutable(metricDataList, oldIndex, newIndex));
};
useEffect(() => { useEffect(() => {
getMetricData(); getMetricData();
}, [selectedMetricNames]); }, [selectedMetricNames]);
@@ -359,10 +386,10 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
<div className="no-group-con"> <div className="no-group-con">
<DragGroup <DragGroup
sortableContainerProps={{ sortableContainerProps={{
onSortStart: () => 0, onSortStart: dragStart,
onSortEnd: () => 0, onSortEnd: dragEnd,
axis: 'xy', axis: 'xy',
useDragHandle: false, useDragHandle: true,
}} }}
gridProps={{ gridProps={{
span: 12, span: 12,

View File

@@ -1,4 +1,5 @@
import { AppContainer, Divider, IconFont, Progress, Tooltip, Utils } from 'knowdesign'; import { AppContainer, Divider, Progress, Tooltip, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import AccessClusters from '../MutliClusterPage/AccessCluster'; import AccessClusters from '../MutliClusterPage/AccessCluster';
import './index.less'; import './index.less';

View File

@@ -2,7 +2,8 @@ import moment from 'moment';
import React from 'react'; import React from 'react';
import { timeFormat } from '../../constants/common'; import { timeFormat } from '../../constants/common';
import TagsWithHide from '../../components/TagsWithHide/index'; import TagsWithHide from '../../components/TagsWithHide/index';
import { Form, IconFont, InputNumber, Tooltip } from 'knowdesign'; import { Form, InputNumber, Tooltip } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { systemKey } from '../../constants/menu'; import { systemKey } from '../../constants/menu';

View File

@@ -1,6 +1,7 @@
/* eslint-disable no-case-declarations */ /* eslint-disable no-case-declarations */
import { DownloadOutlined } from '@ant-design/icons'; import { DownloadOutlined } from '@ant-design/icons';
import { AppContainer, Divider, IconFont, message, Tooltip, Utils } from 'knowdesign'; import { AppContainer, Divider, message, Tooltip, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import * as React from 'react'; import * as React from 'react';
import moment from 'moment'; import moment from 'moment';
import { timeFormat } from '../../constants/common'; import { timeFormat } from '../../constants/common';

View File

@@ -1,6 +1,7 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Table, Input, InputNumber, Popconfirm, Form, Typography, Button, message, IconFont, Select } from 'knowdesign'; import { Table, Input, InputNumber, Popconfirm, Form, Typography, Button, message, Select } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import './style/edit-table.less'; import './style/edit-table.less';
import { CheckOutlined, CloseOutlined, PlusSquareOutlined } from '@ant-design/icons'; import { CheckOutlined, CloseOutlined, PlusSquareOutlined } from '@ant-design/icons';

View File

@@ -1,5 +1,6 @@
import { QuestionCircleOutlined } from '@ant-design/icons'; import { QuestionCircleOutlined } from '@ant-design/icons';
import { IconFont, Switch, Tooltip } from 'knowdesign'; import { Switch, Tooltip } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { FormItemType, IFormItem } from 'knowdesign/es/extend/x-form'; import { FormItemType, IFormItem } from 'knowdesign/es/extend/x-form';
import moment from 'moment'; import moment from 'moment';
import React from 'react'; import React from 'react';

View File

@@ -1,6 +1,7 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { AppContainer, Button, Empty, IconFont, List, Popover, ProTable, Radio, Spin, Utils } from 'knowdesign'; import { AppContainer, Button, Empty, List, Popover, ProTable, Radio, Spin, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import api, { MetricType } from '@src/api'; import api, { MetricType } from '@src/api';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';

View File

@@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Drawer, Form, Input, Space, Button, Utils, Row, Col, IconFont, Divider, message } from 'knowdesign'; import { Drawer, Form, Input, Space, Button, Utils, Row, Col, Divider, message } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import Api from '@src/api'; import Api from '@src/api';
export const ConfigurationEdit = (props: any) => { export const ConfigurationEdit = (props: any) => {

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Alert, Button, Checkbox, Form, IconFont, Input, ProTable, Select, Tooltip, Utils } from 'knowdesign'; import { Alert, Button, Checkbox, Form, Input, ProTable, Select, Tooltip, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import Api from '@src/api'; import Api from '@src/api';
import { useParams, useHistory } from 'react-router-dom'; import { useParams, useHistory } from 'react-router-dom';
import { getTopicMessagesColmns } from './config'; import { getTopicMessagesColmns } from './config';

View File

@@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import moment from 'moment'; import moment from 'moment';
import { timeFormat } from '../../constants/common'; import { timeFormat } from '../../constants/common';
import { IconFont, Tooltip } from 'knowdesign'; import { message, Tooltip, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import ContentWithCopy from '@src/components/CopyContent';
const aclOperationType: any = { const aclOperationType: any = {
0: 'UNKNOWN', 0: 'UNKNOWN',
1: 'ANY', 1: 'ANY',
@@ -80,6 +81,7 @@ export const getTopicMessagesColmns = () => {
title: 'Offset', title: 'Offset',
dataIndex: 'offset', dataIndex: 'offset',
key: 'offset', key: 'offset',
render: (t: number) => (t ? t.toLocaleString() : '-'),
}, },
{ {
title: 'Timestamp', title: 'Timestamp',
@@ -100,8 +102,9 @@ export const getTopicMessagesColmns = () => {
dataIndex: 'value', dataIndex: 'value',
key: 'value', key: 'value',
width: 280, width: 280,
lineClampTwo: true, render: (t: string) => {
needTooltip: true, return t ? <ContentWithCopy content={t} /> : '-';
},
}, },
{ {
title: 'Header', title: 'Header',

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { Button, Form, IconFont, Input, Modal, notification, Utils } from 'knowdesign'; import { Button, Form, Input, Modal, notification, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import Api from '@src/api/index'; import Api from '@src/api/index';
// eslint-disable-next-line react/display-name // eslint-disable-next-line react/display-name

View File

@@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom';
import { AppContainer, Button, Divider, Drawer, Form, InputNumber, notification, SingleChart, Space, Spin, Utils } from 'knowdesign'; import { AppContainer, Button, Divider, Drawer, Form, InputNumber, notification, SingleChart, Space, Spin, Utils } from 'knowdesign';
import Api, { MetricType } from '@src/api/index'; import Api, { MetricType } from '@src/api/index';
import { getBasicChartConfig, getUnit } from '@src/constants/chartConfig'; import { getBasicChartConfig, getUnit } from '@src/constants/chartConfig';
import { formatChartData, MetricDefaultChartDataType } from '@src/components/DashboardDragChart/config'; import { formatChartData, MetricDefaultChartDataType } from '@src/constants/chartConfig';
const ExpandPartition = (props: { record: any; onConfirm: () => void }) => { const ExpandPartition = (props: { record: any; onConfirm: () => void }) => {
const [global] = AppContainer.useGlobalValue(); const [global] = AppContainer.useGlobalValue();
@@ -74,8 +74,7 @@ const ExpandPartition = (props: { record: any; onConfirm: () => void }) => {
], ],
global?.getMetricDefine || {}, global?.getMetricDefine || {},
MetricType.Topic, MetricType.Topic,
[startStamp, endStamp], [startStamp, endStamp]
10 * 60 * 1000
); );
setMinByteInOut(minByteInOut < empiricalMinValue ? empiricalMinValue : minByteInOut); setMinByteInOut(minByteInOut < empiricalMinValue ? empiricalMinValue : minByteInOut);

View File

@@ -1,7 +1,8 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useHistory, useParams } from 'react-router-dom'; import { useHistory, useParams } from 'react-router-dom';
import { AppContainer, IconFont, Input, ProTable, Select, Switch, Tooltip, Utils, Dropdown, Menu, Button, Divider } from 'knowdesign'; import { AppContainer, Input, ProTable, Select, Switch, Tooltip, Utils, Dropdown, Menu, Button, Divider } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import Create from './Create'; import Create from './Create';
import './index.less'; import './index.less';
import Api from '@src/api/index'; import Api from '@src/api/index';
@@ -90,11 +91,11 @@ const AutoPage = (props: any) => {
const orgVal = record?.latestMetrics?.metrics?.[metricName]; const orgVal = record?.latestMetrics?.metrics?.[metricName];
if (orgVal !== undefined) { if (orgVal !== undefined) {
if (metricName === 'HealthScore') { if (metricName === 'HealthScore') {
return Math.round(orgVal); return Math.round(orgVal).toLocaleString();
} else if (metricName === 'LogSize') { } else if (metricName === 'LogSize') {
return Number(Utils.formatAssignSize(orgVal, 'MB')); return Number(Utils.formatAssignSize(orgVal, 'MB')).toLocaleString();
} else { } else {
return Number(Utils.formatAssignSize(orgVal, 'KB')); return Number(Utils.formatAssignSize(orgVal, 'KB')).toLocaleString();
// return Utils.formatAssignSize(orgVal, 'KB'); // return Utils.formatAssignSize(orgVal, 'KB');
} }
} }

View File

@@ -655,4 +655,4 @@
.@{ant-prefix}-empty-img-default{ .@{ant-prefix}-empty-img-default{
width: 100% !important; width: 100% !important;
} }

View File

@@ -30,10 +30,14 @@ public interface GroupService {
int replaceDBData(GroupMemberPO groupMemberPO); int replaceDBData(GroupMemberPO groupMemberPO);
void batchReplace(List<GroupMemberPO> newGroupMemberList);
GroupStateEnum getGroupStateFromDB(Long clusterPhyId, String groupName); GroupStateEnum getGroupStateFromDB(Long clusterPhyId, String groupName);
List<GroupMemberPO> listGroupByTopic(Long clusterPhyId, String topicName); List<GroupMemberPO> listGroupByTopic(Long clusterPhyId, String topicName);
List<GroupMemberPO> listGroup(Long clusterPhyId);
PaginationResult<GroupMemberPO> pagingGroupMembers(Long clusterPhyId, PaginationResult<GroupMemberPO> pagingGroupMembers(Long clusterPhyId,
String topicName, String topicName,
String groupName, String groupName,

View File

@@ -90,23 +90,31 @@ public class GroupMetricServiceImpl extends BaseMetricService implements GroupMe
@Override @Override
public Result<List<GroupMetrics>> collectGroupMetricsFromKafka(Long clusterId, String groupName, List<String> metrics) { public Result<List<GroupMetrics>> collectGroupMetricsFromKafka(Long clusterId, String groupName, List<String> metrics) {
List<GroupMetrics> allGroupMetrics = new ArrayList<>(); List<GroupMetrics> allGroupMetrics = new ArrayList<>();
Map<String, GroupMetrics> topicPartitionGroupMap = new HashMap<>(); Map<String, GroupMetrics> topicPartitionGroupMap = new HashMap<>();
GroupMetrics groupMetrics = new GroupMetrics(clusterId, groupName, true); GroupMetrics groupMetrics = new GroupMetrics(clusterId, groupName, true);
for(String metric : metrics){ Set<String> existMetricSet = new HashSet<>();
if(null != groupMetrics.getMetrics().get(metric)){continue;} for (String metric : metrics) {
if (existMetricSet.contains(metric)) {
continue;
}
Result<List<GroupMetrics>> ret = collectGroupMetricsFromKafka(clusterId, groupName, metric); Result<List<GroupMetrics>> ret = collectGroupMetricsFromKafka(clusterId, groupName, metric);
if(null != ret && ret.successful()){ if (null != ret && ret.successful()) {
List<GroupMetrics> groupMetricsList = ret.getData(); List<GroupMetrics> groupMetricsList = ret.getData();
for(GroupMetrics gm : groupMetricsList){
if(gm.isBGroupMetric()){ for (GroupMetrics gm : groupMetricsList) {
//记录已存在的指标
existMetricSet.addAll(gm.getMetrics().keySet());
if (gm.isBGroupMetric()) {
groupMetrics.getMetrics().putAll(gm.getMetrics()); groupMetrics.getMetrics().putAll(gm.getMetrics());
}else { } else {
GroupMetrics topicGroupMetric = topicPartitionGroupMap.getOrDefault( GroupMetrics topicGroupMetric = topicPartitionGroupMap.getOrDefault(
gm.getTopic() + gm.getPartitionId(), gm.getTopic() + gm.getPartitionId(),
new GroupMetrics(clusterId, groupName, false)); new GroupMetrics(clusterId, gm.getPartitionId(), gm.getTopic(), groupName, false));
topicGroupMetric.getMetrics().putAll(gm.getMetrics()); topicGroupMetric.getMetrics().putAll(gm.getMetrics());
topicPartitionGroupMap.put(gm.getTopic() + gm.getPartitionId(), topicGroupMetric); topicPartitionGroupMap.put(gm.getTopic() + gm.getPartitionId(), topicGroupMetric);

View File

@@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum.SERVICE_SEARCH_GROUP; import static com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum.SERVICE_SEARCH_GROUP;
@@ -120,6 +121,38 @@ public class GroupServiceImpl extends BaseVersionControlService implements Group
return groupMemberDAO.replace(groupMemberPO); return groupMemberDAO.replace(groupMemberPO);
} }
@Override
public void batchReplace(List<GroupMemberPO> newGroupMemberList) {
if (newGroupMemberList == null || newGroupMemberList.isEmpty()) {
return;
}
Long clusterPhyId = newGroupMemberList.get(0).getClusterPhyId();
if (clusterPhyId == null) {
return;
}
List<GroupMemberPO> dbGroupMemberList = listGroup(clusterPhyId);
Map<String, GroupMemberPO> dbGroupMemberMap = dbGroupMemberList.stream().collect(Collectors.toMap(elem -> elem.getGroupName() + elem.getTopicName(), Function.identity()));
for (GroupMemberPO groupMemberPO : newGroupMemberList) {
GroupMemberPO po = dbGroupMemberMap.remove(groupMemberPO.getGroupName() + groupMemberPO.getTopicName());
try {
if (po != null) {
groupMemberPO.setId(po.getId());
groupMemberDAO.updateById(groupMemberPO);
} else {
groupMemberDAO.insert(groupMemberPO);
}
} catch (Exception e) {
log.error("method=batchReplace||clusterPhyId={}||groupName={}||errMsg=exception", clusterPhyId, groupMemberPO.getGroupName(), e);
}
}
}
@Override @Override
public GroupStateEnum getGroupStateFromDB(Long clusterPhyId, String groupName) { public GroupStateEnum getGroupStateFromDB(Long clusterPhyId, String groupName) {
LambdaQueryWrapper<GroupMemberPO> lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<GroupMemberPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
@@ -143,6 +176,14 @@ public class GroupServiceImpl extends BaseVersionControlService implements Group
return groupMemberDAO.selectList(lambdaQueryWrapper); return groupMemberDAO.selectList(lambdaQueryWrapper);
} }
@Override
public List<GroupMemberPO> listGroup(Long clusterPhyId) {
LambdaQueryWrapper<GroupMemberPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(GroupMemberPO::getClusterPhyId, clusterPhyId);
return groupMemberDAO.selectList(lambdaQueryWrapper);
}
@Override @Override
public PaginationResult<GroupMemberPO> pagingGroupMembers(Long clusterPhyId, public PaginationResult<GroupMemberPO> pagingGroupMembers(Long clusterPhyId,
String topicName, String topicName,

View File

@@ -0,0 +1,102 @@
version: "2"
services:
# *不要调整knowstreaming-manager服务名称ui中会用到
knowstreaming-manager:
image: knowstreaming/knowstreaming-manager:latest
container_name: knowstreaming-manager
privileged: true
restart: always
depends_on:
- elasticsearch-single
- knowstreaming-mysql
expose:
- 80
command:
- /bin/sh
- /ks-start.sh
environment:
TZ: Asia/Shanghai
# mysql服务地址
SERVER_MYSQL_ADDRESS: knowstreaming-mysql:3306
# mysql数据库名
SERVER_MYSQL_DB: know_streaming
# mysql用户名
SERVER_MYSQL_USER: root
# mysql用户密码
SERVER_MYSQL_PASSWORD: admin2022_
# es服务地址
SERVER_ES_ADDRESS: elasticsearch-single:9200
# 服务JVM参数
JAVA_OPTS: -Xmx1g -Xms1g
# 对于kafka中ADVERTISED_LISTENERS填写的hostname可以通过该方式完成
# extra_hosts:
# - "hostname:x.x.x.x"
# 服务日志路径
# volumes:
# - /ks/manage/log:/logs
knowstreaming-ui:
image: knowstreaming/knowstreaming-ui:latest
container_name: knowstreaming-ui
restart: always
ports:
- '80:80'
environment:
TZ: Asia/Shanghai
depends_on:
- knowstreaming-manager
# extra_hosts:
# - "hostname:x.x.x.x"
elasticsearch-single:
image: docker.io/library/elasticsearch:7.6.2
container_name: elasticsearch-single
restart: always
expose:
- 9200
- 9300
# ports:
# - '9200:9200'
# - '9300:9300'
environment:
TZ: Asia/Shanghai
# es的JVM参数
ES_JAVA_OPTS: -Xms512m -Xmx512m
# 单节点配置,多节点集群参考 https://www.elastic.co/guide/en/elasticsearch/reference/7.6/docker.html#docker-compose-file
discovery.type: single-node
# 数据持久化路径
# volumes:
# - /ks/es/data:/usr/share/elasticsearch/data
# es初始化服务与manager使用同一镜像
# 首次启动es需初始化模版和索引,后续会自动创建
knowstreaming-init:
image: knowstreaming/knowstreaming-manager:latest
container_name: knowstreaming-init
depends_on:
- elasticsearch-single
command:
- /bin/bash
- /es_template_create.sh
environment:
TZ: Asia/Shanghai
# es服务地址
SERVER_ES_ADDRESS: elasticsearch-single:9200
knowstreaming-mysql:
image: knowstreaming/knowstreaming-mysql:latest
container_name: knowstreaming-mysql
restart: always
environment:
TZ: Asia/Shanghai
# root 用户密码
MYSQL_ROOT_PASSWORD: admin2022_
# 初始化时创建的数据库名称
MYSQL_DATABASE: know_streaming
# 通配所有host,可以访问远程
MYSQL_ROOT_HOST: '%'
expose:
- 3306
# ports:
# - '3306:3306'
# 数据持久化路径
# volumes:
# - /ks/mysql/data:/data/mysql

View File

@@ -0,0 +1,17 @@
FROM java:8
#维护者
MAINTAINER wangdongfang <wangdongfang@didiglobal.com>
# 编译好的knowstreaming包
ADD km-rest.jar /
# docker启动脚本 helm安装不使用
ADD ks-start.sh /
# es初始化脚本 helm安装不使用
ADD es_template_create.sh /
RUN mkdir /conf
# { 配置文件 helm安装不使用
ADD application.yml /conf/
ADD logback-spring.xml /conf/
# }

View File

@@ -0,0 +1,661 @@
echo "Wait ElasticSearch Start...${SERVER_ES_ADDRESS}"
while true
do
curl -s --connect-timeout 10 -o /dev/null http://${SERVER_ES_ADDRESS}/_cat/nodes > /dev/null 2>&1
if [ "$?" != "0" ];then
sleep 1s
else
echo "ElasticSearch Start Initialize"
break
fi
done
curl -s --connect-timeout 10 -o /dev/null -X POST -H 'cache-control: no-cache' -H 'content-type: application/json' http://${SERVER_ES_ADDRESS}/_template/ks_kafka_broker_metric -d '{
"order" : 10,
"index_patterns" : [
"ks_kafka_broker_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"brokerId" : {
"type" : "long"
},
"routingValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"clusterPhyId" : {
"type" : "long"
},
"metrics" : {
"properties" : {
"NetworkProcessorAvgIdle" : {
"type" : "float"
},
"UnderReplicatedPartitions" : {
"type" : "float"
},
"BytesIn_min_15" : {
"type" : "float"
},
"HealthCheckTotal" : {
"type" : "float"
},
"RequestHandlerAvgIdle" : {
"type" : "float"
},
"connectionsCount" : {
"type" : "float"
},
"BytesIn_min_5" : {
"type" : "float"
},
"HealthScore" : {
"type" : "float"
},
"BytesOut" : {
"type" : "float"
},
"BytesOut_min_15" : {
"type" : "float"
},
"BytesIn" : {
"type" : "float"
},
"BytesOut_min_5" : {
"type" : "float"
},
"TotalRequestQueueSize" : {
"type" : "float"
},
"MessagesIn" : {
"type" : "float"
},
"TotalProduceRequests" : {
"type" : "float"
},
"HealthCheckPassed" : {
"type" : "float"
},
"TotalResponseQueueSize" : {
"type" : "float"
}
}
},
"key" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"index" : true,
"type" : "date",
"doc_values" : true
}
}
},
"aliases" : { }
}'
curl -s -o /dev/null -X POST -H 'cache-control: no-cache' -H 'content-type: application/json' http://${SERVER_ES_ADDRESS}/_template/ks_kafka_cluster_metric -d '{
"order" : 10,
"index_patterns" : [
"ks_kafka_cluster_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"routingValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"clusterPhyId" : {
"type" : "long"
},
"metrics" : {
"properties" : {
"Connections" : {
"type" : "double"
},
"BytesIn_min_15" : {
"type" : "double"
},
"PartitionURP" : {
"type" : "double"
},
"HealthScore_Topics" : {
"type" : "double"
},
"EventQueueSize" : {
"type" : "double"
},
"ActiveControllerCount" : {
"type" : "double"
},
"GroupDeads" : {
"type" : "double"
},
"BytesIn_min_5" : {
"type" : "double"
},
"HealthCheckTotal_Topics" : {
"type" : "double"
},
"Partitions" : {
"type" : "double"
},
"BytesOut" : {
"type" : "double"
},
"Groups" : {
"type" : "double"
},
"BytesOut_min_15" : {
"type" : "double"
},
"TotalRequestQueueSize" : {
"type" : "double"
},
"HealthCheckPassed_Groups" : {
"type" : "double"
},
"TotalProduceRequests" : {
"type" : "double"
},
"HealthCheckPassed" : {
"type" : "double"
},
"TotalLogSize" : {
"type" : "double"
},
"GroupEmptys" : {
"type" : "double"
},
"PartitionNoLeader" : {
"type" : "double"
},
"HealthScore_Brokers" : {
"type" : "double"
},
"Messages" : {
"type" : "double"
},
"Topics" : {
"type" : "double"
},
"PartitionMinISR_E" : {
"type" : "double"
},
"HealthCheckTotal" : {
"type" : "double"
},
"Brokers" : {
"type" : "double"
},
"Replicas" : {
"type" : "double"
},
"HealthCheckTotal_Groups" : {
"type" : "double"
},
"GroupRebalances" : {
"type" : "double"
},
"MessageIn" : {
"type" : "double"
},
"HealthScore" : {
"type" : "double"
},
"HealthCheckPassed_Topics" : {
"type" : "double"
},
"HealthCheckTotal_Brokers" : {
"type" : "double"
},
"PartitionMinISR_S" : {
"type" : "double"
},
"BytesIn" : {
"type" : "double"
},
"BytesOut_min_5" : {
"type" : "double"
},
"GroupActives" : {
"type" : "double"
},
"MessagesIn" : {
"type" : "double"
},
"GroupReBalances" : {
"type" : "double"
},
"HealthCheckPassed_Brokers" : {
"type" : "double"
},
"HealthScore_Groups" : {
"type" : "double"
},
"TotalResponseQueueSize" : {
"type" : "double"
},
"Zookeepers" : {
"type" : "double"
},
"LeaderMessages" : {
"type" : "double"
},
"HealthScore_Cluster" : {
"type" : "double"
},
"HealthCheckPassed_Cluster" : {
"type" : "double"
},
"HealthCheckTotal_Cluster" : {
"type" : "double"
}
}
},
"key" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"type" : "date"
}
}
},
"aliases" : { }
}'
curl -s -o /dev/null -X POST -H 'cache-control: no-cache' -H 'content-type: application/json' http://${SERVER_ES_ADDRESS}/_template/ks_kafka_group_metric -d '{
"order" : 10,
"index_patterns" : [
"ks_kafka_group_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"group" : {
"type" : "keyword"
},
"partitionId" : {
"type" : "long"
},
"routingValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"clusterPhyId" : {
"type" : "long"
},
"topic" : {
"type" : "keyword"
},
"metrics" : {
"properties" : {
"HealthScore" : {
"type" : "float"
},
"Lag" : {
"type" : "float"
},
"OffsetConsumed" : {
"type" : "float"
},
"HealthCheckTotal" : {
"type" : "float"
},
"HealthCheckPassed" : {
"type" : "float"
}
}
},
"groupMetric" : {
"type" : "keyword"
},
"key" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"index" : true,
"type" : "date",
"doc_values" : true
}
}
},
"aliases" : { }
}'
curl -s -o /dev/null -X POST -H 'cache-control: no-cache' -H 'content-type: application/json' http://${SERVER_ES_ADDRESS}/_template/ks_kafka_partition_metric -d '{
"order" : 10,
"index_patterns" : [
"ks_kafka_partition_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"brokerId" : {
"type" : "long"
},
"partitionId" : {
"type" : "long"
},
"routingValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"clusterPhyId" : {
"type" : "long"
},
"topic" : {
"type" : "keyword"
},
"metrics" : {
"properties" : {
"LogStartOffset" : {
"type" : "float"
},
"Messages" : {
"type" : "float"
},
"LogEndOffset" : {
"type" : "float"
}
}
},
"key" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"index" : true,
"type" : "date",
"doc_values" : true
}
}
},
"aliases" : { }
}'
curl -s -o /dev/null -X POST -H 'cache-control: no-cache' -H 'content-type: application/json' http://${SERVER_ES_ADDRESS}/_template/ks_kafka_replication_metric -d '{
"order" : 10,
"index_patterns" : [
"ks_kafka_partition_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"brokerId" : {
"type" : "long"
},
"partitionId" : {
"type" : "long"
},
"routingValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"clusterPhyId" : {
"type" : "long"
},
"topic" : {
"type" : "keyword"
},
"metrics" : {
"properties" : {
"LogStartOffset" : {
"type" : "float"
},
"Messages" : {
"type" : "float"
},
"LogEndOffset" : {
"type" : "float"
}
}
},
"key" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"index" : true,
"type" : "date",
"doc_values" : true
}
}
},
"aliases" : { }
}[root@10-255-0-23 template]# cat ks_kafka_replication_metric
PUT _template/ks_kafka_replication_metric
{
"order" : 10,
"index_patterns" : [
"ks_kafka_replication_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"index" : true,
"type" : "date",
"doc_values" : true
}
}
},
"aliases" : { }
}'
curl -s -o /dev/null -X POST -H 'cache-control: no-cache' -H 'content-type: application/json' http://${SERVER_ES_ADDRESS}/_template/ks_kafka_topic_metric -d '{
"order" : 10,
"index_patterns" : [
"ks_kafka_topic_metric*"
],
"settings" : {
"index" : {
"number_of_shards" : "10"
}
},
"mappings" : {
"properties" : {
"brokerId" : {
"type" : "long"
},
"routingValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"topic" : {
"type" : "keyword"
},
"clusterPhyId" : {
"type" : "long"
},
"metrics" : {
"properties" : {
"BytesIn_min_15" : {
"type" : "float"
},
"Messages" : {
"type" : "float"
},
"BytesRejected" : {
"type" : "float"
},
"PartitionURP" : {
"type" : "float"
},
"HealthCheckTotal" : {
"type" : "float"
},
"ReplicationCount" : {
"type" : "float"
},
"ReplicationBytesOut" : {
"type" : "float"
},
"ReplicationBytesIn" : {
"type" : "float"
},
"FailedFetchRequests" : {
"type" : "float"
},
"BytesIn_min_5" : {
"type" : "float"
},
"HealthScore" : {
"type" : "float"
},
"LogSize" : {
"type" : "float"
},
"BytesOut" : {
"type" : "float"
},
"BytesOut_min_15" : {
"type" : "float"
},
"FailedProduceRequests" : {
"type" : "float"
},
"BytesIn" : {
"type" : "float"
},
"BytesOut_min_5" : {
"type" : "float"
},
"MessagesIn" : {
"type" : "float"
},
"TotalProduceRequests" : {
"type" : "float"
},
"HealthCheckPassed" : {
"type" : "float"
}
}
},
"brokerAgg" : {
"type" : "keyword"
},
"key" : {
"type" : "text",
"fields" : {
"keyword" : {
"ignore_above" : 256,
"type" : "keyword"
}
}
},
"timestamp" : {
"format" : "yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis",
"index" : true,
"type" : "date",
"doc_values" : true
}
}
},
"aliases" : { }
}'
for i in {0..6};
do
logdate=_$(date -d "${i} day ago" +%Y-%m-%d)
curl -s --connect-timeout 10 -o /dev/null -X PUT http://${SERVER_ES_ADDRESS}/ks_kafka_broker_metric${logdate} && \
curl -s -o /dev/null -X PUT http://${SERVER_ES_ADDRESS}/ks_kafka_cluster_metric${logdate} && \
curl -s -o /dev/null -X PUT http://${SERVER_ES_ADDRESS}/ks_kafka_group_metric${logdate} && \
curl -s -o /dev/null -X PUT http://${SERVER_ES_ADDRESS}/ks_kafka_partition_metric${logdate} && \
curl -s -o /dev/null -X PUT http://${SERVER_ES_ADDRESS}/ks_kafka_replication_metric${logdate} && \
curl -s -o /dev/null -X PUT http://${SERVER_ES_ADDRESS}/ks_kafka_topic_metric${logdate} || \
exit 2
done
echo "ElasticSearch Initialize Success"

View File

@@ -0,0 +1,7 @@
sed -i "s/SERVER_MYSQL_ADDRESS/${SERVER_MYSQL_ADDRESS}/g" /conf/application.yml
sed -i "s/SERVER_MYSQL_DB/${SERVER_MYSQL_DB}/g" /conf/application.yml
sed -i "s/SERVER_MYSQL_USER/${SERVER_MYSQL_USER}/g" /conf/application.yml
sed -i "s/SERVER_MYSQL_PASSWORD/${SERVER_MYSQL_PASSWORD}/g" /conf/application.yml
sed -i "s/SERVER_ES_ADDRESS/${SERVER_ES_ADDRESS}/g" /conf/application.yml
java -server ${JAVA_OPTS} -XX:+UseStringDeduplication -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+08 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs -XX:ErrorFile=/logs/jvm/hs_err_pid%p.log -jar /km-rest.jar --spring.config.location=/conf/application.yml

View File

@@ -0,0 +1,4 @@
FROM mysql/mysql-server:5.7.38
COPY initsql /docker-entrypoint-initdb.d/
COPY init.sh /docker-entrypoint-initdb.d/
ADD my.cnf /etc/

View File

@@ -0,0 +1,6 @@
if [ "$MYSQL_DATABASE" ]; then
"${mysql[@]}" < /docker-entrypoint-initdb.d/initsql
else
echo "CREATE DATABASE IF NOT EXISTS ks ;" | "${mysql[@]}"
"${mysql[@]}" ks < /docker-entrypoint-initdb.d/initsql
fi

View File

@@ -0,0 +1,784 @@
DROP TABLE IF EXISTS `ks_km_broker`;
CREATE TABLE `ks_km_broker` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '物理集群ID',
`broker_id` int(16) NOT NULL DEFAULT '-1' COMMENT 'brokerId',
`host` varchar(128) NOT NULL DEFAULT '' COMMENT 'broker主机名',
`port` int(16) NOT NULL DEFAULT '-1' COMMENT 'broker端口',
`jmx_port` int(16) NOT NULL DEFAULT '-1' COMMENT 'Jmx端口',
`start_timestamp` bigint(20) NOT NULL DEFAULT '-1' COMMENT '启动时间',
`rack` varchar(128) NOT NULL DEFAULT '' COMMENT 'Rack信息',
`status` int(16) NOT NULL DEFAULT '0' COMMENT '状态: 1存活0未存活',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`endpoint_map` varchar(1024) NOT NULL DEFAULT '' COMMENT '监听信息',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_phy_id_broker_id` (`cluster_phy_id`,`broker_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Broker信息表';
DROP TABLE IF EXISTS `ks_km_broker_config`;
CREATE TABLE `ks_km_broker_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`broker_id` int(16) NOT NULL DEFAULT '-1' COMMENT 'brokerId',
`config_name` varchar(192) NOT NULL DEFAULT '' COMMENT '配置名称',
`config_value` text COMMENT '配置值',
`diff_type` int(16) NOT NULL DEFAULT '-1' COMMENT '差异类型',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_broker_name` (`cluster_phy_id`,`broker_id`,`config_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Broker配置信息表';
DROP TABLE IF EXISTS `ks_km_cluster_balance_job`;
CREATE TABLE `ks_km_cluster_balance_job` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`cluster_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '集群id',
`brokers` varchar(1024) NOT NULL DEFAULT '' COMMENT '均衡节点',
`topic_black_list` varchar(4096) NOT NULL DEFAULT '' COMMENT 'topic黑名单',
`type` int(16) NOT NULL DEFAULT '0' COMMENT '1:周期均衡2立即均衡',
`balance_interval_json` text COMMENT '均衡区间详情',
`metric_calculation_period` int(16) NOT NULL DEFAULT '0' COMMENT '指标计算周期,单位分钟',
`reassignment_json` text COMMENT '迁移脚本',
`parallel_num` int(16) NOT NULL DEFAULT '0' COMMENT '任务并行数',
`execution_strategy` int(16) NOT NULL DEFAULT '0' COMMENT '执行策略, 1优先最大副本2优先最小副本',
`throttle_unit_b` bigint(20) NOT NULL DEFAULT '0' COMMENT '限流值',
`total_reassign_size` double NOT NULL DEFAULT '0' COMMENT '总迁移大小',
`total_reassign_replica_num` int(16) NOT NULL DEFAULT '0' COMMENT '总迁移副本数',
`move_in_topic_list` varchar(4096) NOT NULL DEFAULT '' COMMENT '移入topic',
`broker_balance_detail` text COMMENT '节点均衡详情',
`status` int(16) NOT NULL DEFAULT '0' COMMENT '任务状态 1进行中2准备3成功4失败5取消',
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT '操作人',
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务开始时间',
`finished_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务完成时间',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '任务修改时间',
`description` text COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='集群均衡任务';
DROP TABLE IF EXISTS `ks_km_cluster_balance_job_config`;
CREATE TABLE `ks_km_cluster_balance_job_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`cluster_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '集群id',
`brokers` varchar(256) NOT NULL DEFAULT '' COMMENT '均衡节点',
`topic_black_list` varchar(4096) NOT NULL DEFAULT '' COMMENT 'topic黑名单',
`task_cron` varchar(64) NOT NULL DEFAULT '' COMMENT '任务周期',
`balance_interval_json` text COMMENT '均衡区间详情',
`metric_calculation_period` int(16) NOT NULL DEFAULT '0' COMMENT '指标计算周期,单位分钟',
`reassignment_json` text COMMENT '迁移脚本',
`parallel_num` int(16) NOT NULL DEFAULT '0' COMMENT '任务并行数',
`execution_strategy` int(16) NOT NULL DEFAULT '0' COMMENT '执行策略, 1优先最大副本2优先最小副本',
`throttle_unit_b` bigint(20) NOT NULL DEFAULT '0' COMMENT '限流值',
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT '操作人',
`status` int(16) NOT NULL DEFAULT '0' COMMENT '任务状态 0未开启1开启',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '任务修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='集群均衡任务';
DROP TABLE IF EXISTS `ks_km_cluster_balance_reassign`;
CREATE TABLE `ks_km_cluster_balance_reassign` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`job_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '父任务ID',
`cluster_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '集群id',
`topic_name` varchar(192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Topic名称',
`partition_id` int(11) NOT NULL DEFAULT '-1' COMMENT '分区ID',
`original_broker_ids` text COMMENT '源BrokerId列表',
`reassign_broker_ids` text COMMENT '目标BrokerId列表',
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务开始时间',
`finished_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务完成时间',
`extend_data` text COMMENT '扩展数据',
`status` int(16) NOT NULL DEFAULT '2' COMMENT '任务状态',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '任务修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='集群平衡迁移详情';
DROP TABLE IF EXISTS `ks_km_group_member`;
CREATE TABLE `ks_km_group_member` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`topic_name` varchar(192) NOT NULL DEFAULT '' COMMENT 'Topic名称',
`group_name` varchar(192) NOT NULL DEFAULT '' COMMENT 'Group名称',
`kafka_user` varchar(192) NOT NULL DEFAULT '' COMMENT 'Kafka用户',
`state` varchar(64) NOT NULL DEFAULT '' COMMENT '状态',
`member_count` int(11) NOT NULL DEFAULT '0' COMMENT '成员数',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_topic_group` (`cluster_phy_id`,`topic_name`,`group_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='GroupMember信息表';
DROP TABLE IF EXISTS `ks_km_health_check_result`;
CREATE TABLE `ks_km_health_check_result` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`dimension` int(11) NOT NULL DEFAULT '0' COMMENT '检查维度(0:未知1:Cluster2:Broker3:Topic4:Group)',
`config_name` varchar(192) NOT NULL DEFAULT '' COMMENT '配置名',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理集群ID',
`res_name` varchar(192) NOT NULL DEFAULT '' COMMENT '资源名称',
`passed` int(11) NOT NULL DEFAULT '0' COMMENT '检查通过(0:未通过1:通过)',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_dimension_config_cluster_res` (`dimension`,`config_name`,`cluster_phy_id`,`res_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='健康检查结果';
DROP TABLE IF EXISTS `ks_km_job`;
CREATE TABLE `ks_km_job` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',
`job_name` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '任务名称',
`job_type` tinyint(10) NOT NULL COMMENT '任务类型',
`job_status` tinyint(10) NOT NULL COMMENT '任务状态',
`job_data` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '任务的详细信息',
`job_desc` varchar(1024) NOT NULL DEFAULT '' COMMENT '任务描述',
`cluster_id` int(11) NOT NULL COMMENT 'kafka集群id',
`target` varchar(8192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '任务执行对象',
`running_status` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '任务运行详细状态(json), Success7 Fail1 Doing2',
`creator` varchar(45) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '创建者',
`plan_time` timestamp NOT NULL DEFAULT '1971-1-1 00:00:00' COMMENT '计划执行时间',
`start_time` timestamp NOT NULL DEFAULT '1971-1-1 00:00:00' COMMENT '实际执行时间',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `index_cluster_id` (`cluster_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Job信息';
DROP TABLE IF EXISTS `ks_km_kafka_acl`;
CREATE TABLE `ks_km_kafka_acl` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '集群id',
`principal` varchar(192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Kafka用户',
`operation` int(11) NOT NULL DEFAULT '0' COMMENT '操作',
`permission_type` int(11) NOT NULL DEFAULT '0' COMMENT '权限类型(0:未知1:任意2:拒绝3:允许)',
`host` varchar(192) NOT NULL DEFAULT '127.0.0.1' COMMENT '机器',
`resource_type` int(11) NOT NULL DEFAULT '0' COMMENT '资源类型(0:未知1:任意2:Topic3:Group4:Cluster5:事务6:Token)',
`resource_name` varchar(192) NOT NULL DEFAULT '' COMMENT '资源名称',
`pattern_type` int(11) NOT NULL COMMENT '匹配类型(0:未知1:任意2:Match3:Literal4:prefixed)',
`unique_field` varchar(1024) NOT NULL DEFAULT '' COMMENT '唯一字段由cluster_phy_id等字段组成',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_uniq_field` (`unique_field`),
KEY `idx_cluster_phy_id_principal_res_name` (`cluster_phy_id`,`principal`,`resource_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='ACL信息';
DROP TABLE IF EXISTS `ks_km_kafka_change_record`;
CREATE TABLE `ks_km_kafka_change_record` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`res_type` int(11) NOT NULL DEFAULT '-1' COMMENT '资源类型',
`res_name` varchar(192) NOT NULL DEFAULT '' COMMENT '资源名称',
`operate_type` int(11) NOT NULL DEFAULT '-1' COMMENT '操作类型',
`operate_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',
`unique_field` varchar(1024) NOT NULL DEFAULT '' COMMENT '唯一键字段',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_field` (`unique_field`),
KEY `idx_cluster_phy_id` (`cluster_phy_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Kafka变更记录表';
DROP TABLE IF EXISTS `ks_km_kafka_controller`;
CREATE TABLE `ks_km_kafka_controller` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群id',
`broker_id` int(16) NOT NULL DEFAULT '-1' COMMENT 'brokerId',
`broker_host` varchar(256) NOT NULL DEFAULT '' COMMENT '主机名',
`broker_rack` varchar(256) NOT NULL DEFAULT '' COMMENT 'BrokerRack信息',
`timestamp` bigint(20) NOT NULL DEFAULT '-1' COMMENT 'controller变更时间-1表示未存活',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_broker_timestamp` (`cluster_phy_id`,`broker_id`,`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='controller记录表';
DROP TABLE IF EXISTS `ks_km_kafka_user`;
CREATE TABLE `ks_km_kafka_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`name` varchar(192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '名称',
`token` varchar(8192) NOT NULL DEFAULT '' COMMENT '密钥',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_phy_id_name` (`cluster_phy_id`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Kafka-User信息表';
DROP TABLE IF EXISTS `ks_km_partition`;
CREATE TABLE `ks_km_partition` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`topic_name` varchar(192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Topic名称',
`partition_id` int(11) NOT NULL DEFAULT '-1' COMMENT '分区ID',
`leader_broker_id` int(11) NOT NULL DEFAULT '-1' COMMENT '分区的LeaderBroker-1表示无Leader',
`in_sync_replicas` varchar(512) NOT NULL DEFAULT '-1' COMMENT 'ISR',
`assign_replicas` varchar(512) NOT NULL DEFAULT '-1' COMMENT 'AR',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_topic_partition` (`cluster_phy_id`,`topic_name`,`partition_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Partition信息表';
DROP TABLE IF EXISTS `ks_km_physical_cluster`;
CREATE TABLE `ks_km_physical_cluster` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '集群id',
`name` varchar(128) NOT NULL DEFAULT '' COMMENT '集群名称',
`zookeeper` varchar(2048) NOT NULL DEFAULT '' COMMENT 'zk地址',
`bootstrap_servers` varchar(2048) NOT NULL DEFAULT '' COMMENT 'server地址',
`kafka_version` varchar(32) NOT NULL DEFAULT '' COMMENT 'kafka版本',
`client_properties` text COMMENT 'Kafka客户端配置',
`jmx_properties` text COMMENT 'JMX配置',
`description` text COMMENT '备注',
`auth_type` int(11) NOT NULL DEFAULT '0' COMMENT '认证类型,-1未知0:无认证,',
`run_state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '运行状态, 0表示未监控, 1监控中有ZK2:监控中无ZK',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '接入时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='物理集群信息表';
DROP TABLE IF EXISTS `ks_km_platform_cluster_config`;
CREATE TABLE `ks_km_platform_cluster_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',
`cluster_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`value_group` varchar(100) NOT NULL DEFAULT '' COMMENT '配置项组',
`value_name` varchar(100) NOT NULL DEFAULT '' COMMENT '配置项名字',
`value` text COMMENT '配置项的值',
`description` text COMMENT '备注',
`operator` varchar(16) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '操作者',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_id_group_name` (`cluster_id`,`value_group`,`value_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='KS平台集群配置';
DROP TABLE IF EXISTS `ks_km_reassign_job`;
CREATE TABLE `ks_km_reassign_job` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '集群id',
`reassignment_json` text COMMENT '迁移计划',
`throttle_unit_byte` bigint(20) NOT NULL DEFAULT '0' COMMENT '限流值',
`start_time` timestamp NOT NULL DEFAULT '1971-1-1 00:00:00' COMMENT '任务开始时间',
`finished_time` timestamp NOT NULL DEFAULT '1971-1-1 00:00:00' COMMENT '任务完成时间',
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT '操作人',
`description` text COMMENT '备注',
`status` int(16) NOT NULL DEFAULT '0' COMMENT '任务状态',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '任务修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='迁移Job信息';
DROP TABLE IF EXISTS `ks_km_reassign_sub_job`;
CREATE TABLE `ks_km_reassign_sub_job` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`job_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '父任务ID',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '集群id',
`topic_name` varchar(192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Topic名称',
`partition_id` int(11) NOT NULL DEFAULT '-1' COMMENT '分区ID',
`original_broker_ids` text COMMENT '源BrokerId列表',
`reassign_broker_ids` text COMMENT '目标BrokerId列表',
`start_time` timestamp NOT NULL DEFAULT '1971-1-1 00:00:00' COMMENT '任务开始时间',
`finished_time` timestamp NOT NULL DEFAULT '1971-1-1 00:00:00' COMMENT '任务完成时间',
`extend_data` text COMMENT '扩展数据',
`status` int(16) NOT NULL DEFAULT '0' COMMENT '任务状态',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '任务修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='迁移SubJob信息';
DROP TABLE IF EXISTS `ks_km_topic`;
CREATE TABLE `ks_km_topic` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`cluster_phy_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '集群ID',
`topic_name` varchar(192) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Topic名称',
`replica_num` int(11) NOT NULL DEFAULT '-1' COMMENT '副本数',
`partition_num` int(11) NOT NULL DEFAULT '-1' COMMENT '分区数',
`broker_ids` varchar(2048) NOT NULL DEFAULT '' COMMENT 'BrokerId列表',
`partition_map` text COMMENT '分区分布信息',
`retention_ms` bigint(20) NOT NULL DEFAULT '-2' COMMENT '保存时间,-2未知-1无限制>=0对应时间单位ms',
`type` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Topic类型默认00:普通1:Kafka内部',
`description` text COMMENT '备注信息',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(尽量与Topic实际创建时间一致)',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间(尽量与Topic实际创建时间一致)',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_cluster_phy_id_topic_name` (`cluster_phy_id`,`topic_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Topic信息表';
DROP TABLE IF EXISTS `ks_km_app_node`;
CREATE TABLE `ks_km_app_node` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`host_name` varchar(256) NOT NULL DEFAULT '' COMMENT 'host',
`ip` varchar(256) NOT NULL DEFAULT '' COMMENT 'ip',
`beat_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'node 的心跳时间',
`app_name` varchar(128) NOT NULL DEFAULT '' COMMENT 'km 集群的应用名',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `idx_app_host` (`app_name`,`host_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='km集群部署的node信息';
-- Logi-Job模块的sql安装KS-KM需要执行该sql
DROP TABLE IF EXISTS `logi_job`;
CREATE TABLE `logi_job` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',
`task_code` varchar(255) NOT NULL DEFAULT '' COMMENT '任务code',
`class_name` varchar(255) NOT NULL DEFAULT '' COMMENT '类的全限定名',
`try_times` int(10) NOT NULL DEFAULT '0' COMMENT '第几次重试',
`worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT '执行机器',
`app_name` varchar(100) NOT NULL DEFAULT '' COMMENT '被调度的应用名称',
`start_time` datetime DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `job_code` (`job_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='正在执行的job信息';
DROP TABLE IF EXISTS `logi_job_log`;
CREATE TABLE `logi_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'job taskCode',
`task_code` varchar(255) NOT NULL DEFAULT '' COMMENT '任务code',
`task_name` varchar(255) NOT NULL DEFAULT '' COMMENT '任务名称',
`task_desc` varchar(255) NOT NULL DEFAULT '' COMMENT '任务描述',
`task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id',
`class_name` varchar(255) NOT NULL DEFAULT '' COMMENT '类的全限定名',
`try_times` int(10) NOT NULL DEFAULT '0' COMMENT '第几次重试',
`worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT '执行机器',
`worker_ip` varchar(200) NOT NULL DEFAULT '' COMMENT '执行机器ip',
`start_time` datetime DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',
`end_time` datetime DEFAULT '1971-01-01 00:00:00' COMMENT '结束时间',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行结果 1成功 2失败 3取消',
`error` text NOT NULL COMMENT '错误信息',
`result` text NOT NULL COMMENT '执行结果',
`app_name` varchar(100) NOT NULL DEFAULT '' COMMENT '被调度的应用名称',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `index_job_code` (`job_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='job执行历史日志';
DROP TABLE IF EXISTS `logi_task`;
CREATE TABLE `logi_task` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`task_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',
`task_name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
`task_desc` varchar(1000) NOT NULL DEFAULT '' COMMENT '任务描述',
`cron` varchar(100) NOT NULL DEFAULT '' COMMENT 'cron 表达式',
`class_name` varchar(255) NOT NULL DEFAULT '' COMMENT '类的全限定名',
`params` varchar(1000) NOT NULL DEFAULT '' COMMENT '执行参数 map 形式{key1:value1,key2:value2}',
`retry_times` int(10) NOT NULL DEFAULT '0' COMMENT '允许重试次数',
`last_fire_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '上次执行时间',
`timeout` bigint(20) NOT NULL DEFAULT '0' COMMENT '超时 毫秒',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '1等待 2运行中 3暂停',
`sub_task_codes` varchar(1000) NOT NULL DEFAULT '' COMMENT '子任务code列表,逗号分隔',
`consensual` varchar(200) NOT NULL DEFAULT '' COMMENT '执行策略',
`owner` varchar(200) NOT NULL DEFAULT '' COMMENT '责任人',
`task_worker_str` varchar(3000) NOT NULL DEFAULT '' COMMENT '机器执行信息',
`app_name` varchar(100) NOT NULL DEFAULT '' COMMENT '被调度的应用名称',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `task_code` (`task_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务信息';
DROP TABLE IF EXISTS `logi_task_lock`;
CREATE TABLE `logi_task_lock` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`task_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',
`worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',
`app_name` varchar(100) NOT NULL DEFAULT '' COMMENT '被调度的应用名称',
`expire_time` bigint(20) NOT NULL DEFAULT '0' COMMENT '过期时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务锁';
DROP TABLE IF EXISTS `logi_worker`;
CREATE TABLE `logi_worker` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',
`worker_name` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker名',
`ip` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker的ip',
`cpu` int(11) NOT NULL DEFAULT '0' COMMENT 'cpu数量',
`cpu_used` double NOT NULL DEFAULT '0' COMMENT 'cpu使用率',
`memory` double NOT NULL DEFAULT '0' COMMENT '内存,以M为单位',
`memory_used` double NOT NULL DEFAULT '0' COMMENT '内存使用率',
`jvm_memory` double NOT NULL DEFAULT '0' COMMENT 'jvm堆大小以M为单位',
`jvm_memory_used` double NOT NULL DEFAULT '0' COMMENT 'jvm堆使用率',
`job_num` int(10) NOT NULL DEFAULT '0' COMMENT '正在执行job数',
`heartbeat` datetime DEFAULT '1971-01-01 00:00:00' COMMENT '心跳时间',
`app_name` varchar(100) NOT NULL DEFAULT '' COMMENT '被调度的应用名称',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `worker_code` (`worker_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='worker信息';
DROP TABLE IF EXISTS `logi_worker_blacklist`;
CREATE TABLE `logi_worker_blacklist` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `worker_code` (`worker_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='worker黑名单列表';
DROP TABLE IF EXISTS `logi_security_dept`;
CREATE TABLE `logi_security_dept`
(
id int auto_increment primary key,
dept_name varchar(10) not null comment '部门名',
parent_id int not null comment '父部门id',
leaf tinyint(1) not null comment '是否叶子部门',
level tinyint not null comment 'parentId为0的层级为1',
description varchar(20) null comment '描述',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '部门信息表';
DROP TABLE IF EXISTS `logi_security_message`;
CREATE TABLE `logi_security_message`
(
id int auto_increment primary key,
title varchar(60) not null comment '标题',
content varchar(256) null comment '内容',
read_tag tinyint(1) default 0 null comment '是否已读',
oplog_id int null comment '操作日志id',
user_id int null comment '这条消息属于哪个用户的用户id',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '消息中心';
DROP TABLE IF EXISTS `logi_security_oplog`;
CREATE TABLE `logi_security_oplog`
(
id int auto_increment primary key,
operator_ip varchar(64) not null comment '操作者ip',
operator varchar(64) null comment '操作者账号',
operate_page varchar(64) not null default '' comment '操作页面',
operate_type varchar(64) not null comment '操作类型',
target_type varchar(64) not null comment '对象分类',
target varchar(1024) not null comment '操作对象',
operation_methods varchar(64) not null default '' comment '操作方式',
detail text null comment '日志详情',
create_time timestamp default CURRENT_TIMESTAMP null,
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '操作日志';
DROP TABLE IF EXISTS `logi_security_oplog_extra`;
CREATE TABLE `logi_security_oplog_extra`
(
id int auto_increment primary key,
info varchar(16) null comment '信息',
type tinyint not null comment '哪种信息1操作页面;2操作类型;3对象分类',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '操作日志信息(操作页面、操作类型、对象分类)';
DROP TABLE IF EXISTS `logi_security_permission`;
CREATE TABLE `logi_security_permission`
(
id int auto_increment primary key,
permission_name varchar(40) not null comment '权限名字',
parent_id int not null comment '父权限id',
leaf tinyint(1) not null comment '是否叶子权限点(具体的操作)',
level tinyint not null comment '权限点的层级parentId为0的层级为1',
description varchar(64) null comment '权限点描述',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '权限表';
DROP TABLE IF EXISTS `logi_security_project`;
CREATE TABLE `logi_security_project`
(
id int auto_increment comment '项目id' primary key,
project_code varchar(128) not null comment '项目编号',
project_name varchar(128) not null comment '项目名',
description varchar(512) default '' not null comment '项目描述',
dept_id int not null comment '部门id',
running tinyint(1) default 1 not null comment '启用 or 停用',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '项目表';
DROP TABLE IF EXISTS `logi_security_resource_type`;
CREATE TABLE `logi_security_resource_type`
(
id int auto_increment primary key,
type_name varchar(16) null comment '资源类型名',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '资源类型表';
DROP TABLE IF EXISTS `logi_security_role`;
CREATE TABLE `logi_security_role`
(
id int auto_increment primary key,
role_code varchar(128) not null comment '角色编号',
role_name varchar(128) not null comment '名称',
description varchar(128) null comment '角色描述',
last_reviser varchar(30) null comment '最后修改人',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '角色信息';
DROP TABLE IF EXISTS `logi_security_role_permission`;
CREATE TABLE `logi_security_role_permission`
(
id int auto_increment primary key,
role_id int not null comment '角色id',
permission_id int not null comment '权限id',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '角色权限表(只保留叶子权限与角色关系)';
DROP TABLE IF EXISTS `logi_security_user`;
CREATE TABLE `logi_security_user`
(
id int auto_increment primary key,
user_name varchar(64) not null comment '用户账号',
pw varchar(2048) not null comment '用户密码',
salt char(5) default '' not null comment '密码盐',
real_name varchar(128) default '' not null comment '真实姓名',
phone char(11) default '' not null comment 'mobile',
email varchar(30) default '' not null comment 'email',
dept_id int null comment '所属部门id',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
create_time timestamp default CURRENT_TIMESTAMP null comment '注册时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户信息';
DROP TABLE IF EXISTS `logi_security_user_project`;
CREATE TABLE `logi_security_user_project`
(
id int auto_increment primary key,
user_id int not null comment '用户id',
project_id int not null comment '项目id',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户项目关系表(项目负责人)';
DROP TABLE IF EXISTS `logi_security_user_resource`;
CREATE TABLE `logi_security_user_resource`
(
id int auto_increment primary key,
user_id int not null comment '用户id',
project_id int not null comment '资源所属项目id',
resource_type_id int not null comment '资源类别id',
resource_id int not null comment '资源id',
control_level tinyint not null comment '管理级别1查看权限2管理权限',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户和资源关系表';
DROP TABLE IF EXISTS `logi_security_user_role`;
CREATE TABLE `logi_security_user_role`
(
id int auto_increment primary key,
user_id int not null comment '用户id',
role_id int not null comment '角色id',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint(1) default 0 not null comment '逻辑删除',
app_name varchar(16) null comment '应用名称'
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户角色表';
DROP TABLE IF EXISTS `logi_security_config`;
CREATE TABLE `logi_security_config`
(
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',
`value_group` varchar(100) NOT NULL DEFAULT '' COMMENT '配置项组',
`value_name` varchar(100) NOT NULL DEFAULT '' COMMENT '配置项名字',
`value` text COMMENT '配置项的值',
`edit` int(4) NOT NULL DEFAULT '1' COMMENT '是否可以编辑 1 不可编辑(程序获取) 2 可编辑',
`status` int(4) NOT NULL DEFAULT '1' COMMENT '1 正常 2 禁用',
`memo` varchar(1000) NOT NULL DEFAULT '' COMMENT '备注',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
`app_name` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '应用名称',
`operator` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '操作者',
PRIMARY KEY (`id`),
KEY `idx_group_name` (`value_group`,`value_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 COMMENT='logi配置项';
INSERT INTO `ks_km_platform_cluster_config` (`cluster_id`,`value_group`,`value_name`,`value`,`description`,`operator`) VALUES (-1,'HEALTH','HC_CLUSTER_NO_CONTROLLER','{ \"value\": 1, \"weight\": 30 } ','集群Controller数正常','know-streaming');
INSERT INTO `ks_km_platform_cluster_config` (`cluster_id`,`value_group`,`value_name`,`value`,`description`,`operator`) VALUES (-1,'HEALTH','HC_BROKER_REQUEST_QUEUE_FULL','{ \"value\": 10, \"weight\": 20 } ','Broker-RequestQueueSize指标','know-streaming');
INSERT INTO `ks_km_platform_cluster_config` (`cluster_id`,`value_group`,`value_name`,`value`,`description`,`operator`) VALUES (-1,'HEALTH','HC_BROKER_NETWORK_PROCESSOR_AVG_IDLE_TOO_LOW','{ \"value\": 0.8, \"weight\": 20 } ','Broker-NetworkProcessorAvgIdlePercent指标','know-streaming');
INSERT INTO `ks_km_platform_cluster_config` (`cluster_id`,`value_group`,`value_name`,`value`,`description`,`operator`) VALUES (-1,'HEALTH','HC_GROUP_RE_BALANCE_TOO_FREQUENTLY','{\n \"latestMinutes\": 10,\n \"detectedTimes\": 8,\n \"weight\": 10\n}\n','Group的re-balance频率','know-streaming');
INSERT INTO `ks_km_platform_cluster_config` (`cluster_id`,`value_group`,`value_name`,`value`,`description`,`operator`) VALUES (-1,'HEALTH','HC_TOPIC_NO_LEADER','{ \"value\": 1, \"weight\": 10 } ','Topic 无Leader数','know-stream');
INSERT INTO `ks_km_platform_cluster_config` (`cluster_id`,`value_group`,`value_name`,`value`,`description`,`operator`) VALUES (-1,'HEALTH','HC_TOPIC_UNDER_REPLICA_TOO_LONG','{ \"latestMinutes\": 10, \"detectedTimes\": 8, \"weight\": 10 } ','Topic 未同步持续时间','know-streaming');
-- 初始化权限
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1593', '多集群管理', '0', '0', '1', '多集群管理', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1595', '系统管理', '0', '0', '1', '系统管理', '0', 'know-streaming');
-- 多集群管理权限
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1597', '接入集群', '1593', '1', '2', '接入集群', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1599', '删除集群', '1593', '1', '2', '删除集群', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1601', 'Cluster-修改集群信息', '1593', '1', '2', 'Cluster-修改集群信息', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1603', 'Cluster-修改健康规则', '1593', '1', '2', 'Cluster-修改健康规则', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1605', 'Broker-修改Broker配置', '1593', '1', '2', 'Broker-修改Broker配置', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1607', 'Topic-新增Topic', '1593', '1', '2', 'Topic-新增Topic', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1609', 'Topic-扩分区', '1593', '1', '2', 'Topic-扩分区', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1611', 'Topic-删除Topic', '1593', '1', '2', 'Topic-扩分区', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1613', 'Topic-重置Offset', '1593', '1', '2', 'Topic-重置Offset', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1615', 'Topic-修改Topic配置', '1593', '1', '2', 'Topic-修改Topic配置', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1617', 'Consumers-重置Offset', '1593', '1', '2', 'Consumers-重置Offset', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1619', 'Test-Producer', '1593', '1', '2', 'Test-Producer', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1621', 'Test-Consumer', '1593', '1', '2', 'Test-Consumer', '0', 'know-streaming');
-- 系统管理权限
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1623', '配置管理-新增配置', '1595', '1', '2', '配置管理-新增配置', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1625', '配置管理-编辑配置', '1595', '1', '2', '配置管理-编辑配置', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1627', '配置管理-删除配置', '1595', '1', '2', '配置管理-删除配置', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1629', '用户管理-新增人员', '1595', '1', '2', '用户管理-新增人员', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1631', '用户管理-编辑人员', '1595', '1', '2', '用户管理-编辑人员', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1633', '用户管理-修改人员密码', '1595', '1', '2', '用户管理-修改人员密码', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1635', '用户管理-删除人员', '1595', '1', '2', '用户管理-删除人员', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1637', '用户管理-新增角色', '1595', '1', '2', '用户管理-新增角色', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1639', '用户管理-编辑角色', '1595', '1', '2', '用户管理-编辑角色', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1641', '用户管理-分配用户角色', '1595', '1', '2', '用户管理-分配用户角色', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('1643', '用户管理-删除角色', '1595', '1', '2', '用户管理-删除角色', '0', 'know-streaming');
-- 多集群管理权限2022-09-06新增
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2000', '多集群管理查看', '1593', '1', '2', '多集群管理查看', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2002', 'Topic-迁移副本', '1593', '1', '2', 'Topic-迁移副本', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2004', 'Topic-扩缩副本', '1593', '1', '2', 'Topic-扩缩副本', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2006', 'Cluster-LoadReBalance-周期均衡', '1593', '1', '2', 'Cluster-LoadReBalance-周期均衡', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2008', 'Cluster-LoadReBalance-立即均衡', '1593', '1', '2', 'Cluster-LoadReBalance-立即均衡', '0', 'know-streaming');
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2010', 'Cluster-LoadReBalance-设置集群规格', '1593', '1', '2', 'Cluster-LoadReBalance-设置集群规格', '0', 'know-streaming');
-- 系统管理权限2022-09-06新增
INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('3000', '系统管理查看', '1595', '1', '2', '系统管理查看', '0', 'know-streaming');
-- 初始化用户
INSERT INTO `logi_security_user` (`id`, `user_name`, `pw`, `real_name`, `is_delete`, `app_name`) VALUES ('1', 'admin', 'V1ZkU2RHRlhOVGRSUmxweFUycFNhR0V6ZEdKSk1FRjRVVU5PWkdaVmJ6SlZiWGh6WVVWQ09YdEFWbXBLTkdGcmUxc2pRREpBSTExOVNqWlNiR3hvUUgwPXtAVmpKNGFre1sjQDNAI119SjZSbGxoQH0=Mv{#cdRgJ45Lqx}3IubEW87!==', '系统管理员', '0', 'know-streaming');
-- 初始化角色
INSERT INTO `logi_security_role` (`id`, `role_code`, `role_name`, `description`, `last_reviser`, `is_delete`, `app_name`) VALUES ('1677', 'r15477137', '管理员角色', '包含系统所有权限', 'admin', '0', 'know-streaming');
-- 初始化角色权限关系
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1597', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1599', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1601', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1603', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1605', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1607', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1609', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1611', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1613', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1615', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1617', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1619', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1621', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1593', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1623', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1625', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1627', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1629', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1631', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1633', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1635', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1637', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1639', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1641', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1643', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '1595', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2000', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2002', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2004', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2006', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2008', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2010', '0', 'know-streaming');
INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '3000', '0', 'know-streaming');
-- 初始化 用户角色关系
INSERT INTO `logi_security_user_role` (`id`, `user_id`, `role_id`, `is_delete`, `app_name`) VALUES ('1', '1', '1677', '0', 'know-streaming');
INSERT INTO `logi_security_config`
(`value_group`,`value_name`,`value`,`edit`,`status`,`memo`,`is_delete`,`app_name`,`operator`)
VALUES
('SECURITY.LOGIN','SECURITY.TRICK_USERS','[\n \"admin\"\n]',1,1,'允许跳过登录的用户',0,'know-streaming','admin');

View File

@@ -0,0 +1,15 @@
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
skip-host-cache
skip-name-resolve
datadir=/data/mysql
socket=/var/lib/mysql/mysql.sock
secure-file-priv=/var/lib/mysql-files
character-set-server=utf8
user=mysql
symbolic-links=0
pid-file=/var/run/mysqld/mysqld.pid
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

View File

@@ -0,0 +1,5 @@
FROM nginx:1.18
ADD pub.tar /
ADD knowstreaming.conf /etc/nginx/conf.d/
RUN rm -rf /etc/nginx/conf.d/default.conf

View File

@@ -0,0 +1,46 @@
server {
listen 80;
server_name localhost;
gzip on;
gzip_buffers 16 8k;
gzip_comp_level 4;
gzip_http_version 1.0;
gzip_min_length 1280;
gzip_types text/plain text/css text/xml application/x-javascript application/xml application/xml+rss application/json application/javascript text/*;
gzip_vary on;
root /pub;
location / {
root /pub;
if ($request_filename ~* .*\.(?:htm|html|json)$) {
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
}
try_files $uri /layout/index.html;
}
location ~* \.(json)$ {
add_header Cache-Control no-cache;
}
location @kmfallback {
}
#location ~ ^/(clusters|config|cluster|login) {
# rewrite ^.*$ /;
#}
location ~ ^/ks-km/api/v3 {
#rewrite ^/ks-km/api/v3/(.*)$ /ks-km/ks-km/api/v3/$1 break;
proxy_pass http://knowstreaming-manager;
#proxy_pass https://api-kylin-xg02.intra.xiaojukeji.com;
#proxy_cookie_path /ks-km/ /;
#proxy_set_header Host $host;
#proxy_set_header Referer $http_referer;
#proxy_set_header Cookie $http_cookie;
#proxy_set_header X-Real-Ip $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/logi-security/api/v1 {
#rewrite ^/logi-security/api/v1/(.*)$ /ks-km/logi-security/api/v1/$1 break;
proxy_pass http://knowstreaming-manager;
#proxy_pass https://api-kylin-xg02.intra.xiaojukeji.com;
}
location ~ ^/(401|403|404|500){
rewrite ^.*$ /;
}
}

View File

@@ -4,13 +4,13 @@ description: knowstreaming-manager Helm chart
type: application type: application
version: 0.1.4 version: 0.1.5
maintainers: maintainers:
- email: didicloud@didiglobal.com - email: didicloud@didiglobal.com
name: didicloud name: didicloud
appVersion: "3.0.0-beta.2" appVersion: "3.0.0-beta.3"
dependencies: dependencies:
- name: knowstreaming-web - name: knowstreaming-web

View File

@@ -21,7 +21,7 @@ spec:
{{- include "ksmysql.selectorLabels" . | nindent 8 }} {{- include "ksmysql.selectorLabels" . | nindent 8 }}
spec: spec:
containers: containers:
- image: knowstreaming/knowstreaming-mysql:0.2.0 - image: knowstreaming/knowstreaming-mysql:latest
name: {{ .Chart.Name }} name: {{ .Chart.Name }}
env: env:
- name: MYSQL_DATABASE - name: MYSQL_DATABASE

View File

@@ -3,7 +3,7 @@ replicaCount: 2
image: image:
repository: knowstreaming/knowstreaming-manager repository: knowstreaming/knowstreaming-manager
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: "0.2.0" tag: "latest"
imagePullSecrets: [] imagePullSecrets: []
nameOverride: "" nameOverride: ""
@@ -73,7 +73,7 @@ knowstreaming-web:
image: image:
repository: knowstreaming/knowstreaming-ui repository: knowstreaming/knowstreaming-ui
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: "0.2.0" tag: "latest"
service: service:
type: NodePort type: NodePort

View File

@@ -257,6 +257,7 @@ CREATE TABLE `ks_km_physical_cluster` (
`kafka_version` varchar(32) NOT NULL DEFAULT '' COMMENT 'kafka版本', `kafka_version` varchar(32) NOT NULL DEFAULT '' COMMENT 'kafka版本',
`client_properties` text COMMENT 'Kafka客户端配置', `client_properties` text COMMENT 'Kafka客户端配置',
`jmx_properties` text COMMENT 'JMX配置', `jmx_properties` text COMMENT 'JMX配置',
`zk_properties` text COMMENT 'ZK配置',
`description` text COMMENT '备注', `description` text COMMENT '备注',
`auth_type` int(11) NOT NULL DEFAULT '0' COMMENT '认证类型,-1未知0:无认证,', `auth_type` int(11) NOT NULL DEFAULT '0' COMMENT '认证类型,-1未知0:无认证,',
`run_state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '运行状态, 0表示未监控, 1监控中有ZK2:监控中无ZK', `run_state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '运行状态, 0表示未监控, 1监控中有ZK2:监控中无ZK',

View File

@@ -392,10 +392,7 @@ public class ESOpClient {
return false; return false;
} }
/** public boolean templateExist(String indexTemplateName){
* 创建索引模板
*/
public boolean createIndexTemplateIfNotExist(String indexTemplateName, String config) {
ESClient esClient = null; ESClient esClient = null;
try { try {
@@ -410,6 +407,29 @@ public class ESOpClient {
if (null != templateConfig) { if (null != templateConfig) {
return true; return true;
} }
} catch (Exception e) {
LOGGER.warn( "method=templateExist||indexTemplateName={}||msg=exception!",
indexTemplateName, e);
} finally {
if (esClient != null) {
this.returnESClientToPool(esClient);
}
}
return false;
}
/**
* 创建索引模板
*/
public boolean createIndexTemplateIfNotExist(String indexTemplateName, String config) {
ESClient esClient = null;
try {
esClient = this.getESClientFromPool();
//存在模板就返回,不存在就创建
if(templateExist(indexTemplateName)){return true;}
// 创建新的模板 // 创建新的模板
ESIndicesPutTemplateResponse response = esClient.admin().indices().preparePutTemplate( indexTemplateName ) ESIndicesPutTemplateResponse response = esClient.admin().indices().preparePutTemplate( indexTemplateName )
@@ -417,8 +437,7 @@ public class ESOpClient {
return response.getAcknowledged(); return response.getAcknowledged();
} catch (Exception e) { } catch (Exception e) {
LOGGER.warn( LOGGER.warn( "method=createIndexTemplateIfNotExist||indexTemplateName={}||config={}||msg=exception!",
"class=ESOpClient||method=createIndexTemplateIfNotExist||indexTemplateName={}||config={}||msg=exception!",
indexTemplateName, config, e indexTemplateName, config, e
); );
} finally { } finally {

View File

@@ -13,6 +13,7 @@
<result column="kafka_version" property="kafkaVersion" /> <result column="kafka_version" property="kafkaVersion" />
<result column="client_properties" property="clientProperties" /> <result column="client_properties" property="clientProperties" />
<result column="jmx_properties" property="jmxProperties" /> <result column="jmx_properties" property="jmxProperties" />
<result column="zk_properties" property="zkProperties" />
<result column="auth_type" property="authType" /> <result column="auth_type" property="authType" />
<result column="run_state" property="runState" /> <result column="run_state" property="runState" />
<result column="description" property="description" /> <result column="description" property="description" />
@@ -23,8 +24,8 @@
useGeneratedKeys="true" useGeneratedKeys="true"
keyProperty="id"> keyProperty="id">
INSERT INTO ks_km_physical_cluster INSERT INTO ks_km_physical_cluster
(name, zookeeper, bootstrap_servers, kafka_version, client_properties, jmx_properties, description, auth_type, run_state) (name, zookeeper, bootstrap_servers, kafka_version, client_properties, jmx_properties, zk_properties, description, auth_type, run_state)
VALUES VALUES
(#{name}, #{zookeeper}, #{bootstrapServers}, #{kafkaVersion}, #{clientProperties}, #{jmxProperties}, #{description}, #{authType}, #{runState}) (#{name}, #{zookeeper}, #{bootstrapServers}, #{kafkaVersion}, #{clientProperties}, #{jmxProperties}, #{zkProperties}, #{description}, #{authType}, #{runState})
</insert> </insert>
</mapper> </mapper>

View File

@@ -19,8 +19,8 @@
<insert id="addAndSetId" parameterType="com.xiaojukeji.know.streaming.km.common.bean.po.reassign.ReassignJobPO"> <insert id="addAndSetId" parameterType="com.xiaojukeji.know.streaming.km.common.bean.po.reassign.ReassignJobPO">
INSERT INTO ks_km_reassign_job INSERT INTO ks_km_reassign_job
(id, cluster_phy_id, reassignment_json, description, throttle_unit_byte, start_time, finished_time, creator, status) (id, cluster_phy_id, reassignment_json, description, throttle_unit_byte, creator, status)
VALUES VALUES
(#{id}, #{clusterPhyId}, #{reassignmentJson}, #{description}, #{throttleUnitByte}, #{startTime}, #{finishedTime}, #{creator}, #{status}) (#{id}, #{clusterPhyId}, #{reassignmentJson}, #{description}, #{throttleUnitByte}, #{creator}, #{status})
</insert> </insert>
</mapper> </mapper>

View File

@@ -11,9 +11,11 @@ import com.xiaojukeji.know.streaming.km.common.constant.Constant;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
@@ -67,7 +69,7 @@ public class VersionController {
@PostMapping(value = "clusters/{clusterId}/types/{type}/user-metric-config") @PostMapping(value = "clusters/{clusterId}/types/{type}/user-metric-config")
@ResponseBody @ResponseBody
public Result<Void> updateUserMetricItem(@PathVariable Long clusterId, @PathVariable Integer type, public Result<Void> updateUserMetricItem(@PathVariable Long clusterId, @PathVariable Integer type,
@RequestBody UserMetricConfigDTO userMetricConfigDTO, HttpServletRequest request){ @Validated @RequestBody UserMetricConfigDTO userMetricConfigDTO, HttpServletRequest request) {
return versionControlManager.updateUserMetricItem(clusterId, type, userMetricConfigDTO, HttpRequestUtil.getOperator(request)); return versionControlManager.updateUserMetricItem(clusterId, type, userMetricConfigDTO, HttpRequestUtil.getOperator(request));
} }
} }

View File

@@ -9,36 +9,38 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy;
import com.xiaojukeji.know.streaming.km.common.bean.entity.config.healthcheck.BaseClusterHealthConfig; import com.xiaojukeji.know.streaming.km.common.bean.entity.config.healthcheck.BaseClusterHealthConfig;
import com.xiaojukeji.know.streaming.km.common.bean.entity.health.HealthCheckResult; import com.xiaojukeji.know.streaming.km.common.bean.entity.health.HealthCheckResult;
import com.xiaojukeji.know.streaming.km.common.bean.entity.param.cluster.ClusterPhyParam; import com.xiaojukeji.know.streaming.km.common.bean.entity.param.cluster.ClusterPhyParam;
import com.xiaojukeji.know.streaming.km.common.component.SpringTool;
import com.xiaojukeji.know.streaming.km.common.constant.Constant; import com.xiaojukeji.know.streaming.km.common.constant.Constant;
import com.xiaojukeji.know.streaming.km.common.enums.health.HealthCheckDimensionEnum; import com.xiaojukeji.know.streaming.km.common.enums.health.HealthCheckDimensionEnum;
import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils;
import com.xiaojukeji.know.streaming.km.core.service.health.checkresult.HealthCheckResultService;
import com.xiaojukeji.know.streaming.km.core.service.health.checker.AbstractHealthCheckService; import com.xiaojukeji.know.streaming.km.core.service.health.checker.AbstractHealthCheckService;
import com.xiaojukeji.know.streaming.km.core.service.health.checker.broker.HealthCheckBrokerService;
import com.xiaojukeji.know.streaming.km.core.service.health.checkresult.HealthCheckResultService;
import com.xiaojukeji.know.streaming.km.task.metrics.AbstractAsyncMetricsDispatchTask; import com.xiaojukeji.know.streaming.km.task.metrics.AbstractAsyncMetricsDispatchTask;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.*; import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Task(name = "HealthCheckTask", @Task(name = "BrokerHealthCheckTask",
description = "健康检查", description = "Broker健康检查",
cron = "0 0/1 * * * ? *", cron = "0 0/1 * * * ? *",
autoRegister = true, autoRegister = true,
consensual = ConsensualEnum.BROADCAST, consensual = ConsensualEnum.BROADCAST,
timeout = 2 * 60) timeout = 2 * 60)
public class HealthCheckTask extends AbstractAsyncMetricsDispatchTask { public class BrokerHealthCheckTask extends AbstractAsyncMetricsDispatchTask {
private static final ILog log = LogFactory.getLog(HealthCheckTask.class); private static final ILog log = LogFactory.getLog(BrokerHealthCheckTask.class);
@Autowired @Autowired
private HealthCheckResultService healthCheckResultService; private HealthCheckResultService healthCheckResultService;
private final List<AbstractHealthCheckService> healthCheckServiceList = new ArrayList<>( @Autowired
SpringTool.getBeansOfType(AbstractHealthCheckService.class).values() private HealthCheckBrokerService healthCheckBrokerService;
);
@Override @Override
public TaskResult processClusterTask(ClusterPhy clusterPhy, long triggerTimeUnitMs) { public TaskResult processClusterTask(ClusterPhy clusterPhy, long triggerTimeUnitMs) {
@@ -53,25 +55,22 @@ public class HealthCheckTask extends AbstractAsyncMetricsDispatchTask {
List<HealthCheckResult> resultList = new ArrayList<>(); List<HealthCheckResult> resultList = new ArrayList<>();
// 遍历Check-Service // 遍历Check-Service
for (AbstractHealthCheckService healthCheckService: healthCheckServiceList) { List<ClusterPhyParam> paramList = healthCheckBrokerService.getResList(clusterPhy.getId());
List<ClusterPhyParam> paramList = healthCheckService.getResList(clusterPhy.getId()); if (ValidateUtils.isEmptyList(paramList)) {
if (ValidateUtils.isEmptyList(paramList)) { // 当前无该维度的资源则直接设置为
// 当前无该维度的资源则直接设置为 resultList.addAll(this.getNoResResult(clusterPhy.getId(), healthCheckBrokerService, healthConfigMap));
resultList.addAll(this.getNoResResult(clusterPhy.getId(), healthCheckService, healthConfigMap)); }
continue;
}
// 遍历资源 // 遍历资源
for (ClusterPhyParam clusterPhyParam: paramList) { for (ClusterPhyParam clusterPhyParam: paramList) {
resultList.addAll(this.checkAndGetResult(healthCheckService, clusterPhyParam, healthConfigMap)); resultList.addAll(this.checkAndGetResult(healthCheckBrokerService, clusterPhyParam, healthConfigMap));
}
} }
for (HealthCheckResult checkResult: resultList) { for (HealthCheckResult checkResult: resultList) {
try { try {
healthCheckResultService.replace(checkResult); healthCheckResultService.replace(checkResult);
} catch (Exception e) { } catch (Exception e) {
log.error("method=processSubTask||clusterPhyId={}||checkResult={}||errMsg=exception!", clusterPhy.getId(), checkResult, e); log.error("class=BrokerHealthCheckTask||method=processSubTask||clusterPhyId={}||checkResult={}||errMsg=exception!", clusterPhy.getId(), checkResult, e);
} }
} }
@@ -79,7 +78,7 @@ public class HealthCheckTask extends AbstractAsyncMetricsDispatchTask {
try { try {
healthCheckResultService.deleteByUpdateTimeBeforeInDB(clusterPhy.getId(), new Date(triggerTimeUnitMs - 10 * 60 * 1000)); healthCheckResultService.deleteByUpdateTimeBeforeInDB(clusterPhy.getId(), new Date(triggerTimeUnitMs - 10 * 60 * 1000));
} catch (Exception e) { } catch (Exception e) {
log.error("method=processSubTask||clusterPhyId={}||errMsg=exception!", clusterPhy.getId(), e); log.error("class=BrokerHealthCheckTask||method=processSubTask||clusterPhyId={}||errMsg=exception!", clusterPhy.getId(), e);
} }
return TaskResult.SUCCESS; return TaskResult.SUCCESS;

View File

@@ -0,0 +1,130 @@
package com.xiaojukeji.know.streaming.km.task.health;
import com.didiglobal.logi.job.annotation.Task;
import com.didiglobal.logi.job.common.TaskResult;
import com.didiglobal.logi.job.core.consensual.ConsensualEnum;
import com.didiglobal.logi.log.ILog;
import com.didiglobal.logi.log.LogFactory;
import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy;
import com.xiaojukeji.know.streaming.km.common.bean.entity.config.healthcheck.BaseClusterHealthConfig;
import com.xiaojukeji.know.streaming.km.common.bean.entity.health.HealthCheckResult;
import com.xiaojukeji.know.streaming.km.common.bean.entity.param.cluster.ClusterPhyParam;
import com.xiaojukeji.know.streaming.km.common.constant.Constant;
import com.xiaojukeji.know.streaming.km.common.enums.health.HealthCheckDimensionEnum;
import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils;
import com.xiaojukeji.know.streaming.km.core.service.health.checker.AbstractHealthCheckService;
import com.xiaojukeji.know.streaming.km.core.service.health.checker.cluster.HealthCheckClusterService;
import com.xiaojukeji.know.streaming.km.core.service.health.checkresult.HealthCheckResultService;
import com.xiaojukeji.know.streaming.km.task.metrics.AbstractAsyncMetricsDispatchTask;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@NoArgsConstructor
@AllArgsConstructor
@Task(name = "ClusterHealthCheckTask",
description = "Cluster健康检查",
cron = "0 0/1 * * * ? *",
autoRegister = true,
consensual = ConsensualEnum.BROADCAST,
timeout = 2 * 60)
public class ClusterHealthCheckTask extends AbstractAsyncMetricsDispatchTask {
private static final ILog log = LogFactory.getLog(ClusterHealthCheckTask.class);
@Autowired
private HealthCheckResultService healthCheckResultService;
@Autowired
private HealthCheckClusterService healthCheckClusterService;
@Override
public TaskResult processClusterTask(ClusterPhy clusterPhy, long triggerTimeUnitMs) {
return this.calAndUpdateHealthCheckResult(clusterPhy, triggerTimeUnitMs);
}
private TaskResult calAndUpdateHealthCheckResult(ClusterPhy clusterPhy, long triggerTimeUnitMs) {
// 获取配置,<配置名,配置信息>
Map<String, BaseClusterHealthConfig> healthConfigMap = healthCheckResultService.getClusterHealthConfig(clusterPhy.getId());
// 检查结果
List<HealthCheckResult> resultList = new ArrayList<>();
// 遍历Check-Service
List<ClusterPhyParam> paramList = healthCheckClusterService.getResList(clusterPhy.getId());
if (ValidateUtils.isEmptyList(paramList)) {
// 当前无该维度的资源,则直接设置为
resultList.addAll(this.getNoResResult(clusterPhy.getId(), healthCheckClusterService, healthConfigMap));
}
// 遍历资源
for (ClusterPhyParam clusterPhyParam: paramList) {
resultList.addAll(this.checkAndGetResult(healthCheckClusterService, clusterPhyParam, healthConfigMap));
}
for (HealthCheckResult checkResult: resultList) {
try {
healthCheckResultService.replace(checkResult);
} catch (Exception e) {
log.error("class=ClusterHealthCheckTask||method=processSubTask||clusterPhyId={}||checkResult={}||errMsg=exception!", clusterPhy.getId(), checkResult, e);
}
}
// 删除10分钟之前的检查结果
try {
healthCheckResultService.deleteByUpdateTimeBeforeInDB(clusterPhy.getId(), new Date(triggerTimeUnitMs - 10 * 60 * 1000));
} catch (Exception e) {
log.error("class=ClusterHealthCheckTask||method=processSubTask||clusterPhyId={}||errMsg=exception!", clusterPhy.getId(), e);
}
return TaskResult.SUCCESS;
}
private List<HealthCheckResult> getNoResResult(Long clusterPhyId, AbstractHealthCheckService healthCheckService, Map<String, BaseClusterHealthConfig> healthConfigMap) {
List<HealthCheckResult> resultList = new ArrayList<>();
// 进行检查
for (BaseClusterHealthConfig clusterHealthConfig: healthConfigMap.values()) {
HealthCheckDimensionEnum dimensionEnum = healthCheckService.getHealthCheckDimensionEnum();
if (!clusterHealthConfig.getCheckNameEnum().getDimensionEnum().equals(dimensionEnum)) {
// 类型不匹配
continue;
}
// 记录
HealthCheckResult checkResult = new HealthCheckResult(
dimensionEnum.getDimension(),
clusterHealthConfig.getCheckNameEnum().getConfigName(),
clusterPhyId,
"-1"
);
checkResult.setPassed(Constant.YES);
resultList.add(checkResult);
}
return resultList;
}
private List<HealthCheckResult> checkAndGetResult(AbstractHealthCheckService healthCheckService,
ClusterPhyParam clusterPhyParam,
Map<String, BaseClusterHealthConfig> healthConfigMap) {
List<HealthCheckResult> resultList = new ArrayList<>();
// 进行检查
for (BaseClusterHealthConfig clusterHealthConfig: healthConfigMap.values()) {
HealthCheckResult healthCheckResult = healthCheckService.checkAndGetResult(clusterPhyParam, clusterHealthConfig);
if (healthCheckResult == null) {
continue;
}
// 记录
resultList.add(healthCheckResult);
}
return resultList;
}
}

Some files were not shown because too many files have changed in this diff Show More