mirror of
https://github.com/didi/KnowStreaming.git
synced 2026-01-13 19:42:15 +08:00
V3.2
This commit is contained in:
@@ -1,20 +1,13 @@
|
||||
import { Col, Row, SingleChart, Utils, Modal, Spin, Empty, AppContainer, Tooltip } from 'knowdesign';
|
||||
import { IconFont } from '@knowdesign/icons';
|
||||
import { SingleChart, Utils, Spin, AppContainer, Tooltip } from 'knowdesign';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { arrayMoveImmutable } from 'array-move';
|
||||
import api from '@src/api';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {
|
||||
OriginMetricData,
|
||||
FormattedMetricData,
|
||||
formatChartData,
|
||||
supplementaryPoints,
|
||||
resolveMetricsRank,
|
||||
MetricInfo,
|
||||
} from '@src/constants/chartConfig';
|
||||
import { OriginMetricData, FormattedMetricData, formatChartData, supplementaryPoints } from '@src/constants/chartConfig';
|
||||
import { MetricType } from '@src/api';
|
||||
import { getDataUnit } from '@src/constants/chartConfig';
|
||||
import ChartOperateBar, { KsHeaderOptions } from '@src/components/ChartOperateBar';
|
||||
import MetricsFilter from '@src/components/ChartOperateBar/MetricSelect';
|
||||
import RenderEmpty from '@src/components/RenderEmpty';
|
||||
import DragGroup from '@src/components/DragGroup';
|
||||
import { getChartConfig } from './config';
|
||||
@@ -56,7 +49,6 @@ const DEFUALT_METRIC_NEED_METRICS = [DEFAULT_METRIC, 'TotalLogSize', 'TotalProdu
|
||||
const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
|
||||
const [global] = AppContainer.useGlobalValue();
|
||||
const { clusterId } = useParams<{ clusterId: string }>();
|
||||
const [metricList, setMetricList] = useState<MetricInfo[]>([]); // 指标列表
|
||||
const [selectedMetricNames, setSelectedMetricNames] = useState<(string | number)[]>([]); // 默认选中的指标的列表
|
||||
const [metricDataList, setMetricDataList] = useState<any>([]);
|
||||
const [messagesInMetricData, setMessagesInMetricData] = useState<MessagesInMetric>({
|
||||
@@ -72,6 +64,7 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
|
||||
messagesIn: 0,
|
||||
other: 0,
|
||||
});
|
||||
const metricFilterRef = useRef(null);
|
||||
|
||||
// 筛选项变化或者点击刷新按钮
|
||||
const ksHeaderChange = (ksOptions: KsHeaderOptions) => {
|
||||
@@ -86,65 +79,9 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
|
||||
});
|
||||
};
|
||||
|
||||
// 更新 rank
|
||||
const updateRank = (metricList: MetricInfo[]) => {
|
||||
const { list, listInfo, shouldUpdate } = resolveMetricsRank(metricList);
|
||||
metricRankList.current = list;
|
||||
if (shouldUpdate) {
|
||||
updateMetricList(listInfo);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取指标列表
|
||||
const getMetricList = () => {
|
||||
Utils.request(api.getDashboardMetricList(clusterId, MetricType.Cluster)).then((res: MetricInfo[] | null) => {
|
||||
if (!res) return;
|
||||
const supportMetrics = res.filter((metric) => metric.support);
|
||||
const selectedMetrics = supportMetrics.filter((metric) => metric.set).map((metric) => metric.name);
|
||||
!selectedMetrics.includes(DEFAULT_METRIC) && selectedMetrics.push(DEFAULT_METRIC);
|
||||
updateRank([...supportMetrics]);
|
||||
setMetricList(supportMetrics);
|
||||
setSelectedMetricNames(selectedMetrics);
|
||||
});
|
||||
};
|
||||
|
||||
// 更新指标
|
||||
const updateMetricList = (metricDetailDTOList: { metric: string; rank: number; set: boolean }[]) => {
|
||||
return Utils.request(api.getDashboardMetricList(clusterId, MetricType.Cluster), {
|
||||
method: 'POST',
|
||||
data: {
|
||||
metricDetailDTOList,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 指标选中项更新回调
|
||||
const indicatorChangeCallback = (newMetricNames: (string | number)[]) => {
|
||||
const updateMetrics: { metric: string; set: boolean; rank: number }[] = [];
|
||||
// 需要选中的指标
|
||||
newMetricNames.forEach(
|
||||
(name) =>
|
||||
!selectedMetricNames.includes(name) &&
|
||||
updateMetrics.push({ metric: name as string, set: true, rank: metricList.find(({ name: metric }) => metric === name)?.rank })
|
||||
);
|
||||
// 取消选中的指标
|
||||
selectedMetricNames.forEach(
|
||||
(name) =>
|
||||
!newMetricNames.includes(name) &&
|
||||
updateMetrics.push({ metric: name as string, set: false, rank: metricList.find(({ name: metric }) => metric === name)?.rank })
|
||||
);
|
||||
const requestPromise = Object.keys(updateMetrics).length ? updateMetricList(updateMetrics) : Promise.resolve();
|
||||
requestPromise.then(
|
||||
() => getMetricList(),
|
||||
() => getMetricList()
|
||||
);
|
||||
|
||||
return requestPromise;
|
||||
};
|
||||
|
||||
// 获取 metric 列表的图表数据
|
||||
const getMetricData = () => {
|
||||
if (!selectedMetricNames.length) return;
|
||||
if (!selectedMetricNames?.length) return;
|
||||
!curHeaderOptions.isAutoReload && setChartLoading(true);
|
||||
const [startTime, endTime] = curHeaderOptions.rangeTime;
|
||||
|
||||
@@ -286,7 +223,7 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
|
||||
const originTarget = metricRankList.current.indexOf(metricDataList[newIndex].metricName);
|
||||
const newList = arrayMoveImmutable(metricRankList.current, originFrom, originTarget);
|
||||
metricRankList.current = newList;
|
||||
updateMetricList(newList.map((metric, rank) => ({ metric, rank, set: metricList.find(({ name }) => metric === name)?.set || false })));
|
||||
metricFilterRef.current?.rankChange(originFrom, originTarget);
|
||||
setMetricDataList(arrayMoveImmutable(metricDataList, oldIndex, newIndex));
|
||||
};
|
||||
|
||||
@@ -302,29 +239,23 @@ const DetailChart = (props: { children: JSX.Element }): JSX.Element => {
|
||||
}, [curHeaderOptions]);
|
||||
|
||||
useEffect(() => {
|
||||
getMetricList();
|
||||
setTimeout(() => observeDashboardWidthChange());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="chart-panel cluster-detail-container">
|
||||
<ChartOperateBar
|
||||
openMetricFilter={() => metricFilterRef.current?.open()}
|
||||
onChange={ksHeaderChange}
|
||||
hideNodeScope={true}
|
||||
hideGridSelect={true}
|
||||
metricSelect={{
|
||||
hide: false,
|
||||
metricType: MetricType.Cluster,
|
||||
tableData: metricList,
|
||||
selectedRows: selectedMetricNames,
|
||||
checkboxProps: (record: MetricInfo) => {
|
||||
return record.name === DEFAULT_METRIC
|
||||
? {
|
||||
disabled: true,
|
||||
}
|
||||
: {};
|
||||
},
|
||||
submitCallback: indicatorChangeCallback,
|
||||
/>
|
||||
<MetricsFilter
|
||||
ref={metricFilterRef}
|
||||
metricType={MetricType.Cluster}
|
||||
onSelectChange={(list, rankList) => {
|
||||
metricRankList.current = rankList;
|
||||
setSelectedMetricNames(list);
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
@@ -32,6 +32,14 @@ export const dimensionMap = {
|
||||
label: 'Zookeeper',
|
||||
href: '/zookeeper',
|
||||
},
|
||||
5: {
|
||||
label: 'Connect',
|
||||
href: '/connect',
|
||||
},
|
||||
6: {
|
||||
label: 'Connector',
|
||||
href: '/connect/connectors',
|
||||
},
|
||||
} as any;
|
||||
|
||||
const toLowerCase = (name = '') => {
|
||||
@@ -78,6 +86,15 @@ const CONFIG_ITEM_DETAIL_DESC = {
|
||||
SentRate: (valueGroup: any) => {
|
||||
return `Zookeeper 首发包数小于 ${valueGroup?.ratio * 100}% 总容量`;
|
||||
},
|
||||
TaskStartupFailurePercentage: (valueGroup: any) => {
|
||||
return `任务启动失败概率 小于 ${valueGroup?.value * 100}%`;
|
||||
},
|
||||
ConnectorFailedTaskCount: (valueGroup: any) => {
|
||||
return `失败状态的任务数量 小于 ${valueGroup?.value}`;
|
||||
},
|
||||
ConnectorUnassignedTaskCount: (valueGroup: any) => {
|
||||
return `未被分配的任务数量 小于 ${valueGroup?.value}`;
|
||||
},
|
||||
};
|
||||
|
||||
export const getConfigItemDetailDesc = (item: keyof typeof CONFIG_ITEM_DETAIL_DESC, valueGroup: any) => {
|
||||
@@ -145,9 +162,9 @@ export const getDetailColumn = (clusterId: number) => [
|
||||
// eslint-disable-next-line react/display-name
|
||||
render: (text: number, record: any) => {
|
||||
return dimensionMap[text] ? (
|
||||
<Link to={`/${systemKey}/${clusterId}${dimensionMap[text]?.href}`}>{toLowerCase(record?.dimensionName)}</Link>
|
||||
<Link to={`/${systemKey}/${clusterId}${dimensionMap[text]?.href}`}>{record?.dimensionDisplayName}</Link>
|
||||
) : (
|
||||
toLowerCase(record?.dimensionName)
|
||||
record?.dimensionDisplayName
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -219,9 +236,9 @@ export const getHealthySettingColumn = (form: any, data: any, clusterId: string)
|
||||
// eslint-disable-next-line react/display-name
|
||||
render: (text: number, record: any) => {
|
||||
return dimensionMap[text] ? (
|
||||
<Link to={`/${systemKey}/${clusterId}${dimensionMap[text]?.href}`}>{toLowerCase(record?.dimensionName)}</Link>
|
||||
<Link to={`/${systemKey}/${clusterId}${dimensionMap[text]?.href}`}>{record?.dimensionDisplayName}</Link>
|
||||
) : (
|
||||
toLowerCase(record?.dimensionName)
|
||||
record?.dimensionDisplayName
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -365,6 +382,33 @@ export const getHealthySettingColumn = (form: any, data: any, clusterId: string)
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'TaskStartupFailurePercentage': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, percent: true })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'ConnectorFailedTaskCount': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, attrs: { min: 0, max: 99998 } })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'ConnectorUnassignedTaskCount': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, attrs: { min: 0, max: 99998 } })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user