From 5b10d06367a79614f8aa2327b6a33a6be45200fe Mon Sep 17 00:00:00 2001 From: yangon <2689991790@qq.com> Date: Wed, 20 Mar 2024 15:13:48 +0800 Subject: [PATCH] fix:Filter monitored parameters (#255) * fix:Filter monitored parameters * fix:Filter out the failed cluster --- ui/src/components/MonitorComp/LineGraph.tsx | 12 ++-- ui/src/components/MonitorComp/index.tsx | 16 +++-- .../Cluster/Detail/Overview/ZoneTable.tsx | 18 +++-- .../pages/Cluster/Detail/Overview/helper.ts | 25 +++---- .../pages/Cluster/Detail/Overview/index.tsx | 22 ++++-- ui/src/pages/Cluster/index.tsx | 19 ++--- .../Detail/Backup/BackupConfiguration.tsx | 70 +++++++++---------- .../pages/Tenant/Detail/NewBackup/index.tsx | 2 +- ui/src/pages/Tenant/New/BasicInfo.tsx | 14 ++-- ui/src/services/index.ts | 51 +++++++++++--- ui/src/services/typings.d.ts | 1 + 11 files changed, 158 insertions(+), 92 deletions(-) diff --git a/ui/src/components/MonitorComp/LineGraph.tsx b/ui/src/components/MonitorComp/LineGraph.tsx index ab33b2a15..a4d61e330 100644 --- a/ui/src/components/MonitorComp/LineGraph.tsx +++ b/ui/src/components/MonitorComp/LineGraph.tsx @@ -44,7 +44,8 @@ export default function LineGraph({ const lineGraphRef = useRef(null); const lineInstanceRef = useRef(null); const [inViewport] = useInViewport(lineGraphRef); - // 进入可见区域次数,只在第一次进入可见区域发起网络请求 + // The number of times to enter the visible area, + //only initiate a network request when entering the visible area for the first time const [inViewportCount, setInViewportCount] = useState(0); const getQueryParms = () => { let metricsKeys: string[] = [metrics[0].key], @@ -55,7 +56,7 @@ export default function LineGraph({ if (type === 'OVERVIEW') realLabels = []; return { groupLabels, - labels: realLabels, //为空则查询全部集群 + labels: realLabels, // If empty, query all clusters metrics: metricsKeys, queryRange, type, @@ -110,6 +111,9 @@ export default function LineGraph({ if (!isEmpty) setIsEmpty(true); }; + + + // filter metricsData const { data: metricsData, run: queryMetrics, @@ -137,7 +141,7 @@ export default function LineGraph({ lineInstanceDestroy(); }, }); - + useUpdateEffect(() => { if (!isEmpty) { lineInstanceRender(metricsData); @@ -156,7 +160,7 @@ export default function LineGraph({ } }, [inViewportCount]); - //开启实时模式后处理 + // Process after turning on real-time mode useUpdateEffect(() => { if (!isRefresh) { if (inViewport) { diff --git a/ui/src/components/MonitorComp/index.tsx b/ui/src/components/MonitorComp/index.tsx index ba1a5af56..2b611d4ec 100644 --- a/ui/src/components/MonitorComp/index.tsx +++ b/ui/src/components/MonitorComp/index.tsx @@ -8,13 +8,15 @@ import { getAllMetrics } from '@/services'; import LineGraph,{ LineGraphProps,MetricType } from './LineGraph'; import styles from './index.less'; -//查询的label -// ob_cluster_name -// ob_cluster_id -// tenant_name -// tenant_id -// svr_ip -// obzone +/** + * Queryable label: + * ob_cluster_name + * ob_cluster_id + * tenant_name + * tenant_id + * svr_ip + * obzone + */ interface MonitorCompProps { filterLabel: API.MetricsLabels; diff --git a/ui/src/pages/Cluster/Detail/Overview/ZoneTable.tsx b/ui/src/pages/Cluster/Detail/Overview/ZoneTable.tsx index a8584bf50..6fbd0c21e 100644 --- a/ui/src/pages/Cluster/Detail/Overview/ZoneTable.tsx +++ b/ui/src/pages/Cluster/Detail/Overview/ZoneTable.tsx @@ -1,5 +1,5 @@ import { intl } from '@/utils/intl'; //@ts-nocheck -import { Col, Table, Tag, message, Card } from 'antd'; +import { Button,Card,Col,Table,Tag,message } from 'antd'; import type { ColumnType } from 'antd/es/table'; import showDeleteConfirm from '@/components/customModal/DeleteModal'; @@ -13,6 +13,7 @@ interface ZoneTableProps { chooseZoneRef: React.MutableRefObject; typeRef: React.MutableRefObject; setChooseServerNum: React.Dispatch>; + clusterStatus:'running' | 'failed' | 'operating' } export default function ZoneTable({ @@ -21,6 +22,7 @@ export default function ZoneTable({ chooseZoneRef, typeRef, setChooseServerNum, + clusterStatus }: ZoneTableProps) { const getZoneColumns = (remove, clickScale) => { const columns: ColumnType = [ @@ -80,20 +82,22 @@ export default function ZoneTable({ render: (value, record) => { return ( <> - { clickScale(record.zone); setChooseServerNum(record.replicas); }} + disabled={clusterStatus === 'failed'} + type="link" > {intl.formatMessage({ id: 'OBDashboard.Detail.Overview.ZoneTable.Scale', defaultMessage: '扩缩容', })} - - + ); }, diff --git a/ui/src/pages/Cluster/Detail/Overview/helper.ts b/ui/src/pages/Cluster/Detail/Overview/helper.ts index ce74ddba1..239a33831 100644 --- a/ui/src/pages/Cluster/Detail/Overview/helper.ts +++ b/ui/src/pages/Cluster/Detail/Overview/helper.ts @@ -1,5 +1,5 @@ // Functions without UI -import { CLUSTER_INFO_CONFIG } from "@/constants"; +import { CLUSTER_INFO_CONFIG, RESULT_STATUS } from "@/constants"; /** * Get the namespace, name and cluster name or tenant name through the path of the url @@ -36,16 +36,18 @@ const getNSName = () => { // if there is cluster|zone|server whose status isn't running,the return status is operating. const formatClusterData = (responseData: any): API.ClusterDetail => { const res: any = { + status:responseData.status, info: {}, metrics: {}, zones: [], servers: [], }; - let status: 'running' | 'operating' = 'running'; + // let status: 'running' | 'operating' = 'running'; + for (let key of Object.keys(responseData)) { - if (key === 'status' && responseData[key] !== 'running') { - status = 'operating'; - } + // if (key === 'status' && !RESULT_STATUS.includes(responseData[key])) { + // status = 'operating'; + // } if(CLUSTER_INFO_CONFIG.includes(key)){ res['info'][key] = responseData[key]; } @@ -69,17 +71,16 @@ const formatClusterData = (responseData: any): API.ClusterDetail => { } return temp; }); - for (let zone of zones) { - if (zone.status !== 'running') status = 'operating'; - } - for (let server of servers) { - if (server.status !== 'running') status = 'operating'; - } + // for (let zone of zones) { + // if (!RESULT_STATUS.includes(zone.status)) status = 'operating'; + // } + // for (let server of servers) { + // if (!RESULT_STATUS.includes(server.status)) status = 'operating'; + // } res['zones'] = zones; res['servers'] = servers; } } - res.status = status; return res; }; diff --git a/ui/src/pages/Cluster/Detail/Overview/index.tsx b/ui/src/pages/Cluster/Detail/Overview/index.tsx index 2184b9922..87e1f9744 100644 --- a/ui/src/pages/Cluster/Detail/Overview/index.tsx +++ b/ui/src/pages/Cluster/Detail/Overview/index.tsx @@ -42,7 +42,6 @@ const ClusterOverview: React.FC = () => { }, }, ); - const isOperating = clusterDetail && clusterDetail.status === 'operating'; const handleDelete = async () => { const res = await deleteObcluster({ ns, name }); if (res.successful) { @@ -77,20 +76,34 @@ const ClusterOverview: React.FC = () => { defaultMessage: '集群概览', }), extra: [ - , - , - deleteBackupPolicyReq({ ns, name })} - title={intl.formatMessage({ - id: 'Dashboard.Detail.Backup.BackupConfiguration.DeleteBackup', - defaultMessage: '删除备份', - })} - description={intl.formatMessage({ - id: 'Dashboard.Detail.Backup.BackupConfiguration.AreYouSureYouWant', - defaultMessage: '确定要删除该备份策略吗?', - })} + - + {intl.formatMessage({ + id: 'Dashboard.Detail.Backup.BackupConfiguration.Delete', + defaultMessage: '删除', + })} + } > diff --git a/ui/src/pages/Tenant/Detail/NewBackup/index.tsx b/ui/src/pages/Tenant/Detail/NewBackup/index.tsx index a69f7e39c..fdfa224b3 100644 --- a/ui/src/pages/Tenant/Detail/NewBackup/index.tsx +++ b/ui/src/pages/Tenant/Detail/NewBackup/index.tsx @@ -26,7 +26,7 @@ export default function NewBackup() { ]; const handleSubmit = async (values: any) => { - if (!checkScheduleDatesHaveFull(values)) { + if (!checkScheduleDatesHaveFull(values.scheduleDates)) { message.warning( intl.formatMessage({ id: 'Dashboard.Detail.NewBackup.ConfigureAtLeastOneFull', diff --git a/ui/src/pages/Tenant/New/BasicInfo.tsx b/ui/src/pages/Tenant/New/BasicInfo.tsx index 5969ad188..a9536f953 100644 --- a/ui/src/pages/Tenant/New/BasicInfo.tsx +++ b/ui/src/pages/Tenant/New/BasicInfo.tsx @@ -1,8 +1,8 @@ import InputNumber from '@/components/InputNumber'; import PasswordInput from '@/components/PasswordInput'; -import { RESOURCE_NAME_REG, TZ_NAME_REG } from '@/constants'; +import { RESOURCE_NAME_REG,TZ_NAME_REG } from '@/constants'; import { intl } from '@/utils/intl'; -import { Card, Col, Form, Input, Row, Select } from 'antd'; +import { Card,Col,Form,Input,Row,Select } from 'antd'; import type { FormInstance } from 'antd/lib/form'; interface BasicInfoProps { @@ -20,10 +20,12 @@ export default function BasicInfo({ setPasswordVal, setSelectClusterId, }: BasicInfoProps) { - const clusterOptions = clusterList.map((cluster) => ({ - value: cluster.clusterId, - label: cluster.name, - })); + const clusterOptions = clusterList + .filter((cluster) => cluster.status !== 'failed') + .map((cluster) => ({ + value: cluster.clusterId, + label: cluster.name, + })); const selectClusterChange = (id: number) => { setSelectClusterId(id); }; diff --git a/ui/src/services/index.ts b/ui/src/services/index.ts index 718c6b3ae..18da5d0b3 100644 --- a/ui/src/services/index.ts +++ b/ui/src/services/index.ts @@ -3,8 +3,9 @@ import { formatClusterData } from '@/pages/Cluster/Detail/Overview/helper'; import { formatStatisticData } from '@/utils/helper'; import { intl } from '@/utils/intl'; //@ts-nocheck import { request } from '@umijs/max'; -import _,{ cloneDeep } from 'lodash'; +import _ from 'lodash'; import moment from 'moment'; +import { getAllTenants } from './tenant'; const obClusterPrefix = '/api/v1/obclusters'; const clusterPrefix = '/api/v1/cluster'; @@ -138,10 +139,13 @@ export async function getObclusterListReq() { } res.push(obj); } - return res; + return { + ...r, + data:res + } } - return []; + return r; } export async function getSimpleClusterList(): Promise { @@ -156,7 +160,8 @@ export async function getSimpleClusterList(): Promise{ return `${tenantName}(${clustetName})` } -export async function queryMetricsReq({ useFor, type, ...data }: API.QueryMetricsType) { +const filterMetricsData = async ( + type: 'tenant' | 'cluster', + metricsData: any, +) => { + const request = type === 'cluster' ? getObclusterListReq : getAllTenants; + const { data, successful } = await request(); + if (successful) { + return metricsData.filter((item) => { + let targetName = + item?.metric?.labels?.find( + (label) => + label.key === + (type === 'tenant' ? 'tenant_name' : 'ob_cluster_name'), + ).value || ''; + if(type === 'cluster'){ + return !!data.find((cluster)=>cluster.clusterName === targetName); + }else{ + return !!data.find((tenant)=>tenant.tenantName === targetName); + } + }); + } + return metricsData; +}; + +export async function queryMetricsReq({ + useFor, + type, + ...data +}: API.QueryMetricsType) { const r = await request('/api/v1/metrics/query', { method: 'POST', data, }); if (r.successful) { + r.data = await filterMetricsData(useFor,r.data); if (!r.data || !r.data.length) return []; r.data.forEach((metric) => { - metric.values.forEach((item) => { // item.date = moment.unix(item.timestamp).format('YYYY-MM-DD HH:mm:ss'); item.date = item.timestamp * 1000; if (type === 'OVERVIEW') { if (useFor === 'tenant') { - let metricLabels = metric.metric.labels; - if(metricLabels.length > 1){ + let metricLabels = metric.metric.labels; + if (metricLabels.length > 1) { item.name = setMetricNameFromLabels(metricLabels); - }else{ + } else { item.name = metricLabels[0]?.value || ''; } } else { diff --git a/ui/src/services/typings.d.ts b/ui/src/services/typings.d.ts index b2fb79741..145755821 100644 --- a/ui/src/services/typings.d.ts +++ b/ui/src/services/typings.d.ts @@ -132,6 +132,7 @@ declare namespace API { clusterId: number; namespace: string; topology: Topology[]; + status: string; } type SimpleClusterList = SimpleCluster[];