add queue mertic
This commit is contained in:
parent
948ad752ab
commit
88bf54a615
|
@ -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>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue