add queue mertic

This commit is contained in:
liugq 2021-11-30 19:46:19 +08:00
parent 948ad752ab
commit 88bf54a615
1 changed files with 274 additions and 0 deletions

View File

@ -0,0 +1,274 @@
import * as React from "react";
import {
Axis,
Chart,
CurveType,
LineSeries,
niceTimeFormatByDay,
Position,
ScaleType,
Settings,
timeFormatter,
} from "@elastic/charts";
import useFetch from "@/lib/hooks/use_fetch";
import { ESPrefix } from "@/services/common";
import styles from "../Metrics.less";
import { Spin, Radio, Select, Skeleton, Row, Col } from "antd";
import { formatter, getFormatter, getNumFormatter } from "../format";
import "./node_metric.scss";
import { calculateBounds } from "@/components/kibana/data/common/query/timefilter";
import moment from "moment";
import { formatMessage } from "umi/locale";
import MetricContainer from "./metric_container";
import _ from "lodash";
const gorupOrder = ["system"];
export default ({ clusterID, timezone, timeRange, handleTimeChange }) => {
const [filter, setFilter] = React.useState({
top: "5",
node_name: undefined,
});
const topChange = React.useCallback(
(e) => {
setFilter({
node_name: undefined,
top: e.target.value,
});
},
[setFilter]
);
const nodeValueChange = React.useCallback(
(value) => {
setFilter({
top: undefined,
node_name: value,
});
},
[setFilter]
);
const queryParams = React.useMemo(() => {
const bounds = calculateBounds({
from: timeRange.min,
to: timeRange.max,
});
return {
...filter,
min: bounds.min.valueOf(),
max: bounds.max.valueOf(),
};
}, [filter, timeRange]);
const { loading, error, value } = useFetch(
`${ESPrefix}/${clusterID}/queue_metrics`,
{
queryParams: queryParams,
},
[clusterID, queryParams]
);
const metrics = React.useMemo(() => {
return _.groupBy(value?.metrics, "group");
// return Object.values(value?.metrics || {}).sort(
// (a, b) => a.order - b.order
// );
}, [value]);
const chartRefs = React.useRef();
React.useEffect(() => {
let refs = [];
Object.values(metrics).map((m) => {
m.forEach(() => {
refs.push(React.createRef());
});
});
chartRefs.current = refs;
}, [metrics]);
const { value: nodes } = useFetch(`${ESPrefix}/${clusterID}/nodes`, {}, [
clusterID,
]);
const nodeNames = React.useMemo(() => {
return Object.keys(nodes || {}).map((k) => nodes[k].transport_address);
}, [nodes]);
const pointerUpdate = (event) => {
chartRefs.current.forEach((ref) => {
if (ref.current) {
ref.current.dispatchExternalPointerEvent(event);
}
});
};
const handleChartBrush = ({ x }) => {
if (!x) {
return;
}
const [from, to] = x;
if (typeof handleTimeChange == "function") {
handleTimeChange({
start: moment(from).toISOString(),
end: moment(to).toISOString(),
});
}
};
let refIdx = 0;
if (Object.keys(metrics).length == 0) {
return null;
}
return (
<div id="node-metric">
<div className="px">
<div className="metric-control">
<div className="selector">
<div className="top_radio">
<Radio.Group onChange={topChange} value={filter.top}>
<Radio.Button key="5" value="5">
Top5
</Radio.Button>
<Radio.Button key="10" value="10">
Top10
</Radio.Button>
<Radio.Button key="15" value="15">
Top15
</Radio.Button>
<Radio.Button key="20" value="20">
Top20
</Radio.Button>
</Radio.Group>
</div>
<div className="value-selector">
<Select
style={{ width: 200 }}
onChange={nodeValueChange}
placeholder="Select node"
value={filter.node_name}
showSearch={true}
>
{nodeNames.map((name) => (
<Select.Option key={name}>{name}</Select.Option>
))}
</Select>
</div>
</div>
</div>
</div>
<div className="px">
<Skeleton active loading={!value} paragraph={{ rows: 20 }}>
{//Object.keys(metrics)
gorupOrder.map((e, i) => {
return (
<div key={e} style={{ margin: "8px 0" }}>
<MetricContainer
title={formatMessage({ id: `cluster.metrics.group.${e}` })}
collapsed={false}
>
<div className="metric-inner-cnt">
{metrics[e].map((metric) => {
let axis = metric.axis;
let lines = metric.lines;
if (lines && lines[0]?.data?.length == 0) {
return null;
}
let disableHeaderFormat = false;
let headerUnit = "";
return (
<div key={metrics.key} className="metric-item">
<Chart
size={[, 200]}
className={styles.vizChartItem}
ref={chartRefs.current[refIdx++]}
>
<Settings
// theme={theme}
pointerUpdateDebounce={0}
pointerUpdateTrigger="x"
// externalPointerEvents={{
// tooltip: { visible: true },
// }}
onPointerUpdate={pointerUpdate}
showLegend
legendPosition={Position.Top}
onBrushEnd={handleChartBrush}
tooltip={{
headerFormatter: disableHeaderFormat
? undefined
: ({ value }) =>
`${formatter.full_dates(value)}${
headerUnit ? ` ${headerUnit}` : ""
}`,
}}
debug={false}
/>
<Axis
id="{e}-bottom"
position={Position.Bottom}
showOverlappingTicks
labelFormat={timeRange.timeFormatter}
tickFormat={timeRange.timeFormatter}
ticks={8}
/>
{axis.map((item) => {
return (
<Axis
key={e + "-" + item.id}
id={e + "-" + item.id}
showGridLines={item.showGridLines}
groupId={item.group}
title={formatMessage({
id:
"cluster.metrics.node.axis." +
metric.key +
".title",
})}
position={item.position}
ticks={item.ticks}
labelFormat={getFormatter(
item.formatType,
item.labelFormat
)}
tickFormat={getFormatter(
item.formatType,
item.tickFormat
)}
/>
);
})}
{lines.map((item) => {
return (
<LineSeries
key={item.metric.label}
id={item.metric.label}
groupId={item.metric.group}
timeZone={timezone}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
xAccessor={0}
tickFormat={getFormatter(
item.metric.formatType,
item.metric.tickFormat,
item.metric.units
)}
yAccessors={[1]}
data={item.data}
curve={CurveType.CURVE_MONOTONE_X}
/>
);
})}
</Chart>
</div>
);
})}
</div>
</MetricContainer>
</div>
);
})}
</Skeleton>
</div>
</div>
);
};