mirror of
https://github.com/apache/rocketmq-dashboard.git
synced 2025-09-11 03:49:06 +08:00
Compare commits
8 Commits
a4e02f472f
...
rocketmq-d
Author | SHA1 | Date | |
---|---|---|---|
|
a013c8fad1 | ||
|
cd262da8b1 | ||
|
37dbd7f327 | ||
|
79556420f5 | ||
|
9cb185afc1 | ||
|
f60103af9b | ||
|
9c2a069976 | ||
|
8cc7d6a727 |
2
NOTICE
2
NOTICE
@@ -1,5 +1,5 @@
|
|||||||
Apache RocketMQ
|
Apache RocketMQ
|
||||||
Copyright 2016-2022 The Apache Software Foundation
|
Copyright 2016-2025 The Apache Software Foundation
|
||||||
|
|
||||||
This product includes software developed at
|
This product includes software developed at
|
||||||
The Apache Software Foundation (http://www.apache.org/).
|
The Apache Software Foundation (http://www.apache.org/).
|
||||||
|
@@ -9,7 +9,7 @@ In the project directory, you can run:
|
|||||||
### `npm run start`
|
### `npm run start`
|
||||||
|
|
||||||
Runs the app in the development mode.\
|
Runs the app in the development mode.\
|
||||||
Open [http://localhost:3003](http://localhost:3000) to view it in your browser.
|
Open [http://localhost:3003](http://localhost:3003) to view it in your browser.
|
||||||
|
|
||||||
The page will reload when you make changes.\
|
The page will reload when you make changes.\
|
||||||
You may also see any lint errors in the console.
|
You may also see any lint errors in the console.
|
||||||
|
34
frontend-new/package-lock.json
generated
34
frontend-new/package-lock.json
generated
@@ -19,11 +19,11 @@
|
|||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"framer-motion": "^12.16.0",
|
"framer-motion": "^12.16.0",
|
||||||
"http-proxy-middleware": "^3.0.5",
|
"http-proxy-middleware": "^3.0.5",
|
||||||
"i18next": "^25.1.3",
|
"i18next": "^23.2.3",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-i18next": "^15.5.1",
|
"react-i18next": "14.1.3",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^7.6.0",
|
"react-router-dom": "^7.6.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
@@ -8918,9 +8918,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/i18next": {
|
"node_modules/i18next": {
|
||||||
"version": "25.1.3",
|
"version": "23.16.8",
|
||||||
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.1.3.tgz",
|
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-23.16.8.tgz",
|
||||||
"integrity": "sha512-VY1iKox3YWPRTNMHFdgk5TV+Jq6rNKexLCLpPmP5oXXJ5Kl7yDBi3ycZ5fyEKZ1tNBW5gOqD4WV0XqE7rl3JUg==",
|
"integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -8936,15 +8936,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.27.1"
|
"@babel/runtime": "^7.23.2"
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
@@ -14000,17 +13992,16 @@
|
|||||||
"integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ=="
|
"integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ=="
|
||||||
},
|
},
|
||||||
"node_modules/react-i18next": {
|
"node_modules/react-i18next": {
|
||||||
"version": "15.5.1",
|
"version": "14.1.3",
|
||||||
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.5.1.tgz",
|
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-14.1.3.tgz",
|
||||||
"integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==",
|
"integrity": "sha512-wZnpfunU6UIAiJ+bxwOiTmBOAaB14ha97MjOEnLGac2RJ+h/maIYXZuTHlmyqQVX1UVHmU1YDTQ5vxLmwfXTjw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.23.9",
|
||||||
"html-parse-stringify": "^3.0.1"
|
"html-parse-stringify": "^3.0.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"i18next": ">= 23.2.3",
|
"i18next": ">= 23.2.3",
|
||||||
"react": ">= 16.8.0",
|
"react": ">= 16.8.0"
|
||||||
"typescript": "^5"
|
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
@@ -14018,9 +14009,6 @@
|
|||||||
},
|
},
|
||||||
"react-native": {
|
"react-native": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -14,11 +14,11 @@
|
|||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"framer-motion": "^12.16.0",
|
"framer-motion": "^12.16.0",
|
||||||
"http-proxy-middleware": "^3.0.5",
|
"http-proxy-middleware": "^3.0.5",
|
||||||
"i18next": "^25.1.3",
|
"i18next": "^23.2.3",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-i18next": "^15.5.1",
|
"react-i18next": "14.1.3",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^7.6.0",
|
"react-router-dom": "^7.6.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
@@ -316,7 +316,7 @@ const remoteApi = {
|
|||||||
*/
|
*/
|
||||||
queryMessageByTopicAndKey: async (topic, key) => {
|
queryMessageByTopicAndKey: async (topic, key) => {
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/message/queryMessageByTopicAndKey.query?topic=${topic}&key=${key}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/message/queryMessageByTopicAndKey.query?topic=${encodeURIComponent(topic)}&key=${key}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -355,6 +355,7 @@ const remoteApi = {
|
|||||||
*/
|
*/
|
||||||
resendMessageDirectly: async (msgId, consumerGroup, topic) => {
|
resendMessageDirectly: async (msgId, consumerGroup, topic) => {
|
||||||
topic = encodeURIComponent(topic)
|
topic = encodeURIComponent(topic)
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/message/consumeMessageDirectly.do?msgId=${msgId}&consumerGroup=${consumerGroup}&topic=${topic}`), {
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/message/consumeMessageDirectly.do?msgId=${msgId}&consumerGroup=${consumerGroup}&topic=${topic}`), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -392,6 +393,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refreshConsumerGroup: async (consumerGroup) => {
|
refreshConsumerGroup: async (consumerGroup) => {
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/group.refresh?consumerGroup=${consumerGroup}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/group.refresh?consumerGroup=${consumerGroup}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -443,6 +445,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
fetchBrokerNameList: async (consumerGroup) => {
|
fetchBrokerNameList: async (consumerGroup) => {
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/fetchBrokerNameList.query?consumerGroup=${consumerGroup}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/fetchBrokerNameList.query?consumerGroup=${consumerGroup}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -454,6 +457,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
deleteConsumerGroup: async (groupName, brokerNameList) => {
|
deleteConsumerGroup: async (groupName, brokerNameList) => {
|
||||||
|
groupName = encodeURIComponent(groupName)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl("/consumer/deleteSubGroup.do"), {
|
const response = await remoteApi._fetch(remoteApi.buildUrl("/consumer/deleteSubGroup.do"), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -471,6 +475,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
queryConsumerConfig: async (consumerGroup) => {
|
queryConsumerConfig: async (consumerGroup) => {
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/examineSubscriptionGroupConfig.query?consumerGroup=${consumerGroup}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/examineSubscriptionGroupConfig.query?consumerGroup=${consumerGroup}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -499,6 +504,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
queryTopicByConsumer: async (consumerGroup, address) => {
|
queryTopicByConsumer: async (consumerGroup, address) => {
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/queryTopicByConsumer.query?consumerGroup=${consumerGroup}&address=${address}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/queryTopicByConsumer.query?consumerGroup=${consumerGroup}&address=${address}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -510,6 +516,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
queryConsumerConnection: async (consumerGroup, address) => {
|
queryConsumerConnection: async (consumerGroup, address) => {
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/consumerConnection.query?consumerGroup=${consumerGroup}&address=${address}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/consumerConnection.query?consumerGroup=${consumerGroup}&address=${address}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -521,6 +528,7 @@ const remoteApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
queryConsumerRunningInfo: async (consumerGroup, clientId, jstack = false) => {
|
queryConsumerRunningInfo: async (consumerGroup, clientId, jstack = false) => {
|
||||||
|
consumerGroup = encodeURIComponent(consumerGroup)
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/consumerRunningInfo.query?consumerGroup=${consumerGroup}&clientId=${clientId}&jstack=${jstack}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/consumer/consumerRunningInfo.query?consumerGroup=${consumerGroup}&clientId=${clientId}&jstack=${jstack}`));
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -559,7 +567,7 @@ const remoteApi = {
|
|||||||
|
|
||||||
getTopicStats: async (topic) => {
|
getTopicStats: async (topic) => {
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/stats.query?topic=${topic}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/stats.query?topic=${encodeURIComponent(topic)}`));
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching topic stats:", error);
|
console.error("Error fetching topic stats:", error);
|
||||||
@@ -569,7 +577,7 @@ const remoteApi = {
|
|||||||
|
|
||||||
getTopicRoute: async (topic) => {
|
getTopicRoute: async (topic) => {
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/route.query?topic=${topic}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/route.query?topic=${encodeURIComponent(topic)}`));
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching topic route:", error);
|
console.error("Error fetching topic route:", error);
|
||||||
@@ -579,7 +587,7 @@ const remoteApi = {
|
|||||||
|
|
||||||
getTopicConsumers: async (topic) => {
|
getTopicConsumers: async (topic) => {
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/queryConsumerByTopic.query?topic=${topic}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/queryConsumerByTopic.query?topic=${encodeURIComponent(topic)}`));
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching topic consumers:", error);
|
console.error("Error fetching topic consumers:", error);
|
||||||
@@ -589,7 +597,7 @@ const remoteApi = {
|
|||||||
|
|
||||||
getTopicConsumerGroups: async (topic) => {
|
getTopicConsumerGroups: async (topic) => {
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/queryTopicConsumerInfo.query?topic=${topic}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/queryTopicConsumerInfo.query?topic=${encodeURIComponent(topic)}`));
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching consumer groups:", error);
|
console.error("Error fetching consumer groups:", error);
|
||||||
@@ -599,7 +607,7 @@ const remoteApi = {
|
|||||||
|
|
||||||
getTopicConfig: async (topic) => {
|
getTopicConfig: async (topic) => {
|
||||||
try {
|
try {
|
||||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/examineTopicConfig.query?topic=${topic}`));
|
const response = await remoteApi._fetch(remoteApi.buildUrl(`/topic/examineTopicConfig.query?topic=${encodeURIComponent(topic)}`));
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching topic config:", error);
|
console.error("Error fetching topic config:", error);
|
||||||
|
@@ -21,7 +21,7 @@ import {remoteApi} from '../../api/remoteApi/remoteApi';
|
|||||||
import {useLanguage} from '../../i18n/LanguageContext';
|
import {useLanguage} from '../../i18n/LanguageContext';
|
||||||
|
|
||||||
|
|
||||||
const ClientInfoModal = ({visible, group, address, onCancel}) => {
|
const ClientInfoModal = ({visible, group, address, onCancel, messageApi}) => {
|
||||||
const {t} = useLanguage();
|
const {t} = useLanguage();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [connectionData, setConnectionData] = useState(null);
|
const [connectionData, setConnectionData] = useState(null);
|
||||||
@@ -34,7 +34,11 @@ const ClientInfoModal = ({visible, group, address, onCancel}) => {
|
|||||||
try {
|
try {
|
||||||
const connResponse = await remoteApi.queryConsumerConnection(group, address);
|
const connResponse = await remoteApi.queryConsumerConnection(group, address);
|
||||||
|
|
||||||
if (connResponse.status === 0) setConnectionData(connResponse.data);
|
if (connResponse.status === 0) {
|
||||||
|
setConnectionData(connResponse.data);
|
||||||
|
}else{
|
||||||
|
messageApi.error(connResponse.errMsg);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ import {Modal, Spin, Table} from 'antd';
|
|||||||
import {remoteApi} from '../../api/remoteApi/remoteApi';
|
import {remoteApi} from '../../api/remoteApi/remoteApi';
|
||||||
import {useLanguage} from '../../i18n/LanguageContext';
|
import {useLanguage} from '../../i18n/LanguageContext';
|
||||||
|
|
||||||
const ConsumerDetailModal = ({visible, group, address, onCancel}) => {
|
const ConsumerDetailModal = ({visible, group, address, onCancel ,messageApi}) => {
|
||||||
const {t} = useLanguage();
|
const {t} = useLanguage();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [details, setDetails] = useState([]);
|
const [details, setDetails] = useState([]);
|
||||||
@@ -34,6 +34,10 @@ const ConsumerDetailModal = ({visible, group, address, onCancel}) => {
|
|||||||
const response = await remoteApi.queryTopicByConsumer(group, address);
|
const response = await remoteApi.queryTopicByConsumer(group, address);
|
||||||
if (response.status === 0) {
|
if (response.status === 0) {
|
||||||
setDetails(response.data);
|
setDetails(response.data);
|
||||||
|
}else {
|
||||||
|
// Handle error case
|
||||||
|
messageApi.error(response.errMsg);
|
||||||
|
setDetails([]);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@@ -18,15 +18,12 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {Button, Checkbox, Modal, notification, Spin} from 'antd';
|
import {Button, Checkbox, Modal, notification, Spin} from 'antd';
|
||||||
import {remoteApi} from '../../api/remoteApi/remoteApi';
|
import {remoteApi} from '../../api/remoteApi/remoteApi';
|
||||||
import {useLanguage} from '../../i18n/LanguageContext';
|
|
||||||
|
|
||||||
const DeleteConsumerModal = ({visible, group, onCancel, onSuccess}) => {
|
const DeleteConsumerModal = ({visible, group, onCancel, onSuccess, t}) => {
|
||||||
const {t} = useLanguage();
|
|
||||||
const [brokerList, setBrokerList] = useState([]);
|
const [brokerList, setBrokerList] = useState([]);
|
||||||
const [selectedBrokers, setSelectedBrokers] = useState([]);
|
const [selectedBrokers, setSelectedBrokers] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
// 获取Broker列表
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchBrokers = async () => {
|
const fetchBrokers = async () => {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
@@ -45,7 +42,6 @@ const DeleteConsumerModal = ({visible, group, onCancel, onSuccess}) => {
|
|||||||
fetchBrokers();
|
fetchBrokers();
|
||||||
}, [visible, group]);
|
}, [visible, group]);
|
||||||
|
|
||||||
// 处理删除提交
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
if (selectedBrokers.length === 0) {
|
if (selectedBrokers.length === 0) {
|
||||||
notification.warning({message: t.PLEASE_SELECT_BROKER});
|
notification.warning({message: t.PLEASE_SELECT_BROKER});
|
||||||
|
@@ -592,9 +592,10 @@ export const translations = {
|
|||||||
"EXPRESSION_TYPE": "Expression Type",
|
"EXPRESSION_TYPE": "Expression Type",
|
||||||
"SUB_VERSION": "Sub Version",
|
"SUB_VERSION": "Sub Version",
|
||||||
"CODE_SET": "Code Set",
|
"CODE_SET": "Code Set",
|
||||||
"TAGS_SET": "Tags Set"
|
"TAGS_SET": "Tags Set",
|
||||||
|
"DELETE_CONSUMER_GROUP": "Delete Consumer Group",
|
||||||
|
"SELECT_DELETE_BROKERS": "Please select brokers to delete consumer group",
|
||||||
|
"CONFIRM_DELETE": "Confirm Delete",
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -288,7 +288,6 @@ const ConsumerGroupList = () => {
|
|||||||
setShowConfig(true);
|
setShowConfig(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 修改操作按钮的点击处理函数
|
|
||||||
const handleClient = (group, address) => {
|
const handleClient = (group, address) => {
|
||||||
setSelectedGroup(group);
|
setSelectedGroup(group);
|
||||||
setSelectedAddress(address);
|
setSelectedAddress(address);
|
||||||
@@ -550,12 +549,12 @@ const ConsumerGroupList = () => {
|
|||||||
/>
|
/>
|
||||||
</Spin>
|
</Spin>
|
||||||
|
|
||||||
{/* 模态框组件保持不变 */}
|
|
||||||
<ClientInfoModal
|
<ClientInfoModal
|
||||||
visible={showClientInfo}
|
visible={showClientInfo}
|
||||||
group={selectedGroup}
|
group={selectedGroup}
|
||||||
address={selectedAddress}
|
address={selectedAddress}
|
||||||
onCancel={() => setShowClientInfo(false)}
|
onCancel={() => setShowClientInfo(false)}
|
||||||
|
messageApi={messageApi}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConsumerDetailModal
|
<ConsumerDetailModal
|
||||||
@@ -563,6 +562,7 @@ const ConsumerGroupList = () => {
|
|||||||
group={selectedGroup}
|
group={selectedGroup}
|
||||||
address={selectedAddress}
|
address={selectedAddress}
|
||||||
onCancel={() => setShowConsumeDetail(false)}
|
onCancel={() => setShowConsumeDetail(false)}
|
||||||
|
messageApi={messageApi}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConsumerConfigModal
|
<ConsumerConfigModal
|
||||||
@@ -579,6 +579,7 @@ const ConsumerGroupList = () => {
|
|||||||
group={selectedGroup}
|
group={selectedGroup}
|
||||||
onCancel={() => setShowDeleteModal(false)}
|
onCancel={() => setShowDeleteModal(false)}
|
||||||
onSuccess={loadConsumerGroups}
|
onSuccess={loadConsumerGroups}
|
||||||
|
t={t}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
12
pom.xml
12
pom.xml
@@ -16,8 +16,7 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache</groupId>
|
<groupId>org.apache</groupId>
|
||||||
@@ -29,14 +28,14 @@
|
|||||||
<groupId>org.apache.rocketmq</groupId>
|
<groupId>org.apache.rocketmq</groupId>
|
||||||
<artifactId>rocketmq-dashboard</artifactId>
|
<artifactId>rocketmq-dashboard</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>2.0.1-SNAPSHOT</version>
|
<version>2.1.0</version>
|
||||||
<name>rocketmq-dashboard</name>
|
<name>rocketmq-dashboard</name>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<url>git@github.com:apache/rocketmq-dashboard.git</url>
|
<url>git@github.com:apache/rocketmq-dashboard.git</url>
|
||||||
<connection>scm:git:git@github.com:apache/rocketmq-dashboard.git</connection>
|
<connection>scm:git:git@github.com:apache/rocketmq-dashboard.git</connection>
|
||||||
<developerConnection>scm:git:git@github.com:apache/rocketmq-dashboard.git</developerConnection>
|
<developerConnection>scm:git:git@github.com:apache/rocketmq-dashboard.git</developerConnection>
|
||||||
<tag>1.0.0</tag>
|
<tag>rocketmq-dashboard-2.1.0</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<mailingLists>
|
<mailingLists>
|
||||||
@@ -250,6 +249,7 @@
|
|||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
@@ -448,7 +448,7 @@
|
|||||||
<goal>npm</goal>
|
<goal>npm</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<arguments>install --legacy-peer-deps</arguments>
|
<arguments>install</arguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -470,7 +470,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<target>
|
<target>
|
||||||
<copy todir="${project.build.directory}/classes/public">
|
<copy todir="${project.build.directory}/classes/public">
|
||||||
<fileset dir="${project.basedir}/frontend-new/build"/>
|
<fileset dir="${project.basedir}/frontend-new/build" />
|
||||||
</copy>
|
</copy>
|
||||||
</target>
|
</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@@ -80,7 +80,7 @@ public class MQAdminAspect {
|
|||||||
String methodName = joinPoint.getSignature().getName();
|
String methodName = joinPoint.getSignature().getName();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isPoolConfigIsolatedByUser(rmqConfigure.isLoginRequired(), methodName)) {
|
if (isPoolConfigIsolatedByUser(rmqConfigure.isLoginRequired(), rmqConfigure.getAuthMode(), methodName)) {
|
||||||
currentUserInfo = (UserInfo) UserInfoContext.get(WebUtil.USER_NAME);
|
currentUserInfo = (UserInfo) UserInfoContext.get(WebUtil.USER_NAME);
|
||||||
// 2. Borrow the user-specific MQAdminExt instance.
|
// 2. Borrow the user-specific MQAdminExt instance.
|
||||||
// currentUser.getName() is assumed to be the AccessKey, and currentUser.getPassword() is SecretKey.
|
// currentUser.getName() is assumed to be the AccessKey, and currentUser.getPassword() is SecretKey.
|
||||||
@@ -123,8 +123,8 @@ public class MQAdminAspect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPoolConfigIsolatedByUser(boolean loginRequired, String methodName) {
|
private boolean isPoolConfigIsolatedByUser(boolean loginRequired, String authMode, String methodName) {
|
||||||
if (!loginRequired) {
|
if (!loginRequired || authMode.equals("file")) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return !METHODS_TO_CHECK.contains(methodName);
|
return !METHODS_TO_CHECK.contains(methodName);
|
||||||
|
@@ -283,6 +283,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TopicConsumerInfo> queryConsumeStatsListByGroupName(String groupName, String address) {
|
public List<TopicConsumerInfo> queryConsumeStatsListByGroupName(String groupName, String address) {
|
||||||
|
groupName = getConsumerGroup(groupName);
|
||||||
List<ConsumeStats> consumeStatses = new ArrayList<>();
|
List<ConsumeStats> consumeStatses = new ArrayList<>();
|
||||||
String topic = null;
|
String topic = null;
|
||||||
try {
|
try {
|
||||||
@@ -295,9 +296,10 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
List<TopicConsumerInfo> res = new ArrayList<>();
|
List<TopicConsumerInfo> res = new ArrayList<>();
|
||||||
|
String finalGroupName = groupName;
|
||||||
consumeStatses.forEach(consumeStats -> {
|
consumeStatses.forEach(consumeStats -> {
|
||||||
if (consumeStats != null && consumeStats.getOffsetTable() != null && !consumeStats.getOffsetTable().isEmpty()) {
|
if (consumeStats != null && consumeStats.getOffsetTable() != null && !consumeStats.getOffsetTable().isEmpty()) {
|
||||||
res.addAll(toTopicConsumerInfoList(topic, consumeStats, groupName));
|
res.addAll(toTopicConsumerInfoList(topic, consumeStats, finalGroupName));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
@@ -305,6 +307,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TopicConsumerInfo> queryConsumeStatsList(final String topic, String groupName) {
|
public List<TopicConsumerInfo> queryConsumeStatsList(final String topic, String groupName) {
|
||||||
|
groupName = getConsumerGroup(groupName);
|
||||||
ConsumeStats consumeStats = null;
|
ConsumeStats consumeStats = null;
|
||||||
try {
|
try {
|
||||||
consumeStats = mqAdminExt.examineConsumeStats(groupName, topic);
|
consumeStats = mqAdminExt.examineConsumeStats(groupName, topic);
|
||||||
@@ -316,6 +319,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<TopicConsumerInfo> toTopicConsumerInfoList(String topic, ConsumeStats consumeStats, String groupName) {
|
private List<TopicConsumerInfo> toTopicConsumerInfoList(String topic, ConsumeStats consumeStats, String groupName) {
|
||||||
|
groupName = getConsumerGroup(groupName);
|
||||||
List<MessageQueue> mqList = Lists.newArrayList(Iterables.filter(consumeStats.getOffsetTable().keySet(), new Predicate<MessageQueue>() {
|
List<MessageQueue> mqList = Lists.newArrayList(Iterables.filter(consumeStats.getOffsetTable().keySet(), new Predicate<MessageQueue>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(MessageQueue o) {
|
public boolean apply(MessageQueue o) {
|
||||||
@@ -339,6 +343,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<MessageQueue, String> getClientConnection(String groupName) {
|
private Map<MessageQueue, String> getClientConnection(String groupName) {
|
||||||
|
groupName = getConsumerGroup(groupName);
|
||||||
Map<MessageQueue, String> results = Maps.newHashMap();
|
Map<MessageQueue, String> results = Maps.newHashMap();
|
||||||
try {
|
try {
|
||||||
ConsumerConnection consumerConnection = mqAdminExt.examineConsumerConnectionInfo(groupName);
|
ConsumerConnection consumerConnection = mqAdminExt.examineConsumerConnectionInfo(groupName);
|
||||||
@@ -417,7 +422,8 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ConsumerConfigInfo> examineSubscriptionGroupConfig(String group) {
|
public List<ConsumerConfigInfo> examineSubscriptionGroupConfig(String consumerGroup) {
|
||||||
|
consumerGroup = getConsumerGroup(consumerGroup);
|
||||||
List<ConsumerConfigInfo> consumerConfigInfoList = Lists.newArrayList();
|
List<ConsumerConfigInfo> consumerConfigInfoList = Lists.newArrayList();
|
||||||
try {
|
try {
|
||||||
ClusterInfo clusterInfo = clusterInfoService.get();
|
ClusterInfo clusterInfo = clusterInfoService.get();
|
||||||
@@ -425,9 +431,9 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
String brokerAddress = clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr();
|
String brokerAddress = clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr();
|
||||||
SubscriptionGroupConfig subscriptionGroupConfig = null;
|
SubscriptionGroupConfig subscriptionGroupConfig = null;
|
||||||
try {
|
try {
|
||||||
subscriptionGroupConfig = mqAdminExt.examineSubscriptionGroupConfig(brokerAddress, group);
|
subscriptionGroupConfig = mqAdminExt.examineSubscriptionGroupConfig(brokerAddress, consumerGroup);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("op=examineSubscriptionGroupConfig_error brokerName={} group={}", brokerName, group);
|
logger.warn("op=examineSubscriptionGroupConfig_error brokerName={} group={}", brokerName, consumerGroup);
|
||||||
}
|
}
|
||||||
if (subscriptionGroupConfig == null) {
|
if (subscriptionGroupConfig == null) {
|
||||||
continue;
|
continue;
|
||||||
@@ -480,6 +486,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean createAndUpdateSubscriptionGroupConfig(ConsumerConfigInfo consumerConfigInfo) {
|
public boolean createAndUpdateSubscriptionGroupConfig(ConsumerConfigInfo consumerConfigInfo) {
|
||||||
|
consumerConfigInfo.getSubscriptionGroupConfig().setGroupName(getConsumerGroup(consumerConfigInfo.getSubscriptionGroupConfig().getGroupName()));
|
||||||
try {
|
try {
|
||||||
ClusterInfo clusterInfo = clusterInfoService.get();
|
ClusterInfo clusterInfo = clusterInfoService.get();
|
||||||
for (String brokerName : changeToBrokerNameSet(clusterInfo.getClusterAddrTable(),
|
for (String brokerName : changeToBrokerNameSet(clusterInfo.getClusterAddrTable(),
|
||||||
@@ -495,6 +502,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> fetchBrokerNameSetBySubscriptionGroup(String group) {
|
public Set<String> fetchBrokerNameSetBySubscriptionGroup(String group) {
|
||||||
|
group = getConsumerGroup(group);
|
||||||
Set<String> brokerNameSet = Sets.newHashSet();
|
Set<String> brokerNameSet = Sets.newHashSet();
|
||||||
try {
|
try {
|
||||||
List<ConsumerConfigInfo> consumerConfigInfoList = examineSubscriptionGroupConfig(group);
|
List<ConsumerConfigInfo> consumerConfigInfoList = examineSubscriptionGroupConfig(group);
|
||||||
@@ -511,6 +519,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsumerConnection getConsumerConnection(String consumerGroup, String address) {
|
public ConsumerConnection getConsumerConnection(String consumerGroup, String address) {
|
||||||
|
consumerGroup = getConsumerGroup(consumerGroup);
|
||||||
try {
|
try {
|
||||||
String[] addresses = address.split(",");
|
String[] addresses = address.split(",");
|
||||||
String addr = addresses[0];
|
String addr = addresses[0];
|
||||||
@@ -523,6 +532,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack) {
|
public ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack) {
|
||||||
|
consumerGroup = getConsumerGroup(consumerGroup);
|
||||||
try {
|
try {
|
||||||
return mqAdminExt.getConsumerRunningInfo(consumerGroup, clientId, jstack);
|
return mqAdminExt.getConsumerRunningInfo(consumerGroup, clientId, jstack);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -533,7 +543,6 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GroupConsumeInfo refreshGroup(String address, String consumerGroup) {
|
public GroupConsumeInfo refreshGroup(String address, String consumerGroup) {
|
||||||
|
|
||||||
if (isCacheBeingBuilt || cacheConsumeInfoList.isEmpty()) {
|
if (isCacheBeingBuilt || cacheConsumeInfoList.isEmpty()) {
|
||||||
throw new RuntimeException("Cache is being built or empty, please try again later");
|
throw new RuntimeException("Cache is being built or empty, please try again later");
|
||||||
}
|
}
|
||||||
@@ -541,7 +550,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
for (int i = 0; i < cacheConsumeInfoList.size(); i++) {
|
for (int i = 0; i < cacheConsumeInfoList.size(); i++) {
|
||||||
GroupConsumeInfo groupConsumeInfo = cacheConsumeInfoList.get(i);
|
GroupConsumeInfo groupConsumeInfo = cacheConsumeInfoList.get(i);
|
||||||
if (groupConsumeInfo.getGroup().equals(consumerGroup)) {
|
if (groupConsumeInfo.getGroup().equals(consumerGroup)) {
|
||||||
GroupConsumeInfo updatedInfo = queryGroup(consumerGroup, "");
|
GroupConsumeInfo updatedInfo = queryGroup(consumerGroup, address);
|
||||||
updatedInfo.setUpdateTime(new Date());
|
updatedInfo.setUpdateTime(new Date());
|
||||||
updatedInfo.setGroup(consumerGroup);
|
updatedInfo.setGroup(consumerGroup);
|
||||||
updatedInfo.setAddress(consumerGroupMap.get(consumerGroup));
|
updatedInfo.setAddress(consumerGroupMap.get(consumerGroup));
|
||||||
@@ -559,4 +568,11 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
|
|||||||
consumerGroupMap.clear();
|
consumerGroupMap.clear();
|
||||||
return queryGroupList(false, address);
|
return queryGroupList(false, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getConsumerGroup(String consumerGroup) {
|
||||||
|
if (consumerGroup != null && consumerGroup.startsWith("%SYS%")) {
|
||||||
|
return consumerGroup.substring(5); // Remove "%SYS%" prefix
|
||||||
|
}
|
||||||
|
return consumerGroup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,11 +21,9 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import org.apache.rocketmq.client.QueryResult;
|
import org.apache.rocketmq.client.QueryResult;
|
||||||
import org.apache.rocketmq.client.exception.MQBrokerException;
|
import org.apache.rocketmq.client.exception.MQBrokerException;
|
||||||
import org.apache.rocketmq.client.impl.MQAdminImpl;
|
|
||||||
import org.apache.rocketmq.client.impl.MQClientAPIImpl;
|
import org.apache.rocketmq.client.impl.MQClientAPIImpl;
|
||||||
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
|
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
|
||||||
import org.apache.rocketmq.common.TopicConfig;
|
import org.apache.rocketmq.common.TopicConfig;
|
||||||
import org.apache.rocketmq.common.message.Message;
|
|
||||||
import org.apache.rocketmq.common.message.MessageExt;
|
import org.apache.rocketmq.common.message.MessageExt;
|
||||||
import org.apache.rocketmq.common.message.MessageQueue;
|
import org.apache.rocketmq.common.message.MessageQueue;
|
||||||
import org.apache.rocketmq.dashboard.service.client.MQAdminExtImpl;
|
import org.apache.rocketmq.dashboard.service.client.MQAdminExtImpl;
|
||||||
@@ -589,26 +587,6 @@ public class MQAdminExtImplTest {
|
|||||||
Assert.assertNotNull(result);
|
Assert.assertNotNull(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStart() {
|
|
||||||
assertNotNull(mqAdminExtImpl);
|
|
||||||
try {
|
|
||||||
mqAdminExtImpl.start();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Assert.assertTrue(e instanceof IllegalStateException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testShutdown() {
|
|
||||||
assertNotNull(mqAdminExtImpl);
|
|
||||||
try {
|
|
||||||
mqAdminExtImpl.shutdown();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Assert.assertTrue(e instanceof IllegalStateException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQueryConsumeTimeSpan() throws Exception {
|
public void testQueryConsumeTimeSpan() throws Exception {
|
||||||
assertNotNull(mqAdminExtImpl);
|
assertNotNull(mqAdminExtImpl);
|
||||||
@@ -659,7 +637,7 @@ public class MQAdminExtImplTest {
|
|||||||
{
|
{
|
||||||
when(defaultMQAdminExt.viewBrokerStatsData(anyString(), anyString(), anyString())).thenReturn(new BrokerStatsData());
|
when(defaultMQAdminExt.viewBrokerStatsData(anyString(), anyString(), anyString())).thenReturn(new BrokerStatsData());
|
||||||
}
|
}
|
||||||
BrokerStatsData brokerStatsData = mqAdminExtImpl.viewBrokerStatsData(brokerAddr, BrokerStatsManager.TOPIC_PUT_NUMS, "topic_test");
|
BrokerStatsData brokerStatsData = mqAdminExtImpl.viewBrokerStatsData(brokerAddr, BrokerStatsManager.BROKER_ACK_NUMS, "topic_test");
|
||||||
Assert.assertNotNull(brokerStatsData);
|
Assert.assertNotNull(brokerStatsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user