diff --git a/README.md b/README.md index 77729c25..db8a1b52 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ - [滴滴Logi-KafkaManager 开源之路](https://xie.infoq.cn/article/0223091a99e697412073c0d64) - [滴滴Logi-KafkaManager 系列视频教程](https://mp.weixin.qq.com/s/9X7gH0tptHPtfjPPSdGO8g) - [kafka实践(十五):滴滴开源Kafka管控平台 Logi-KafkaManager研究--A叶子叶来](https://blog.csdn.net/yezonggang/article/details/113106244) +- [kafka的灵魂伴侣Logi-KafkaManager系列文章专栏 --石臻](https://blog.csdn.net/u010634066/category_10977588.html) ## 3 滴滴Logi开源用户交流群 diff --git a/build.sh b/build.sh index a6e86d7d..9c107907 100644 --- a/build.sh +++ b/build.sh @@ -4,7 +4,7 @@ cd $workspace ## constant OUTPUT_DIR=./output -KM_VERSION=2.3.1 +KM_VERSION=2.4.0 APP_NAME=kafka-manager APP_DIR=${APP_NAME}-${KM_VERSION} diff --git a/container/dockerfiles/Dockerfile b/container/dockerfiles/Dockerfile index d8a3d158..1ffe27e4 100644 --- a/container/dockerfiles/Dockerfile +++ b/container/dockerfiles/Dockerfile @@ -1,14 +1,11 @@ -FROM openjdk:8-jdk-alpine3.9 +FROM openjdk:16-jdk-alpine3.13 LABEL author="yangvipguang" -ENV VERSION 2.1.0 -ENV JAR_PATH kafka-manager-web/target -COPY $JAR_PATH/kafka-manager-web-$VERSION-SNAPSHOT.jar /tmp/app.jar -COPY $JAR_PATH/application.yml /km/ +ENV VERSION 2.3.1 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories -RUN apk add --no-cache --virtual .build-deps \ +RUN apk add --no-cache --virtual .build-deps \ font-adobe-100dpi \ ttf-dejavu \ fontconfig \ @@ -19,26 +16,28 @@ RUN apk add --no-cache --virtual .build-deps \ tomcat-native \ && apk del .build-deps +RUN apk add --no-cache tini + + + + ENV AGENT_HOME /opt/agent/ WORKDIR /tmp + +COPY $JAR_PATH/kafka-manager.jar app.jar +# COPY application.yml application.yml ##默认使用helm 挂载,防止敏感配置泄露 + COPY docker-depends/config.yaml $AGENT_HOME -COPY docker-depends/jmx_prometheus_javaagent-0.14.0.jar $AGENT_HOME - -ENV JAVA_AGENT="-javaagent:$AGENT_HOME/jmx_prometheus_javaagent-0.14.0.jar=9999:$AGENT_HOME/config.yaml" +COPY docker-depends/jmx_prometheus_javaagent-0.15.0.jar $AGENT_HOME +ENV JAVA_AGENT="-javaagent:$AGENT_HOME/jmx_prometheus_javaagent-0.15.0.jar=9999:$AGENT_HOME/config.yaml" ENV JAVA_HEAP_OPTS="-Xms1024M -Xmx1024M -Xmn100M " - ENV JAVA_OPTS="-verbose:gc \ - -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -Xloggc:/tmp/gc.log -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps \ -XX:MaxMetaspaceSize=256M -XX:+DisableExplicitGC -XX:+UseStringDeduplication \ -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:-UseContainerSupport" -#-Xlog:gc -Xlog:gc* -Xlog:gc+heap=trace -Xlog:safepoint - EXPOSE 8080 9999 -ENTRYPOINT ["sh","-c","java -jar $JAVA_HEAP_OPTS $JAVA_OPTS /tmp/app.jar --spring.config.location=/km/application.yml"] - -## 默认不带Prometheus JMX监控,需要可以自行取消以下注释并注释上面一行默认Entrypoint 命令。 -## ENTRYPOINT ["sh","-c","java -jar $JAVA_AGENT $JAVA_HEAP_OPTS $JAVA_OPTS /tmp/app.jar --spring.config.location=/km/application.yml"] +ENTRYPOINT ["tini", "--"] +CMD ["sh","-c","java -jar $JAVA_AGENT $JAVA_HEAP_OPTS $JAVA_OPTS app.jar --spring.config.location=application.yml"] diff --git a/container/dockerfiles/docker-depends/jmx_prometheus_javaagent-0.15.0.jar b/container/dockerfiles/docker-depends/jmx_prometheus_javaagent-0.15.0.jar new file mode 100644 index 00000000..d896a217 Binary files /dev/null and b/container/dockerfiles/docker-depends/jmx_prometheus_javaagent-0.15.0.jar differ diff --git a/docs/user_guide/faq.md b/docs/user_guide/faq.md index c0c6b1a3..bf569fb2 100644 --- a/docs/user_guide/faq.md +++ b/docs/user_guide/faq.md @@ -20,8 +20,11 @@ - 8、`topic biz data not exist`错误及处理方式 - 9、进程启动后,如何查看API文档 - 10、如何创建告警组? -- 11、连接信息、耗时信息为什么没有数据? +- 11、连接信息、耗时信息、磁盘信息为什么没有数据? - 12、逻辑集群申请审批通过之后为什么看不到逻辑集群? +- 13、heartbeat表关联业务和使用场景是什么? +- 14、集群的删除,是否会真正的删除集群? +- 15、APP(应用)如何被使用起来? --- @@ -70,7 +73,7 @@ - 3、数据库时区问题。 -检查MySQL的topic_metrics表,查看是否有数据,如果有数据,那么再检查设置的时区是否正确。 +检查MySQL的cluster表的gmt_modify字段,做一个update动作,看这个gmt_modify时间是否是当前时间,如果不是,那么就是时区问题了。时区不对问题具体可以搜索一下看如何解决。 --- @@ -113,11 +116,14 @@ ### 10、如何创建告警组? -这块需要配合监控系统进行使用,现在默认已经实现了夜莺的对接,当然也可以对接自己内部的监控系统,不过需要实现一些接口。 +告警组的创建需要到Logi-KM对接的监控系统中创建,比如我们现在默认是对接了夜莺,那么告警组需要到夜莺中创建,如果没有安装夜莺,那么需要安装一下夜莺并进行对接。当然,这里也可以对接自己内部的监控系统,不过需要实现一些接口。 具体的文档可见:[监控功能对接夜莺](../dev_guide/monitor_system_integrate_with_n9e.md)、[监控功能对接其他系统](../dev_guide/monitor_system_integrate_with_self.md) -### 11、连接信息、耗时信息为什么没有数据? +那么在夜莺中,如何创建告警组呢? +需要前往夜莺平台-用户资源中心-团队管理中新建团队。新建过团队之后再次回到Logi-KM中刷新页面就可以在该下拉框中选择告警接收组了。 + +### 11、连接信息、耗时信息、磁盘信息为什么没有数据? 这块需要结合滴滴内部的kafka-gateway一同使用才会有数据,滴滴kafka-gateway暂未开源。 @@ -126,3 +132,26 @@ 逻辑集群的申请与审批仅仅只是一个工单流程,并不会去实际创建逻辑集群,逻辑集群的创建还需要手动去创建。 具体的操作可见:[kafka-manager 接入集群](add_cluster/add_cluster.md)。 + + +### 13、heartbeat表关联业务和使用场景是什么? + +做任务抢占用的。 + +KM支持HA的方式部署,那么部署多台的时候,就会出现每一台都可能去做指标收集的事情,这块就使用heartbeat表做KM的存活性判断,然后进行任务的抢占或者是均衡。 + +更多详细的内容,可以看一下源码中,heartbeat表在哪里被使用了。 + + +### 14、集群的删除,是否会真正的删除集群? + +Logi-KM的运维管控,集群列表中的集群删除,仅仅只是将该集群从Logi-KM中进行删除,并不会对真正的物理集群做什么操作。 + + +### 15、APP(应用)如何被使用起来? + +app在Logi-KM中可以近似理解为租户,或者是kafka里面的一个账号的概念。 + +界面中显示的app信息、权限信息等,在平台层面仅仅只是控制Topic或集群在平台上的可见性,如果使用的是社区版本的Kafka,那么实际上是不能真正的管控到客户端对Topic的生产和消费。 + +但是如果是使用的滴滴的Kafka-Gateway,那么是可以做到对客户端的生产和消费的权限管控。滴滴的Kafka-Gateway暂未开源,属于企业服务,具体的可以入群交流,群地址在README中。 diff --git a/docs/user_guide/user_guide_cn.md b/docs/user_guide/user_guide_cn.md index 3d0519ea..caebf2b0 100644 --- a/docs/user_guide/user_guide_cn.md +++ b/docs/user_guide/user_guide_cn.md @@ -609,10 +609,10 @@ Lag:表示该消费客户端是否有堆积;等于 partition offset-consume 集群类型:选择创建的集群为“独享”还是“独立”。 -* 独享集群意味着,您独自拥有一个 -集群; +* 独享集群意味着, 您拥有一个集群中,部分broker的使用权限。 -* 独立集群意味着,您拥有一个集群中,部分broker的使用权限。 +* 独立集群意味着,您独自拥有一个 + 物理集群; * 共享集群意味着,大家共用一个集群及其中broker。 diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/bizenum/OperateEnum.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/bizenum/OperateEnum.java index 2bc874ec..af69ea50 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/bizenum/OperateEnum.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/bizenum/OperateEnum.java @@ -46,7 +46,7 @@ public enum OperateEnum { public static boolean validate(Integer code) { if (code == null) { - return false; + return true; } for (OperateEnum state : OperateEnum.values()) { if (state.getCode() == code) { diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/constant/ApiPrefix.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/constant/ApiPrefix.java index b90918eb..1aec18f2 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/constant/ApiPrefix.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/constant/ApiPrefix.java @@ -20,6 +20,12 @@ public class ApiPrefix { // open public static final String API_V1_THIRD_PART_PREFIX = API_V1_PREFIX + "third-part/"; + // 开放给OP的接口, 后续对 应的接口的集群都需要是物理集群 + public static final String API_V1_THIRD_PART_OP_PREFIX = API_V1_THIRD_PART_PREFIX + "op/"; + + // 开放给Normal的接口, 后续对应的接口的集群,都需要是逻辑集群 + public static final String API_V1_THIRD_PART_NORMAL_PREFIX = API_V1_THIRD_PART_PREFIX + "normal/"; + // gateway public static final String GATEWAY_API_V1_PREFIX = "/gateway" + API_V1_PREFIX; } \ No newline at end of file diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/op/topic/TopicCreationDTO.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/op/topic/TopicCreationDTO.java index 66c26c5b..b92ef7c1 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/op/topic/TopicCreationDTO.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/op/topic/TopicCreationDTO.java @@ -40,6 +40,9 @@ public class TopicCreationDTO extends ClusterTopicDTO { @ApiModelProperty(value = "Topic属性列表") private Properties properties; + @ApiModelProperty(value = "最大写入字节数") + private Long peakBytesIn; + public String getAppId() { return appId; } @@ -104,6 +107,14 @@ public class TopicCreationDTO extends ClusterTopicDTO { this.properties = properties; } + public Long getPeakBytesIn() { + return peakBytesIn; + } + + public void setPeakBytesIn(Long peakBytesIn) { + this.peakBytesIn = peakBytesIn; + } + @Override public String toString() { return "TopicCreationDTO{" + @@ -135,4 +146,4 @@ public class TopicCreationDTO extends ClusterTopicDTO { } return true; } -} \ No newline at end of file +} diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/rd/OperateRecordDTO.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/rd/OperateRecordDTO.java index 1837ecfc..7f191017 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/rd/OperateRecordDTO.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/dto/rd/OperateRecordDTO.java @@ -81,11 +81,6 @@ public class OperateRecordDTO { } public boolean legal() { - if (!ModuleEnum.validate(moduleId) || - (!ValidateUtils.isNull(operateId) && OperateEnum.validate(operateId)) - ) { - return false; - } - return true; + return !ValidateUtils.isNull(moduleId) && ModuleEnum.validate(moduleId) && OperateEnum.validate(operateId); } } diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/pojo/TopicDO.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/pojo/TopicDO.java index b4b56712..ecb97e47 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/pojo/TopicDO.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/pojo/TopicDO.java @@ -1,6 +1,7 @@ package com.xiaojukeji.kafka.manager.common.entity.pojo; import com.xiaojukeji.kafka.manager.common.entity.dto.op.topic.TopicCreationDTO; +import com.xiaojukeji.kafka.manager.common.utils.ValidateUtils; import java.util.Date; @@ -95,6 +96,7 @@ public class TopicDO { topicDO.setClusterId(dto.getClusterId()); topicDO.setTopicName(dto.getTopicName()); topicDO.setDescription(dto.getDescription()); + topicDO.setPeakBytesIn(ValidateUtils.isNull(dto.getPeakBytesIn()) ? -1L : dto.getPeakBytesIn()); return topicDO; } -} \ No newline at end of file +} diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/common/BrokerOverviewVO.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/common/BrokerOverviewVO.java index bf853853..b2cde3bf 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/common/BrokerOverviewVO.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/common/BrokerOverviewVO.java @@ -33,7 +33,7 @@ public class BrokerOverviewVO { @ApiModelProperty(value = "分区数") private Integer partitionCount; - @ApiModelProperty(value = "已同步副本数") + @ApiModelProperty(value = "失效副本分区的个数") private Integer underReplicatedPartitions; @ApiModelProperty(value = "未同步") diff --git a/kafka-manager-extends/kafka-manager-openapi/src/main/java/com/xiaojukeji/kafka/manager/openapi/common/vo/TopicStatisticMetricsVO.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/normal/topic/TopicStatisticMetricsVO.java similarity index 91% rename from kafka-manager-extends/kafka-manager-openapi/src/main/java/com/xiaojukeji/kafka/manager/openapi/common/vo/TopicStatisticMetricsVO.java rename to kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/normal/topic/TopicStatisticMetricsVO.java index 3665b7ac..c83c24d2 100644 --- a/kafka-manager-extends/kafka-manager-openapi/src/main/java/com/xiaojukeji/kafka/manager/openapi/common/vo/TopicStatisticMetricsVO.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/entity/vo/normal/topic/TopicStatisticMetricsVO.java @@ -1,4 +1,4 @@ -package com.xiaojukeji.kafka.manager.openapi.common.vo; +package com.xiaojukeji.kafka.manager.common.entity.vo.normal.topic; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -14,7 +14,6 @@ public class TopicStatisticMetricsVO { public TopicStatisticMetricsVO(Double peakBytesIn) { this.peakBytesIn = peakBytesIn; - } public Double getPeakBytesIn() { diff --git a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/zookeeper/znode/brokers/BrokerMetadata.java b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/zookeeper/znode/brokers/BrokerMetadata.java index 51c4b06b..3c179b4f 100644 --- a/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/zookeeper/znode/brokers/BrokerMetadata.java +++ b/kafka-manager-common/src/main/java/com/xiaojukeji/kafka/manager/common/zookeeper/znode/brokers/BrokerMetadata.java @@ -1,8 +1,5 @@ package com.xiaojukeji.kafka.manager.common.zookeeper.znode.brokers; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.List; /** @@ -18,12 +15,11 @@ import java.util.List; * "host":null, * "timestamp":"1546632983233", * "port":-1, - * "version":4 + * "version":4, + * "rack": "CY" * } */ public class BrokerMetadata implements Cloneable { - private final static Logger LOGGER = LoggerFactory.getLogger(TopicMetadata.class); - private long clusterId; private int brokerId; @@ -43,6 +39,8 @@ public class BrokerMetadata implements Cloneable { private long timestamp; + private String rack; + public long getClusterId() { return clusterId; } @@ -107,14 +105,12 @@ public class BrokerMetadata implements Cloneable { this.timestamp = timestamp; } - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException var3) { - LOGGER.error("clone BrokerMetadata failed.", var3); - } - return null; + public String getRack() { + return rack; + } + + public void setRack(String rack) { + this.rack = rack; } @Override @@ -128,6 +124,7 @@ public class BrokerMetadata implements Cloneable { ", jmxPort=" + jmx_port + ", version='" + version + '\'' + ", timestamp=" + timestamp + + ", rack='" + rack + '\'' + '}'; } } diff --git a/kafka-manager-console/src/component/flow-table/index.tsx b/kafka-manager-console/src/component/flow-table/index.tsx index 1f7d9be6..c62f7089 100644 --- a/kafka-manager-console/src/component/flow-table/index.tsx +++ b/kafka-manager-console/src/component/flow-table/index.tsx @@ -68,8 +68,8 @@ export class StatusGraghCom extends React.Component { public render() { const statusData = this.getData(); const loading = this.getLoading(); - if (!statusData) return null; const data: any[] = []; + if (!statusData) return ; Object.keys(statusData).map((key) => { if (statusData[key]) { const v = key === 'byteIn' || key === 'byteOut' ? statusData[key].map(i => i && (i / 1024).toFixed(2)) : @@ -85,7 +85,7 @@ export class StatusGraghCom extends React.Component { } }); return ( -
+
); } } diff --git a/kafka-manager-console/src/component/x-form/index.less b/kafka-manager-console/src/component/x-form/index.less index 95152e60..a08230a6 100644 --- a/kafka-manager-console/src/component/x-form/index.less +++ b/kafka-manager-console/src/component/x-form/index.less @@ -1,4 +1,4 @@ -.ant-input-number { +.ant-input-number, .ant-form-item-children .ant-select { width: 314px } diff --git a/kafka-manager-console/src/constants/left-menu.ts b/kafka-manager-console/src/constants/left-menu.ts index 27fcfe0b..e7452667 100644 --- a/kafka-manager-console/src/constants/left-menu.ts +++ b/kafka-manager-console/src/constants/left-menu.ts @@ -59,6 +59,10 @@ export const adminMenu = [{ href: `/admin/bill`, i: 'k-icon-renwuliebiao', title: '用户账单', +},{ + href: `/admin/operation-record`, + i: 'k-icon-operationrecord', + title: '操作记录', }] as ILeftMenu[]; export const expertMenu = [{ diff --git a/kafka-manager-console/src/container/admin/cluster-detail/cluster-topic.tsx b/kafka-manager-console/src/container/admin/cluster-detail/cluster-topic.tsx index 7b7aaae7..c2d3aa54 100644 --- a/kafka-manager-console/src/container/admin/cluster-detail/cluster-topic.tsx +++ b/kafka-manager-console/src/container/admin/cluster-detail/cluster-topic.tsx @@ -172,7 +172,7 @@ export class ClusterTopic extends SearchAndFilterContainer { key: 'appName', // width: '10%', render: (val: string, record: IClusterTopics) => ( - + {val} ), diff --git a/kafka-manager-console/src/container/admin/cluster-detail/exclusive-cluster.tsx b/kafka-manager-console/src/container/admin/cluster-detail/exclusive-cluster.tsx index 6aaa2e78..efc28e68 100644 --- a/kafka-manager-console/src/container/admin/cluster-detail/exclusive-cluster.tsx +++ b/kafka-manager-console/src/container/admin/cluster-detail/exclusive-cluster.tsx @@ -314,8 +314,7 @@ export class ExclusiveCluster extends SearchAndFilterContainer { >
- 由于该Region已被逻辑集群【 {this.state.logicalClusterName} 】使用 - 请先解除Region与逻辑集群的关系 + 该Region已被逻辑集群【 {this.state.logicalClusterName} 】使用,请先解除Region与逻辑集群的关系
diff --git a/kafka-manager-console/src/container/admin/cluster-detail/index.less b/kafka-manager-console/src/container/admin/cluster-detail/index.less index 0dd4d106..9b5d5103 100644 --- a/kafka-manager-console/src/container/admin/cluster-detail/index.less +++ b/kafka-manager-console/src/container/admin/cluster-detail/index.less @@ -16,7 +16,7 @@ .traffic-table { margin: 10px 0; - min-height: 450px; + min-height: 330px; .traffic-header { width: 100%; height: 44px; diff --git a/kafka-manager-console/src/container/admin/cluster-list/index.tsx b/kafka-manager-console/src/container/admin/cluster-list/index.tsx index dfac45d7..be6956d6 100644 --- a/kafka-manager-console/src/container/admin/cluster-list/index.tsx +++ b/kafka-manager-console/src/container/admin/cluster-list/index.tsx @@ -4,6 +4,7 @@ import { wrapper } from 'store'; import { observer } from 'mobx-react'; import { IXFormWrapper, IMetaData, IRegister } from 'types/base-type'; import { admin } from 'store/admin'; +import { users } from 'store/users'; import { registerCluster, createCluster, pauseMonitoring } from 'lib/api'; import { SearchAndFilterContainer } from 'container/search-filter'; import { cluster } from 'store/cluster'; @@ -78,34 +79,34 @@ export class ClusterList extends SearchAndFilterContainer { disabled: item ? true : false, }, }, - { - key: 'idc', - label: '数据中心', - defaultValue: region.regionName, - rules: [{ required: true, message: '请输入数据中心' }], - attrs: { - placeholder: '请输入数据中心', - disabled: true, - }, - }, - { - key: 'mode', - label: '集群类型', - type: 'select', - options: cluster.clusterModes.map(ele => { - return { - label: ele.message, - value: ele.code, - }; - }), - rules: [{ - required: true, - message: '请选择集群类型', - }], - attrs: { - placeholder: '请选择集群类型', - }, - }, + // { + // key: 'idc', + // label: '数据中心', + // defaultValue: region.regionName, + // rules: [{ required: true, message: '请输入数据中心' }], + // attrs: { + // placeholder: '请输入数据中心', + // disabled: true, + // }, + // }, + // { + // key: 'mode', + // label: '集群类型', + // type: 'select', + // options: cluster.clusterModes.map(ele => { + // return { + // label: ele.message, + // value: ele.code, + // }; + // }), + // rules: [{ + // required: true, + // message: '请选择集群类型', + // }], + // attrs: { + // placeholder: '请选择集群类型', + // }, + // }, { key: 'kafkaVersion', label: 'kafka版本', @@ -148,7 +149,7 @@ export class ClusterList extends SearchAndFilterContainer { attrs: { placeholder: `请输入JMX认证,例如: { -"maxConn": 10, #KM对单台Broker对最大连接数 +"maxConn": 10, #KM对单台Broker的最大jmx连接数 "username": "xxxxx", #用户名 "password": "xxxxx", #密码 "openSSL": true, #开启SSL,true表示开启SSL,false表示关闭 @@ -276,32 +277,41 @@ export class ClusterList extends SearchAndFilterContainer { public getColumns = () => { const cols = getAdminClusterColumns(); + const role = users.currentUser.role; const col = { title: '操作', render: (value: string, item: IMetaData) => ( <> - 编辑 - - this.pauseMonitor(item)} - cancelText="取消" - okText="确认" - > - + { + role && role === 2 ? <> - {item.status === 1 ? '暂停监控' : '开始监控'} + >编辑 - - - - 删除 - + this.pauseMonitor(item)} + cancelText="取消" + okText="确认" + > + + + {item.status === 1 ? '暂停监控' : '开始监控'} + + + + + 删除 + + : + 编辑 + {item.status === 1 ? '暂停监控' : '开始监控'} + 删除 + + } ), }; @@ -310,6 +320,7 @@ export class ClusterList extends SearchAndFilterContainer { } public renderClusterList() { + const role = users.currentUser.role; return ( <>
@@ -318,7 +329,14 @@ export class ClusterList extends SearchAndFilterContainer { {this.renderSearch('', '请输入集群名称')}
  • 集群接入指南 - + { + role && role === 2 ? + + : + + + + }
  • diff --git a/kafka-manager-console/src/container/admin/config.tsx b/kafka-manager-console/src/container/admin/config.tsx index 09a70f83..1f9d6d81 100644 --- a/kafka-manager-console/src/container/admin/config.tsx +++ b/kafka-manager-console/src/container/admin/config.tsx @@ -28,14 +28,16 @@ export const getUserColumns = () => { showApplyModal(record)}>编辑 showApplyModalModifyPassword(record)}>修改密码 - users.deleteUser(record.username)} - cancelText="取消" - okText="确认" - > - 删除 - + {record.username == users.currentUser.username ? "" : + users.deleteUser(record.username)} + cancelText="取消" + okText="确认" + > + 删除 + + } ); }, }, diff --git a/kafka-manager-console/src/container/admin/index.tsx b/kafka-manager-console/src/container/admin/index.tsx index 8ae300f0..29c6200a 100644 --- a/kafka-manager-console/src/container/admin/index.tsx +++ b/kafka-manager-console/src/container/admin/index.tsx @@ -11,3 +11,5 @@ export * from './operation-management/migration-detail'; export * from './configure-management'; export * from './individual-bill'; export * from './bill-detail'; +export * from './operation-record'; + diff --git a/kafka-manager-console/src/container/admin/operation-record/config.tsx b/kafka-manager-console/src/container/admin/operation-record/config.tsx new file mode 100644 index 00000000..c298e4c2 --- /dev/null +++ b/kafka-manager-console/src/container/admin/operation-record/config.tsx @@ -0,0 +1,134 @@ +import * as React from 'react'; +import { cellStyle } from 'constants/table'; + +import { Tooltip } from 'antd'; +import { admin } from 'store/admin'; +import moment = require('moment'); + +const moduleList = [ + { moduleId: 0, moduleName: 'Topic' }, + { moduleId: 1, moduleName: '应用' }, + { moduleId: 2, moduleName: '配额' }, + { moduleId: 3, moduleName: '权限' }, + { moduleId: 4, moduleName: '集群' }, + { moduleId: 5, moduleName: '分区' }, + { moduleId: 6, moduleName: 'Gateway配置' }, +] + +export const operateList = { + 0: '新增', + 1: '删除', + 2: '修改' +} + + +// [ +// { operate: '新增', operateId: 0 }, +// { operate: '删除', operateId: 1 }, +// { operate: '修改', operateId: 2 }, +// ] + +export const getJarFuncForm: any = (props: any) => { + const formMap = [ + { + key: 'moduleId', + label: '模块', + type: 'select', + attrs: { + style: { + width: '130px' + }, + placeholder: '请选择模块', + }, + options: moduleList.map(item => { + return { + label: item.moduleName, + value: item.moduleId + } + }), + formAttrs: { + initialvalue: 0, + }, + }, + { + key: 'operator', + label: '操作人', + type: 'input', + attrs: { + style: { + width: '170px' + }, + placeholder: '请输入操作人' + }, + getvaluefromevent: (event: any) => { + return event.target.value.replace(/\s+/g, '') + }, + }, + // { + // key: 'resource', + // label: '资源名称', + // type: 'input', + // attrs: { + // style: { + // width: '170px' + // }, + // placeholder: '请输入资源名称' + // }, + // }, + // { + // key: 'content', + // label: '操作内容', + // type: 'input', + // attrs: { + // style: { + // width: '170px' + // }, + // placeholder: '请输入操作内容' + // }, + // }, + ] + return formMap; +} +export const getOperateColumns = () => { + + const columns: any = [ + { + title: '模块', + dataIndex: 'module', + key: 'module', + align: 'center', + width: '12%' + }, + { + title: '资源名称', + dataIndex: 'resource', + key: 'resource', + align: 'center', + width: '12%' + }, + { + title: '操作内容', + dataIndex: 'content', + key: 'content', + align: 'center', + width: '25%', + onCell: () => ({ + style: { + maxWidth: 350, + ...cellStyle, + }, + }), + render: (text: string, record: any) => { + return ( + {text}); + }, + }, + { + title: '操作人', + dataIndex: 'operator', + align: 'center', + width: '12%' + }, + ]; + return columns +} \ No newline at end of file diff --git a/kafka-manager-console/src/container/admin/operation-record/index.tsx b/kafka-manager-console/src/container/admin/operation-record/index.tsx new file mode 100644 index 00000000..2b18458c --- /dev/null +++ b/kafka-manager-console/src/container/admin/operation-record/index.tsx @@ -0,0 +1,130 @@ +import * as React from 'react'; +import { observer } from 'mobx-react'; +import { SearchAndFilterContainer } from 'container/search-filter'; +import { IXFormWrapper, IMetaData, IRegister } from 'types/base-type'; +import { admin } from 'store/admin'; +import { customPagination, cellStyle } from 'constants/table'; +import { Table, Tooltip } from 'component/antd'; +import { timeFormat } from 'constants/strategy'; +import { SearchFormComponent } from '../searchForm'; +import { getJarFuncForm, operateList, getOperateColumns } from './config' +import moment = require('moment'); +import { tableFilter } from 'lib/utils'; + +@observer +export class OperationRecord extends SearchAndFilterContainer { + public state: any = { + searchKey: '', + filteredInfo: null, + sortedInfo: null, + }; + + public getData(origin: T[]) { + let data: T[] = origin; + let { searchKey } = this.state; + searchKey = (searchKey + '').trim().toLowerCase(); + + data = searchKey ? origin.filter((item: IMetaData) => + (item.clusterName !== undefined && item.clusterName !== null) && item.clusterName.toLowerCase().includes(searchKey as string), + ) : origin; + return data; + }; + + public searchForm = (params: any) => { + // this.props.setFuncSubValue(params) + // getSystemFuncList(params).then(res => { + // this.props.setSysFuncList(res.data) + // this.props.setPagination(res.pagination) + // }) + const { operator, moduleId } = params || {} + operator ? admin.getOperationRecordData(params) : admin.getOperationRecordData({ moduleId }) + // getJarList(params).then(res => { + // this.props.setJarList(res.data) + // this.props.setPagination(res.pagination) + // }) + } + + public clearAll = () => { + this.setState({ + filteredInfo: null, + sortedInfo: null, + }); + }; + + public setHandleChange = (pagination: any, filters: any, sorter: any) => { + this.setState({ + filteredInfo: filters, + sortedInfo: sorter, + }); + } + + public renderOperationRecordList() { + let { sortedInfo, filteredInfo } = this.state; + sortedInfo = sortedInfo || {}; + filteredInfo = filteredInfo || {}; + const operatingTime = Object.assign({ + title: '操作时间', + dataIndex: 'modifyTime', + key: 'modifyTime', + align: 'center', + sorter: (a: any, b: any) => a.modifyTime - b.modifyTime, + render: (t: number) => moment(t).format(timeFormat), + width: '15%', + sortOrder: sortedInfo.columnKey === 'modifyTime' && sortedInfo.order, + }); + + const operatingPractice = Object.assign({ + title: '行为', + dataIndex: 'operate', + key: 'operate', + align: 'center', + width: '12%', + filters: tableFilter(this.getData(admin.oRList), 'operateId', operateList), + // filteredValue: filteredInfo.operate || null, + onFilter: (value: any, record: any) => { + return record.operateId === value + } + }, this.renderColumnsFilter('modifyTime')) + + const columns = getOperateColumns() + columns.splice(0, 0, operatingTime); + columns.splice(3, 0, operatingPractice); + return ( + <> +
    +
    + this.searchForm(params)} + clearAll={() => this.clearAll()} + isReset={true} + /> +
    +
    +
    + + + + ) + }; + + componentDidMount() { + admin.getOperationRecordData({ moduleId: 0 }); + } + + render() { + return
    + { + this.renderOperationRecordList() + } +
    + } +} \ No newline at end of file diff --git a/kafka-manager-console/src/container/admin/searchForm.tsx b/kafka-manager-console/src/container/admin/searchForm.tsx new file mode 100644 index 00000000..afbff03c --- /dev/null +++ b/kafka-manager-console/src/container/admin/searchForm.tsx @@ -0,0 +1,120 @@ +import * as React from 'react'; +import { Select, Input, InputNumber, Form, Switch, Checkbox, DatePicker, Radio, Upload, Button, Icon, Tooltip } from 'component/antd'; +// import './index.less'; +const Search = Input.Search; +export interface IFormItem { + key: string; + label: string; + type: string; + value?: string; + // 内部组件属性注入 + attrs?: any; + // form属性注入 + formAttrs?: any; + defaultValue?: string | number | any[]; + rules?: any[]; + invisible?: boolean; + getvaluefromevent: Function; +} + +interface SerachFormProps { + formMap: IFormItem[]; + // formData: any; + form: any; + onSubmit: Function; + isReset?: boolean; + clearAll: Function; + layout?: 'inline' | 'horizontal' | 'vertical'; +} + +export interface IFormSelect extends IFormItem { + options: Array<{ key?: string | number, value: string | number, label: string }>; +} + +class SearchForm extends React.Component{ + public onSubmit = () => { + // this.props.onSubmit() + // + } + + public renderFormItem(item: IFormItem) { + switch (item.type) { + default: + case 'input': + return ; + case 'select': + return ( + + ); + } + } + + public theQueryClick = (value: any) => { + this.props.onSubmit(value) + this.props.clearAll() + // this.props.form.resetFields() + } + public resetClick = () => { + this.props.form.resetFields() + this.props.clearAll() + this.theQueryClick(this.props.form.getFieldsValue()) + } + + public render() { + const { form, formMap, isReset } = this.props; + const { getFieldDecorator, getFieldsValue } = form; + return ( +
    + { + formMap.map(formItem => { + // const { initialValue, valuePropName } = this.handleFormItem(formItem, formData); + // const getFieldValue = { + // initialValue, + // rules: formItem.rules || [{ required: false, message: '' }], + // valuePropName, + // }; + return ( + + {getFieldDecorator(formItem.key, { + initialValue: formItem.formAttrs?.initialvalue, + getValueFromEvent: formItem?.getvaluefromevent, + })( + this.renderFormItem(formItem), + )} + + ); + }) + } + + { + isReset && + } + + + + ); + } +} +export const SearchFormComponent = Form.create({ name: 'search-form' })(SearchForm); \ No newline at end of file diff --git a/kafka-manager-console/src/container/alarm/add-alarm/filter-form.tsx b/kafka-manager-console/src/container/alarm/add-alarm/filter-form.tsx index 3e5dd0b7..fe74e66f 100644 --- a/kafka-manager-console/src/container/alarm/add-alarm/filter-form.tsx +++ b/kafka-manager-console/src/container/alarm/add-alarm/filter-form.tsx @@ -149,9 +149,9 @@ export class DynamicSetFilter extends React.Component { public handleSelectChange = (e: string, type: 'topic' | 'consumerGroup' | 'location') => { switch (type) { case 'topic': - if (!this.clusterId) { - return message.info('请选择集群'); - } + // if (!this.clusterId) { + // return message.info('请选择集群'); + // } this.topicName = e; const type = this.dealMonitorType(); if (['kafka-consumer-maxLag', 'kafka-consumer-maxDelayTime', 'kafka-consumer-lag'].indexOf(type) > -1) { diff --git a/kafka-manager-console/src/container/app/app-list.tsx b/kafka-manager-console/src/container/app/app-list.tsx index ef897246..d49b1048 100644 --- a/kafka-manager-console/src/container/app/app-list.tsx +++ b/kafka-manager-console/src/container/app/app-list.tsx @@ -52,8 +52,7 @@ export class CommonAppList extends SearchAndFilterContainer { }, }), render: (text: string, record: IAppItem) => { - return ( - {text}); + return ({text}); }, }, { @@ -103,7 +102,7 @@ export class CommonAppList extends SearchAndFilterContainer { } public getOnlineConnect(record: IAppItem) { - modal.showOfflineAppModal(record.appId); + modal.showOfflineAppNewModal(record.appId); } public getData(origin: T[]) { @@ -114,7 +113,7 @@ export class CommonAppList extends SearchAndFilterContainer { data = searchKey ? origin.filter((item: IAppItem) => ((item.name !== undefined && item.name !== null) && item.name.toLowerCase().includes(searchKey as string)) || ((item.principals !== undefined && item.principals !== null) && item.principals.toLowerCase().includes(searchKey as string)) || - ((item.appId !== undefined && item.appId !== null) && item.appId.toLowerCase().includes(searchKey as string)) ) : origin; + ((item.appId !== undefined && item.appId !== null) && item.appId.toLowerCase().includes(searchKey as string))) : origin; return data; } diff --git a/kafka-manager-console/src/container/cluster/my-cluster.tsx b/kafka-manager-console/src/container/cluster/my-cluster.tsx index e017b0dd..3cb6115f 100644 --- a/kafka-manager-console/src/container/cluster/my-cluster.tsx +++ b/kafka-manager-console/src/container/cluster/my-cluster.tsx @@ -29,16 +29,16 @@ export class MyCluster extends SearchAndFilterContainer { public applyCluster() { const xFormModal = { formMap: [ - { - key: 'idc', - label: '数据中心', - defaultValue: region.regionName, - rules: [{ required: true, message: '请输入数据中心' }], - attrs: { - placeholder: '请输入数据中心', - disabled: true, - }, - }, + // { + // key: 'idc', + // label: '数据中心', + // defaultValue: region.regionName, + // rules: [{ required: true, message: '请输入数据中心' }], + // attrs: { + // placeholder: '请输入数据中心', + // disabled: true, + // }, + // }, { key: 'appId', label: '所属应用', diff --git a/kafka-manager-console/src/container/expert/topic-governance/index.tsx b/kafka-manager-console/src/container/expert/topic-governance/index.tsx index 21bd9b10..b495e2f8 100644 --- a/kafka-manager-console/src/container/expert/topic-governance/index.tsx +++ b/kafka-manager-console/src/container/expert/topic-governance/index.tsx @@ -133,15 +133,15 @@ export class GovernanceTopic extends SearchAndFilterContainer { width: '30%', sorter: (a: IResource, b: IResource) => a.topicName.charCodeAt(0) - b.topicName.charCodeAt(0), render: (text: string, item: IResource) => - ( - - - {text} - - ), + ( + + + {text} + + ), }, { title: '所在集群', @@ -215,7 +215,7 @@ export class GovernanceTopic extends SearchAndFilterContainer { return ( <> - {this.pendingTopic(this.getData(expert.resourceData))} + {this.pendingTopic(this.getData(expert.resourceData))} ); } diff --git a/kafka-manager-console/src/container/header/index.less b/kafka-manager-console/src/container/header/index.less index 98aefd99..53301a92 100644 --- a/kafka-manager-console/src/container/header/index.less +++ b/kafka-manager-console/src/container/header/index.less @@ -16,6 +16,14 @@ line-height: 64px; vertical-align: middle; } + .kafka-header-version{ + display: inline-block; + vertical-align: middle; + padding-top:5px; + font-size: 12px; + margin-left:10px; + color:#a0a0a0; + } } .mid-content { diff --git a/kafka-manager-console/src/container/header/index.tsx b/kafka-manager-console/src/container/header/index.tsx index e86bcf11..ebda9760 100644 --- a/kafka-manager-console/src/container/header/index.tsx +++ b/kafka-manager-console/src/container/header/index.tsx @@ -145,6 +145,8 @@ export const Header = observer((props: IHeader) => {
    Kafka Manager + v2.4.0 + {/* 添加版本超链接 */}
    {headerMenu.map((item: IMenuItem, index: number) => diff --git a/kafka-manager-console/src/container/modal/admin/cluster.ts b/kafka-manager-console/src/container/modal/admin/cluster.ts index 20ed9098..ac4af3a5 100644 --- a/kafka-manager-console/src/container/modal/admin/cluster.ts +++ b/kafka-manager-console/src/container/modal/admin/cluster.ts @@ -22,11 +22,11 @@ export const showEditClusterTopic = (item: IClusterTopics) => { }, { key: 'appId', - label: '应用ID', + label: '应用名称', type: 'select', options: app.adminAppData.map(item => { return { - label: item.appId, + label: item.name, value: item.appId, }; }), @@ -61,7 +61,7 @@ export const showEditClusterTopic = (item: IClusterTopics) => { attrs: { placeholder: '请输入保存时间', suffix: '小时', - prompttype:'修改保存时间,预计一分钟左右生效!' + prompttype: '修改保存时间,预计一分钟左右生效!' }, }, { diff --git a/kafka-manager-console/src/container/modal/admin/confirm-detail-topic.tsx b/kafka-manager-console/src/container/modal/admin/confirm-detail-topic.tsx index 41f6ed61..83d1b02d 100644 --- a/kafka-manager-console/src/container/modal/admin/confirm-detail-topic.tsx +++ b/kafka-manager-console/src/container/modal/admin/confirm-detail-topic.tsx @@ -35,7 +35,6 @@ class CustomForm extends React.Component { this.props.form.validateFields((err: any, values: any) => { const deleteData = this.props.formData; if (!err) { - // console.log('values', values); if (values.topicName !== this.props.formData.topicName) { notification.error({ message: 'topic名称不正确,请重新输入' }); } else { @@ -77,7 +76,6 @@ class CustomForm extends React.Component { } public render() { - // console.log('props', this.props); const { formData = {} as any, visible } = this.props; const { getFieldDecorator } = this.props.form; let metadata = [] as IBrokersMetadata[]; diff --git a/kafka-manager-console/src/container/modal/admin/expand-partition.tsx b/kafka-manager-console/src/container/modal/admin/expand-partition.tsx index dfb51ba9..44001081 100644 --- a/kafka-manager-console/src/container/modal/admin/expand-partition.tsx +++ b/kafka-manager-console/src/container/modal/admin/expand-partition.tsx @@ -111,11 +111,11 @@ class CustomForm extends React.Component { })()} - {/* */} + {/* */} {/* this.onSwitchChange(checked)} /> */} { this.onSwitchChange(e.target.value === 'region' ? true : false); }}> Region类型 - Borker类型 + Broker类型 diff --git a/kafka-manager-console/src/container/modal/admin/task.ts b/kafka-manager-console/src/container/modal/admin/task.ts index d9a609ac..12a46d53 100644 --- a/kafka-manager-console/src/container/modal/admin/task.ts +++ b/kafka-manager-console/src/container/modal/admin/task.ts @@ -28,8 +28,8 @@ const updateInputModal = (status?: string) => { formMap[4].invisible = status === 'region'; formMap[5].invisible = status !== 'region'; - formMap[4].rules = [{required: status !== 'region'}]; - formMap[5].rules = [{required: status === 'region'}]; + formMap[4].rules = [{ required: status !== 'region' }]; + formMap[5].rules = [{ required: status === 'region' }]; // tslint:disable-next-line:no-unused-expression wrapper.ref && wrapper.ref.updateFormMap$(formMap, wrapper.xFormWrapper.formData); }; @@ -103,7 +103,7 @@ export const createMigrationTasks = () => { label: 'Region', value: 'region', }, { - label: 'Borker', + label: 'Broker', value: 'broker', }], rules: [{ @@ -141,7 +141,7 @@ export const createMigrationTasks = () => { placeholder: '请选择目标Region', }, }, - + { key: 'beginTime', label: '计划开始时间', diff --git a/kafka-manager-console/src/container/modal/offline-app-modal-new.tsx b/kafka-manager-console/src/container/modal/offline-app-modal-new.tsx new file mode 100644 index 00000000..2b582f77 --- /dev/null +++ b/kafka-manager-console/src/container/modal/offline-app-modal-new.tsx @@ -0,0 +1,78 @@ +import * as React from 'react'; +import { Table, Modal, Tooltip, Icon, message, notification, Alert, Button } from 'component/antd'; +import { app } from 'store/app'; +import { getApplyOnlineColumns } from 'container/topic/config'; +import { observer } from 'mobx-react'; +import { modal } from 'store/modal'; +import { users } from 'store/users'; +import { urlPrefix } from 'constants/left-menu'; +import { region } from 'store'; + +@observer +export class ConnectAppNewList extends React.Component { + + public componentDidMount() { + app.getAppsConnections(modal.params); + } + + public handleCancel = () => { + app.setAppsConnections([]); + modal.close(); + } + + public handleSubmit = () => { + const connectionList = app.appsConnections; + if (connectionList && connectionList.length) { + return message.warning('存在连接信息,无法申请下线!'); + } + const offlineParams = { + type: 11, + applicant: users.currentUser.username, + description: '', + extensions: JSON.stringify({ appId: modal.params }), + }; + app.applyAppOffline(offlineParams).then((data: any) => { + notification.success({ message: '申请下线成功' }); + window.location.href = `${urlPrefix}/user/order-detail/?orderId=${data.id}®ion=${region.currentRegion}`; + }); + modal.close(); + } + + public render() { + const connectionList = app.appsConnections; + return ( + <> + 确定 + : + <> + + + + } + width={500} + > +
    + { + connectionList && connectionList.length + ? + 该应用已与Topic关联,请先解除应用与Topic之间的关系。点击查看 + : + 应用下线后,AppID、密钥将会失效,请谨慎操作! + } +
    +
    + + ); + } +} diff --git a/kafka-manager-console/src/container/modal/order.tsx b/kafka-manager-console/src/container/modal/order.tsx index c982db4c..4daec7c9 100644 --- a/kafka-manager-console/src/container/modal/order.tsx +++ b/kafka-manager-console/src/container/modal/order.tsx @@ -4,13 +4,14 @@ import { message, Icon, notification, Modal, Table, Tooltip } from 'component/an import { IApprovalOrder, IBaseOrder, IOrderInfo } from 'types/base-type'; import { admin } from 'store/admin'; import { modal } from 'store/modal'; +import { cluster } from 'store/cluster'; import { cellStyle } from 'constants/table'; import * as React from 'react'; const updateInputModal = (status: string, type: number) => { const formMap = wrapper.xFormWrapper.formMap; - const region = type === 0 ? 5 : 3; - const broker = type === 0 ? 6 : 4; + const region = type === 0 ? 6 : 3; + const broker = type === 0 ? 7 : 4; formMap[region].invisible = status === 'region'; formMap[broker].invisible = status !== 'region'; @@ -37,6 +38,12 @@ const renderModalTilte = (type: number, status: number) => { export const showApprovalModal = (info: IOrderInfo, status: number, from?: string) => { const { id, type } = info; const formMap = [{ + key: 'clusterId', + label: '所属集群', + type: 'input_number', + defaultValue: info.detail.logicalClusterName, + attrs: { disabled: true }, + }, { key: 'partitionNum', label: '分区数', type: 'input_number', @@ -87,7 +94,7 @@ export const showApprovalModal = (info: IOrderInfo, status: number, from?: strin label: 'Region', value: 'region', }, { - label: 'Borker', + label: 'Broker', value: 'broker', }], rules: [{ required: false, message: '请选择类型' }], diff --git a/kafka-manager-console/src/container/modal/topic.tsx b/kafka-manager-console/src/container/modal/topic.tsx index d4df0318..4e026641 100644 --- a/kafka-manager-console/src/container/modal/topic.tsx +++ b/kafka-manager-console/src/container/modal/topic.tsx @@ -399,8 +399,8 @@ export const updateAllTopicFormModal = () => { const formMap = wrapper.xFormWrapper.formMap; if (topic.authorities) { const { consume, send, checkStatus } = judgeAccessStatus(topic.authorities.access); - formMap[3].defaultValue = checkStatus; - formMap[3].options = [{ + formMap[2].defaultValue = checkStatus; + formMap[2].options = [{ label: `消费权限${consume ? '(已拥有)' : ''}`, value: '1', disabled: consume, @@ -409,7 +409,7 @@ export const updateAllTopicFormModal = () => { value: '2', disabled: send, }]; - formMap[3].rules = [{ + formMap[2].rules = [{ required: true, validator: (rule: any, value: any, callback: any) => getPowerValidator(rule, value, callback, checkStatus, 'allTopic'), }]; @@ -476,7 +476,6 @@ export const showAllPermissionModal = (item: ITopic) => { const showAllPermission = (appId: string, item: ITopic, access: number) => { const { consume, send, checkStatus } = judgeAccessStatus(access); - const xFormModal = { formMap: [ { @@ -489,16 +488,6 @@ const showAllPermission = (appId: string, item: ITopic, access: number) => { disabled: true, }, }, - { - key: 'clusterName', - label: '集群名称', - defaultValue: item.clusterName, - rules: [{ required: true, message: '请输入集群名称' }], - attrs: { - placeholder: '请输入集群名称', - disabled: true, - }, - }, { key: 'appId', label: '绑定应用', @@ -526,6 +515,26 @@ const showAllPermission = (appId: string, item: ITopic, access: number) => { validator: (rule: any, value: any, callback: any) => getPowerValidator(rule, value, callback, checkStatus, 'allTopic'), }], }, + // { + // key: 'clusterName', + // label: '集群名称', + // defaultValue: item.clusterName, + // rules: [{ required: true, message: '请输入集群名称' }], + // attrs: { + // placeholder: '请输入集群名称', + // disabled: true, + // }, + // }, + // { + // key: 'clusterName', + // label: '集群名称', + // defaultValue: item.clusterName, + // rules: [{ required: true, message: '请输入集群名称' }], + // attrs: { + // placeholder: '请输入集群名称', + // disabled: true, + // }, + // }, { key: 'description', label: '申请原因', @@ -587,16 +596,16 @@ export const showPermissionModal = (item: ITopic) => { disabled: true, }, }, - { - key: 'clusterName', - label: '集群名称', - defaultValue: item.clusterName, - rules: [{ required: true, message: '请输入集群名称' }], - attrs: { - placeholder: '请输入集群名称', - disabled: true, - }, - }, + // { + // key: 'clusterName', + // label: '集群名称', + // defaultValue: item.clusterName, + // rules: [{ required: true, message: '请输入集群名称' }], + // attrs: { + // placeholder: '请输入集群名称', + // disabled: true, + // }, + // }, { key: 'appName', label: '绑定应用', diff --git a/kafka-manager-console/src/container/search-filter.tsx b/kafka-manager-console/src/container/search-filter.tsx index ac5d6bc1..f6ed09fa 100644 --- a/kafka-manager-console/src/container/search-filter.tsx +++ b/kafka-manager-console/src/container/search-filter.tsx @@ -126,7 +126,7 @@ export class SearchAndFilterContainer extends React.Component @@ -194,7 +194,7 @@ export class SearchAndFilterContainer extends React.Component { + public renderColumnsFilter = (type: string, params?: any) => { return { filterIcon: this.renderFilterIcon.bind(null, type), filterDropdownVisible: this.state[type] as boolean, diff --git a/kafka-manager-console/src/container/staff-select.tsx b/kafka-manager-console/src/container/staff-select.tsx index e9072569..f01637e9 100644 --- a/kafka-manager-console/src/container/staff-select.tsx +++ b/kafka-manager-console/src/container/staff-select.tsx @@ -28,7 +28,8 @@ export class StaffSelect extends React.Component { public getStaffList = () => { const { value } = this.props; const current = users.currentUser.username || getCookie('username'); - const principals = value || (current ? [current] : []); + const principals = ['']; + // const principals = value || (current ? [current] : []); const promises: any[] = []; for (const item of principals) { @@ -64,7 +65,6 @@ export class StaffSelect extends React.Component { const { value, isDisabled } = this.props; const current = users.currentUser.username || getCookie('username'); const principals = value || (current ? [current] : []); - return ( + diff --git a/kafka-manager-extends/kafka-manager-account/src/main/java/com/xiaojukeji/kafka/manager/account/impl/LoginServiceImpl.java b/kafka-manager-extends/kafka-manager-account/src/main/java/com/xiaojukeji/kafka/manager/account/impl/LoginServiceImpl.java index 61719b4f..7a803603 100644 --- a/kafka-manager-extends/kafka-manager-account/src/main/java/com/xiaojukeji/kafka/manager/account/impl/LoginServiceImpl.java +++ b/kafka-manager-extends/kafka-manager-account/src/main/java/com/xiaojukeji/kafka/manager/account/impl/LoginServiceImpl.java @@ -67,11 +67,14 @@ public class LoginServiceImpl implements LoginService { if (ValidateUtils.isNull(classRequestMappingValue)) { LOGGER.error("class=LoginServiceImpl||method=checkLogin||msg=uri illegal||uri={}", request.getRequestURI()); singleSignOn.setRedirectToLoginPage(response); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return false; } if (classRequestMappingValue.equals(ApiPrefix.API_V1_SSO_PREFIX) || classRequestMappingValue.equals(ApiPrefix.API_V1_THIRD_PART_PREFIX) + || classRequestMappingValue.equals(ApiPrefix.API_V1_THIRD_PART_OP_PREFIX) + || classRequestMappingValue.equals(ApiPrefix.API_V1_THIRD_PART_NORMAL_PREFIX) || classRequestMappingValue.equals(ApiPrefix.GATEWAY_API_V1_PREFIX)) { // 白名单接口直接true return true; @@ -81,6 +84,7 @@ public class LoginServiceImpl implements LoginService { if (ValidateUtils.isBlank(username)) { // 未登录, 则返回false, 同时重定向到登录页面 singleSignOn.setRedirectToLoginPage(response); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } @@ -111,4 +115,4 @@ public class LoginServiceImpl implements LoginService { } return true; } -} \ No newline at end of file +} diff --git a/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/OrderApplyNotifyService.java b/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/OrderApplyNotifyService.java index 35caf21f..c5756217 100644 --- a/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/OrderApplyNotifyService.java +++ b/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/OrderApplyNotifyService.java @@ -1,14 +1,7 @@ package com.xiaojukeji.kafka.manager.notify; -import com.xiaojukeji.kafka.manager.common.entity.ao.account.Account; -import com.xiaojukeji.kafka.manager.common.entity.pojo.OrderDO; import com.xiaojukeji.kafka.manager.common.events.OrderApplyEvent; -import com.xiaojukeji.kafka.manager.notify.common.NotifyConstant; -import com.xiaojukeji.kafka.manager.notify.notifyer.AbstractNotifyService; -import com.xiaojukeji.kafka.manager.notify.common.OrderNotifyTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -19,27 +12,10 @@ import org.springframework.stereotype.Service; */ @Service("orderApplyNotifyService") public class OrderApplyNotifyService implements ApplicationListener { - @Autowired - private AbstractNotifyService notifyService; - - @Value("${notify.order.detail-url}") - private String orderDetailUrl; @Async @Override public void onApplicationEvent(OrderApplyEvent orderApplyEvent) { - OrderDO orderDO = orderApplyEvent.getOrderDO(); - String detailUrl = String.format(orderDetailUrl, orderDO.getId(), orderApplyEvent.getIdc()); - for (Account account : NotifyConstant.accountList) { - notifyService.sendMsg(account.getUsername(), - OrderNotifyTemplate.getNotify2OrderHandlerMessage( - account.getChineseName(), - orderDO.getApplicant(), - orderDO.getTitle(), - detailUrl - ) - ); - } - + // todo 工单通知 } } \ No newline at end of file diff --git a/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/common/NotifyConstant.java b/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/common/NotifyConstant.java deleted file mode 100644 index da4e2737..00000000 --- a/kafka-manager-extends/kafka-manager-notify/src/main/java/com/xiaojukeji/kafka/manager/notify/common/NotifyConstant.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.xiaojukeji.kafka.manager.notify.common; - -import com.xiaojukeji.kafka.manager.common.bizenum.AccountRoleEnum; -import com.xiaojukeji.kafka.manager.common.entity.ao.account.Account; - -import java.util.Arrays; -import java.util.List; - -/** - * @author zengqiao - * @date 20/8/27 - */ -public class NotifyConstant { - - public static final List accountList = Arrays.asList( - new Account("xuzhengxi", "徐正熙", "", AccountRoleEnum.OP) - ); -} \ No newline at end of file diff --git a/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/component/AbstractScheduledTask.java b/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/component/AbstractScheduledTask.java index b0700975..7eddb926 100644 --- a/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/component/AbstractScheduledTask.java +++ b/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/component/AbstractScheduledTask.java @@ -148,10 +148,12 @@ public abstract class AbstractScheduledTask implements Sch } Collections.sort(allTaskList); - List hostList = heartbeatDao.selectActiveHosts( - new Date(now - ScheduledTaskConstant.HEARTBEAT_TIME) - ); + List hostList = heartbeatDao.selectActiveHosts(new Date(now - ScheduledTaskConstant.HEARTBEAT_TIME)); if (ValidateUtils.isEmptyList(hostList)) { + // 当前无机器注册,导致周期任务(Topic指标存DB等任务)不可被触发执行。 + // 大概率原因可能是:DB的时区不对,注册的时间错误导致查询不出来。 + // 如果是单台方式部署的Logi-KM,那么也可能是服务新上线,或者是服务不正常导致的。 + LOGGER.error("customScheduled task running, but without registrant, and so scheduled tasks can't execute, scheduledName:{}.", scheduledName); return Lists.newArrayList(); } @@ -163,8 +165,10 @@ public abstract class AbstractScheduledTask implements Sch idx++; } if (idx == hostList.size()) { - // 当前机器未注册 - LOGGER.error("customScheduled task running, registers not conclude, scheduledName:{}.", scheduledName); + // 当前机器未注册, 原因可能是: + // 1、当前服务新上线,确实暂未注册到DB中。 + // 2、当前服务异常,比如进行FGC等,导致注册任务停止了。 + LOGGER.warn("customScheduled task running, registrants not conclude present machine, scheduledName:{}.", scheduledName); return Lists.newArrayList(); } diff --git a/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutoHandleTopicOrder.java b/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutoHandleTopicOrder.java index 00b9d379..46158b60 100644 --- a/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutoHandleTopicOrder.java +++ b/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutoHandleTopicOrder.java @@ -1,6 +1,5 @@ package com.xiaojukeji.kafka.manager.task.dispatch.op; -import com.alibaba.fastjson.JSON; import com.xiaojukeji.kafka.manager.bpm.OrderService; import com.xiaojukeji.kafka.manager.bpm.common.OrderStatusEnum; import com.xiaojukeji.kafka.manager.bpm.common.OrderTypeEnum; @@ -11,6 +10,7 @@ import com.xiaojukeji.kafka.manager.common.constant.TopicCreationConstant; import com.xiaojukeji.kafka.manager.common.entity.ResultStatus; import com.xiaojukeji.kafka.manager.common.entity.ao.config.CreateTopicElemConfig; import com.xiaojukeji.kafka.manager.bpm.common.entry.apply.OrderExtensionApplyTopicDTO; +import com.xiaojukeji.kafka.manager.common.utils.JsonUtils; import com.xiaojukeji.kafka.manager.common.utils.ListUtils; import com.xiaojukeji.kafka.manager.common.utils.ValidateUtils; import com.xiaojukeji.kafka.manager.common.entity.pojo.*; @@ -23,6 +23,7 @@ import com.xiaojukeji.kafka.manager.task.component.EmptyEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.util.Arrays; @@ -35,6 +36,7 @@ import java.util.Properties; */ @Component @CustomScheduled(name = "autoHandleTopicOrder", cron = "0 0/1 * * * ?", threadNum = 1) +@ConditionalOnProperty(prefix = "task.op.order-auto-exec", name = "topic-enabled", havingValue = "true", matchIfMissing = false) public class AutoHandleTopicOrder extends AbstractScheduledTask { private static final Logger LOGGER = LoggerFactory.getLogger(LogConstant.SCHEDULED_TASK_LOGGER); @@ -72,11 +74,8 @@ public class AutoHandleTopicOrder extends AbstractScheduledTask { Integer maxPassedOrderNumPerTask = configService.getAutoPassedTopicApplyOrderNumPerTask(); for (OrderDO orderDO: doList) { - if (!OrderTypeEnum.APPLY_TOPIC.getCode().equals(orderDO.getType())) { - continue; - } try { - if (!handleApplyTopicOrder(orderDO)) { + if (!OrderTypeEnum.APPLY_TOPIC.getCode().equals(orderDO.getType()) && !handleApplyTopicOrder(orderDO)) { continue; } maxPassedOrderNumPerTask -= 1; @@ -91,7 +90,7 @@ public class AutoHandleTopicOrder extends AbstractScheduledTask { } private boolean handleApplyTopicOrder(OrderDO orderDO) { - OrderExtensionApplyTopicDTO dto = JSON.parseObject(orderDO.getExtensions(), OrderExtensionApplyTopicDTO.class); + OrderExtensionApplyTopicDTO dto = JsonUtils.stringToObj(orderDO.getExtensions(), OrderExtensionApplyTopicDTO.class); Long physicalClusterId = logicalClusterMetadataManager.getPhysicalClusterId(dto.getClusterId(), dto.isPhysicalClusterId()); diff --git a/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutomatedHandleOrder.java b/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutomatedHandleOrder.java index 5491dd85..e9cb1cb1 100644 --- a/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutomatedHandleOrder.java +++ b/kafka-manager-task/src/main/java/com/xiaojukeji/kafka/manager/task/dispatch/op/AutomatedHandleOrder.java @@ -20,6 +20,7 @@ import com.xiaojukeji.kafka.manager.task.component.EmptyEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.util.*; @@ -31,6 +32,7 @@ import java.util.*; */ @Component @CustomScheduled(name = "automatedHandleOrder", cron = "0 0/1 * * * ?", threadNum = 1) +@ConditionalOnProperty(prefix = "task.op.order-auto-exec", name = "app-enabled", havingValue = "true", matchIfMissing = false) public class AutomatedHandleOrder extends AbstractScheduledTask { private static final Logger LOGGER = LoggerFactory.getLogger(LogConstant.SCHEDULED_TASK_LOGGER); @@ -51,6 +53,7 @@ public class AutomatedHandleOrder extends AbstractScheduledTask { public void processTask(EmptyEntry entryEntry) { List waitDealOrderList = orderService.getWaitDealOrder(); if (ValidateUtils.isEmptyList(waitDealOrderList)) { + LOGGER.info("class=AutomatedHandleOrder||method=processTask||msg=waiting deal order is empty"); return; } @@ -65,17 +68,18 @@ public class AutomatedHandleOrder extends AbstractScheduledTask { } private void handleAppApplyOrder(List waitDealOrderList, List passedOrderList) { - LOGGER.info("start handle app apply order."); + LOGGER.info("class=AutomatedHandleOrder||method=processTask||msg=start handle app apply order"); if (ValidateUtils.isEmptyList(waitDealOrderList)) { return; } + Integer maxNum = Constant.HANDLE_APP_APPLY_MAX_NUM_DEFAULT; ConfigDO configDO = configService.getByKey(Constant.HANDLE_APP_APPLY_MAX_NUM); if (!ValidateUtils.isNull(configDO)) { try { maxNum = Integer.parseInt(configDO.getConfigValue()); } catch (Exception e) { - LOGGER.error("", e); + LOGGER.error("class=AutomatedHandleOrder||method=processTask||configDO={}||msg=config value illegal", configDO, e); } } int handleNum = Math.min(maxNum - passedOrderList.size(), waitDealOrderList.size()); @@ -97,7 +101,7 @@ public class AutomatedHandleOrder extends AbstractScheduledTask { applyAppOrder.updateOrder(orderDO, baseDTO, Constant.AUTO_HANDLE_USER_NAME); } } catch (Exception e) { - LOGGER.error("", e); + LOGGER.error("class=AutomatedHandleOrder||method=processTask||orderDO={}||msg=auto handle app order failed", orderDO, e); } } } diff --git a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/normal/NormalTopicController.java b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/normal/NormalTopicController.java index 86755eca..aaac290f 100644 --- a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/normal/NormalTopicController.java +++ b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/normal/NormalTopicController.java @@ -11,11 +11,13 @@ import com.xiaojukeji.kafka.manager.common.entity.metrics.BaseMetrics; import com.xiaojukeji.kafka.manager.common.entity.vo.common.RealTimeMetricsVO; import com.xiaojukeji.kafka.manager.common.entity.vo.normal.TopicBusinessInfoVO; import com.xiaojukeji.kafka.manager.common.entity.vo.normal.topic.*; +import com.xiaojukeji.kafka.manager.common.utils.DateUtils; import com.xiaojukeji.kafka.manager.common.utils.SpringTool; import com.xiaojukeji.kafka.manager.common.utils.ValidateUtils; import com.xiaojukeji.kafka.manager.common.entity.pojo.ClusterDO; import com.xiaojukeji.kafka.manager.common.entity.pojo.KafkaBillDO; import com.xiaojukeji.kafka.manager.common.utils.jmx.JmxAttributeEnum; +import com.xiaojukeji.kafka.manager.common.entity.vo.normal.topic.TopicStatisticMetricsVO; import com.xiaojukeji.kafka.manager.service.cache.LogicalClusterMetadataManager; import com.xiaojukeji.kafka.manager.service.cache.PhysicalClusterMetadataManager; import com.xiaojukeji.kafka.manager.service.service.*; @@ -339,4 +341,23 @@ public class NormalTopicController { ); } + @ApiOperation(value = "Topic流量统计信息", notes = "") + @RequestMapping(value = "{clusterId}/topics/{topicName}/statistic-metrics", method = RequestMethod.GET) + @ResponseBody + public Result getTopicStatisticMetrics(@PathVariable Long clusterId, + @PathVariable String topicName, + @RequestParam(value = "isPhysicalClusterId", required = false) Boolean isPhysicalClusterId, + @RequestParam("latest-day") Integer latestDay) { + Long physicalClusterId = logicalClusterMetadataManager.getPhysicalClusterId(clusterId, isPhysicalClusterId); + if (ValidateUtils.isNull(physicalClusterId)) { + return Result.buildFrom(ResultStatus.CLUSTER_NOT_EXIST); + } + + Double maxAvgBytesIn = topicManagerService.getTopicMaxAvgBytesIn(physicalClusterId, topicName, new Date(DateUtils.getDayStarTime(-1 * latestDay)), new Date(), 1); + if (ValidateUtils.isNull(maxAvgBytesIn)) { + return Result.buildFrom(ResultStatus.MYSQL_ERROR); + } + return new Result<>(new TopicStatisticMetricsVO(maxAvgBytesIn)); + } + } \ No newline at end of file diff --git a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/rd/RdOperateRecordController.java b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/rd/RdOperateRecordController.java index 68068f97..f600aab5 100644 --- a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/rd/RdOperateRecordController.java +++ b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/rd/RdOperateRecordController.java @@ -36,7 +36,7 @@ public class RdOperateRecordController { if (ValidateUtils.isNull(dto) || !dto.legal()) { return Result.buildFrom(ResultStatus.PARAM_ILLEGAL); } - List voList = OperateRecordModelConverter.convert2OperateRecordVOList(operateRecordService.queryByCondt(dto)); + List voList = OperateRecordModelConverter.convert2OperateRecordVOList(operateRecordService.queryByCondition(dto)); if (voList.size() > MAX_RECORD_COUNT) { voList = voList.subList(0, MAX_RECORD_COUNT); } diff --git a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartBrokerController.java b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartBrokerController.java index e324be01..790b85be 100644 --- a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartBrokerController.java +++ b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartBrokerController.java @@ -32,7 +32,7 @@ import java.util.stream.Collectors; */ @Api(tags = "开放接口-Broker相关接口(REST)") @RestController -@RequestMapping(ApiPrefix.API_V1_THIRD_PART_PREFIX) +@RequestMapping(ApiPrefix.API_V1_THIRD_PART_OP_PREFIX) public class ThirdPartBrokerController { @Autowired private BrokerService brokerService; diff --git a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartOpController.java b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartOpUtilController.java similarity index 96% rename from kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartOpController.java rename to kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartOpUtilController.java index 3d31a5f0..b0d8ffd6 100644 --- a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartOpController.java +++ b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartOpUtilController.java @@ -21,8 +21,8 @@ import org.springframework.web.bind.annotation.*; */ @Api(tags = "开放接口-OP相关接口(REST)") @RestController -@RequestMapping(ApiPrefix.API_V1_THIRD_PART_PREFIX) -public class ThirdPartOpController { +@RequestMapping(ApiPrefix.API_V1_THIRD_PART_OP_PREFIX) +public class ThirdPartOpUtilController { @Autowired private AdminService adminService; diff --git a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartTopicController.java b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartTopicController.java index 4d029fb6..b247cdb8 100644 --- a/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartTopicController.java +++ b/kafka-manager-web/src/main/java/com/xiaojukeji/kafka/manager/web/api/versionone/thirdpart/ThirdPartTopicController.java @@ -13,8 +13,6 @@ import com.xiaojukeji.kafka.manager.common.entity.vo.normal.topic.TopicAuthorize import com.xiaojukeji.kafka.manager.common.entity.vo.normal.topic.TopicRequestTimeDetailVO; import com.xiaojukeji.kafka.manager.common.zookeeper.znode.brokers.TopicMetadata; import com.xiaojukeji.kafka.manager.openapi.common.vo.TopicOffsetChangedVO; -import com.xiaojukeji.kafka.manager.openapi.common.vo.TopicStatisticMetricsVO; -import com.xiaojukeji.kafka.manager.common.utils.DateUtils; import com.xiaojukeji.kafka.manager.common.utils.ValidateUtils; import com.xiaojukeji.kafka.manager.common.entity.pojo.ClusterDO; import com.xiaojukeji.kafka.manager.service.cache.PhysicalClusterMetadataManager; @@ -30,7 +28,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import java.util.Date; import java.util.List; /** @@ -69,27 +66,6 @@ public class ThirdPartTopicController { return new Result<>(vo); } - @ApiOperation(value = "Topic流量统计信息", notes = "") - @RequestMapping(value = "{physicalClusterId}/topics/{topicName}/statistic-metrics", method = RequestMethod.GET) - @ResponseBody - public Result getTopicStatisticMetrics(@PathVariable Long physicalClusterId, - @PathVariable String topicName, - @RequestParam("latest-day") Integer latestDay) { - try { - return new Result<>(new TopicStatisticMetricsVO(topicManagerService.getTopicMaxAvgBytesIn( - physicalClusterId, - topicName, - new Date(DateUtils.getDayStarTime(-1 * latestDay)), - new Date(), - 1 - ))); - } catch (Exception e) { - LOGGER.error("get topic statistic metrics failed, clusterId:{} topicName:{} latestDay:{}." - , physicalClusterId, topicName, latestDay, e); - } - return Result.buildFrom(ResultStatus.MYSQL_ERROR); - } - @ApiOperation(value = "Topic是否有流量", notes = "") @RequestMapping(value = "{physicalClusterId}/topics/{topicName}/offset-changed", method = RequestMethod.GET) @ResponseBody diff --git a/kafka-manager-web/src/main/resources/application.yml b/kafka-manager-web/src/main/resources/application.yml index 58ad509f..12241f5c 100644 --- a/kafka-manager-web/src/main/resources/application.yml +++ b/kafka-manager-web/src/main/resources/application.yml @@ -11,9 +11,9 @@ spring: name: kafkamanager datasource: kafka-manager: - jdbc-url: jdbc:mysql://127.0.0.1:3306/logi_kafka_manager?characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 - username: admin - password: admin + jdbc-url: jdbc:mysql://localhost:3306/logi_kafka_manager?characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 + username: root + password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver main: allow-bean-definition-overriding: true @@ -46,6 +46,9 @@ custom: task: op: sync-topic-enabled: false # 未落盘的Topic定期同步到DB中 + order-auto-exec: # 工单自动化审批线程的开关 + topic-enabled: false # Topic工单自动化审批开关, false:关闭自动化审批, true:开启 + app-enabled: false # App工单自动化审批开关, false:关闭自动化审批, true:开启 account: ldap: diff --git a/pom.xml b/pom.xml index 66d78b2b..9d4a5d30 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ - 2.3.1-SNAPSHOT + 2.4.0-SNAPSHOT 2.7.0 1.5.13 @@ -203,7 +203,7 @@ org.eclipse.jetty jetty-util - 9.2.24.v20180105 + 9.4.39.v20210325 @@ -215,7 +215,7 @@ commons-beanutils commons-beanutils - 1.9.3 + 1.9.4