kafka-manager 2.0

This commit is contained in:
zengqiao
2020-09-28 15:46:34 +08:00
parent 28d985aaf1
commit c6e4b60424
1253 changed files with 82183 additions and 37179 deletions

View File

@@ -0,0 +1,210 @@
import { EChartOption } from 'echarts/lib/echarts';
import moment from 'moment';
import { ICurve } from 'container/common-curve/config';
import { adminMonitor } from 'store/admin-monitor';
import { parseBrokerMetricOption } from './parser';
export interface IPeriod {
label: string;
key: string;
dateRange: [moment.Moment, moment.Moment];
}
export const getMoment = () => {
return moment();
};
export const baseColors = ['#F28E61', '#7082A6', '#5AD2A2', '#E96A72', '#59AEE9', '#65A8BF', '#9D7ECF'];
export enum curveKeys {
'byteIn/byteOut' = 'byteIn/byteOut',
bytesRejectedPerSec = 'bytesRejectedPerSec',
failFetchRequestPerSec = 'failFetchRequestPerSec',
failProduceRequestPerSec = 'failProduceRequestPerSec',
fetchConsumerRequestPerSec = 'fetchConsumerRequestPerSec',
healthScore = 'healthScore',
messagesInPerSec = 'messagesInPerSec',
networkProcessorIdlPercent = 'networkProcessorIdlPercent',
produceRequestPerSec = 'produceRequestPerSec',
requestHandlerIdlPercent = 'requestHandlerIdlPercent',
requestQueueSize = 'requestQueueSize',
responseQueueSize = 'responseQueueSize',
totalTimeFetchConsumer99Th = 'totalTimeFetchConsumer99Th',
totalTimeProduce99Th = 'totalTimeProduce99Th',
}
export const byteCurves: ICurve[] = [
{
title: 'byteIn/byteOut',
path: curveKeys['byteIn/byteOut'],
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'bytesRejectedPerSec',
path: curveKeys.bytesRejectedPerSec,
api: adminMonitor.getBrokersChartsData,
colors: ['#E96A72'],
},
];
export const perSecCurves: ICurve[] = [
{
title: 'failFetchRequestPerSec',
path: curveKeys.failFetchRequestPerSec,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'failProduceRequestPerSec',
path: curveKeys.failProduceRequestPerSec,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'fetchConsumerRequestPerSec',
path: curveKeys.fetchConsumerRequestPerSec,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'produceRequestPerSec',
path: curveKeys.produceRequestPerSec,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
},
];
export const otherCurves: ICurve[] = [
{
title: 'healthScore',
path: curveKeys.healthScore,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'messagesInPerSec',
path: curveKeys.messagesInPerSec,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'networkProcessorIdlPercent',
path: curveKeys.networkProcessorIdlPercent,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'requestHandlerIdlPercent',
path: curveKeys.requestHandlerIdlPercent,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'requestQueueSize',
path: curveKeys.requestQueueSize,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'responseQueueSize',
path: curveKeys.responseQueueSize,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'totalTimeFetchConsumer99Th',
path: curveKeys.totalTimeFetchConsumer99Th,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
}, {
title: 'totalTimeProduce99Th',
path: curveKeys.totalTimeProduce99Th,
api: adminMonitor.getBrokersChartsData,
colors: baseColors,
},
];
export enum curveType {
byteCurves = 'byteCurves',
perSecCurves = 'perSecCurves',
other = 'other',
}
export interface ICurveType {
type: curveType;
title: string;
curves: ICurve[];
parser: (option: ICurve, data: any[]) => EChartOption;
}
export const byteTypeCurves: ICurveType[] = [
{
type: curveType.byteCurves,
title: 'byte',
curves: byteCurves.concat(perSecCurves, otherCurves),
parser: parseBrokerMetricOption,
},
];
export const perSecTypeCurves: ICurveType[] = [
{
type: curveType.perSecCurves,
title: 'perSec',
curves: perSecCurves,
parser: parseBrokerMetricOption,
},
];
export const otherTypeCurves: ICurveType[] = [
{
type: curveType.other,
title: 'other',
curves: otherCurves,
parser: parseBrokerMetricOption,
},
];
export const allCurves: ICurveType[] = [].concat(byteTypeCurves);
const curveKeyMap = new Map<string, {typeInfo: ICurveType, curveInfo: ICurve}>();
allCurves.forEach(t => {
t.curves.forEach(c => {
curveKeyMap.set(c.path, {
typeInfo: t,
curveInfo: c,
});
});
});
export const CURVE_KEY_MAP = curveKeyMap;
export const PERIOD_RADIO = [
{
label: '10分钟',
key: 'tenMin',
get dateRange() {
return [getMoment().subtract(10, 'minute'), getMoment()];
},
},
{
label: '1小时',
key: 'oneHour',
get dateRange() {
return [getMoment().subtract(1, 'hour'), getMoment()];
},
},
{
label: '6小时',
key: 'sixHour',
get dateRange() {
return [getMoment().subtract(6, 'hour'), getMoment()];
},
},
{
label: '近1天',
key: 'oneDay',
get dateRange() {
return [getMoment().subtract(1, 'day'), getMoment()];
},
},
{
label: '近1周',
key: 'oneWeek',
get dateRange() {
return [getMoment().subtract(7, 'day'), getMoment()];
},
},
] as IPeriod[];
const periodRadioMap = new Map<string, IPeriod>();
PERIOD_RADIO.forEach(p => {
periodRadioMap.set(p.key, p);
});
export const PERIOD_RADIO_MAP = periodRadioMap;

View File

@@ -0,0 +1,14 @@
.curve-wrapper {
background-color: #fff;
padding: 24px;
position: relative;
}
.right-btn {
position: absolute;
right: 24px;
top: 24px;
}
.operator-select {
position: absolute;
top: 34px;
}

View File

@@ -0,0 +1,49 @@
import React from 'react';
import './index.less';
import { Radio, DatePicker, RadioChangeEvent, RangePickerValue, Button, Icon } from 'component/antd';
import { curveInfo } from 'store/curve-info';
import { curveKeys, CURVE_KEY_MAP, PERIOD_RADIO_MAP, PERIOD_RADIO } from './config';
import moment = require('moment');
import { observer } from 'mobx-react';
import { timeStampStr } from 'constants/strategy';
@observer
export class DataCurveFilter extends React.Component {
public handleRangeChange = (dates: RangePickerValue, dateStrings: [string, string]) => {
curveInfo.setTimeRange(dates as [moment.Moment, moment.Moment]);
this.refreshAll();
}
public radioChange = (e: RadioChangeEvent) => {
const { value } = e.target;
curveInfo.setTimeRange(PERIOD_RADIO_MAP.get(value).dateRange);
this.refreshAll();
}
public refreshAll = () => {
Object.keys(curveKeys).forEach((c: curveKeys) => {
const { typeInfo, curveInfo: option } = CURVE_KEY_MAP.get(c);
const { parser } = typeInfo;
curveInfo.getCommonCurveData(option, parser, true);
});
}
public render() {
return (
<>
<Radio.Group onChange={this.radioChange} defaultValue={curveInfo.periodKey}>
{PERIOD_RADIO.map(p => <Radio.Button key={p.key} value={p.key}>{p.label}</Radio.Button>)}
</Radio.Group>
<DatePicker.RangePicker
format={timeStampStr}
onChange={this.handleRangeChange}
className="ml-10"
value={curveInfo.timeRange}
/>
<div className="right-btn">
<Button onClick={this.refreshAll}><Icon className="dsui-icon-shuaxin1 mr-4" type="reload" /></Button>
</div>
</>
);
}
}

View File

@@ -0,0 +1,147 @@
import moment from 'moment';
import { EChartOption } from 'echarts';
import { ICurve, ILineData, baseLineLegend, baseLineGrid, baseAxisStyle, noAxis, UNIT_HEIGHT } from 'container/common-curve/config';
import { IClusterMetrics, ISeriesOption } from 'types/base-type';
import { timeFormat } from 'constants/strategy';
import { getFilterSeries } from 'lib/chart-utils';
import { dealFlowData } from 'lib/chart-utils';
export const getBaseOptions = (option: ICurve, data: ILineData[]) => {
const date = (data || []).map(i => moment(i.timeStamp).format(timeFormat));
return {
animationDuration: 200,
tooltip: {
trigger: 'axis',
},
toolbox: {
feature: {
saveAsImage: {},
},
},
legend: {
...baseLineLegend,
bottom: '0',
align: 'auto',
},
grid: {
...baseLineGrid,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: date,
...baseAxisStyle,
},
yAxis: {
type: 'value',
...baseAxisStyle,
...noAxis,
name: option.unit || '',
nameTextStyle: {
lineHeight: UNIT_HEIGHT,
},
},
series: [{
type: 'line',
data: data.map(i => {
return Number(i.value);
}),
}],
} as EChartOption;
};
export const parseLine = (option: ICurve, data: ILineData[]): EChartOption => {
return Object.assign({}, getBaseOptions(option, data), {
legend: {
...baseLineLegend,
bottom: '0',
align: 'auto',
},
}) as EChartOption;
};
export const parseBrokerMetricOption = (option: ICurve, data: IClusterMetrics[]): EChartOption => {
let name;
let series: ISeriesOption[];
data = data || [];
data = data.map(item => {
return {
time: moment(item.gmtCreate).format(timeFormat),
...item,
};
});
data = data.sort((a, b) => a.gmtCreate - b.gmtCreate);
const legend = option.path === 'byteIn/byteOut' ? ['bytesInPerSec', 'bytesOutPerSec'] : [option.path];
series = Array.from(legend, (item: string) => ({
name: item,
id: item,
type: 'line',
symbol: 'circle',
showSymbol: false,
smooth: true,
encode: {
x: 'time',
y: item,
tooltip: [
item,
],
},
data: data.map(row => row[item] !== null ? Number(row[item]) : null),
}));
const filterSeries = getFilterSeries(series);
const { name: unitName, data: xData } = dealFlowData(legend, data);
name = unitName;
data = xData;
return {
animationDuration: 200,
tooltip: {
trigger: 'axis',
},
toolbox: {
feature: {
saveAsImage: {},
},
},
grid: {
...baseLineGrid,
},
xAxis: {
splitLine: null,
type: 'time',
},
yAxis: {
type: 'value',
...baseAxisStyle,
...noAxis,
name,
nameTextStyle: {
lineHeight: UNIT_HEIGHT,
},
},
legend: {
data: legend,
...baseLineLegend,
bottom: '0',
align: 'auto',
},
dataset: {
source: data,
},
series: filterSeries,
};
};
export function isM(arr: number[]) {
const filterData = arr.filter(i => i !== 0);
if (filterData.length) return filterData.reduce((cur, pre) => cur + pre) / filterData.length >= 1000000;
return false;
}
export function isK(arr: number[]) {
const filterData = arr.filter(i => i !== 0);
if (filterData.length) return filterData.reduce((cur, pre) => cur + pre) / filterData.length >= 1000;
return false;
}