split cluster metric and change cluster health metric from line to bar

This commit is contained in:
liugq 2021-11-28 14:17:08 +08:00
parent da07a41fee
commit 5253cdc779
3 changed files with 226 additions and 99 deletions

View File

@ -36,6 +36,7 @@ import { EuiSuperDatePicker } from "@elastic/eui";
import { calculateBounds } from "../../components/kibana/data/common/query/timefilter";
import NodeMetric from "./components/node_metric";
import IndexMetric from "./components/index_metric";
import ClusterMetric from "./components/cluster_metric";
import { formatter, getFormatter, getNumFormatter } from "./format";
const { RangePicker } = DatePicker;
@ -169,7 +170,6 @@ class ClusterMonitor extends PureComponent {
super(props);
//this.timePicker = React.createRef();
this.handleChartBrush = this.handleChartBrush.bind(this);
this.chartRefs = [];
this.handleTimeChange = this.handleTimeChange.bind(this);
this.state = {
spinning: false,
@ -214,9 +214,6 @@ class ClusterMonitor extends PureComponent {
cluster_id: this.state.clusterID,
},
}).then((res) => {
this.chartRefs = Object.keys(res?.metrics || {}).map(() => {
return React.createRef();
});
this.setState({
spinning: false,
});
@ -592,107 +589,19 @@ class ClusterMonitor extends PureComponent {
</Row>
</div>
<div>
<Tabs animated={false}>
<Tabs destroyInactiveTabPane animated={false}>
<Tabs.TabPane
key="cluster"
tab={formatMessage({
id: "cluster.monitor.cluster.title",
})}
>
{Object.keys(clusterMetrics).map((e, i) => {
let axis = clusterMetrics[e].axis;
let lines = clusterMetrics[e].lines;
let disableHeaderFormat = false;
let headerUnit = "";
return (
<div key={e} className={styles.vizChartContainer}>
<Chart
size={[, 200]}
className={styles.vizChartItem}
ref={this.chartRefs[i]}
>
<Settings
pointerUpdateDebounce={0}
pointerUpdateTrigger="x"
// externalPointerEvents={{
// tooltip: { visible: true },
// }}
onPointerUpdate={this.pointerUpdate}
theme={theme}
showLegend
legendPosition={Position.Top}
onBrushEnd={this.handleChartBrush}
tooltip={{
headerFormatter: disableHeaderFormat
? undefined
: ({ value }) =>
`${formatter.full_dates(value)}${
headerUnit ? ` ${headerUnit}` : ""
}`,
}}
debug={false}
/>
<Axis
id="{e}-bottom"
position={Position.Bottom}
showOverlappingTicks
labelFormat={this.state.timeRange.timeFormatter}
tickFormat={this.state.timeRange.timeFormatter}
/>
{axis.map((item) => {
return (
<Axis
key={e + "-" + item.id}
id={e + "-" + item.id}
showGridLines={item.showGridLines}
groupId={item.group}
title={formatMessage({
id:
"dashboard.charts.title." +
e +
".axis." +
item.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}
color={item.color}
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>
);
})}
<ClusterMetric
clusterID={this.props.selectedCluster.id}
timezone={timezone}
timeRange={this.state.timeRange}
handleTimeChange={this.handleTimeChange}
/>
</Tabs.TabPane>
<Tabs.TabPane
key="node"

View File

@ -0,0 +1,215 @@
import * as React from "react";
import {
Axis,
Chart,
CurveType,
LineSeries,
BarSeries,
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 } 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 _ from "lodash";
export default ({ clusterID, timezone, timeRange, handleTimeChange }) => {
const queryParams = React.useMemo(() => {
const bounds = calculateBounds({
from: timeRange.min,
to: timeRange.max,
});
return {
min: bounds.min.valueOf(),
max: bounds.max.valueOf(),
};
}, [timeRange]);
const { loading, error, value } = useFetch(
`${ESPrefix}/${clusterID}/cluster_metrics`,
{
queryParams: queryParams,
},
[clusterID, queryParams]
);
const { metrics = {} } = value || {};
const chartRefs = React.useRef();
React.useEffect(() => {
let refs = [];
Object.keys(metrics).map((m) => {
refs.push(React.createRef());
});
chartRefs.current = refs;
}, [metrics]);
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="cluster-metric">
<div className="px">
<Skeleton active loading={!value} paragraph={{ rows: 20 }}>
{Object.keys(metrics).map((e, i) => {
let axis = metrics[e].axis;
let lines = metrics[e].lines;
let disableHeaderFormat = false;
let headerUnit = "";
return (
<div key={e} className={styles.vizChartContainer}>
<Chart
size={[, 200]}
className={styles.vizChartItem}
ref={chartRefs[i]}
>
<Settings
pointerUpdateDebounce={0}
pointerUpdateTrigger="x"
// externalPointerEvents={{
// tooltip: { visible: true },
// }}
onPointerUpdate={pointerUpdate}
// theme={theme}
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}
/>
{e == "cluster_health" ? (
<Axis
id="cluster_health"
title={formatMessage({
id: "dashboard.charts.title." + e + ".axis.percent",
})}
position={Position.Left}
tickFormat={(d) => Number(d).toFixed(0) + "%"}
/>
) : null}
{axis.map((item) => {
return (
<Axis
key={e + "-" + item.id}
id={e + "-" + item.id}
showGridLines={item.showGridLines}
groupId={item.group}
title={formatMessage({
id:
"dashboard.charts.title." +
e +
".axis." +
item.title,
})}
position={item.position}
ticks={item.ticks}
labelFormat={getFormatter(
item.formatType,
item.labelFormat
)}
tickFormat={getFormatter(
item.formatType,
item.tickFormat
)}
/>
);
})}
{lines.map((item) => {
if (item.type == "bar") {
return (
<BarSeries
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
xAccessor="x"
yAccessors={["y"]}
stackAccessors={["x"]}
splitSeriesAccessors={["g"]}
data={item.data}
color={({ specId, yAccessor, splitAccessors }) => {
const g = splitAccessors.get("g");
if (
yAccessor === "y" &&
["red", "yellow", "green"].includes(g)
) {
return g;
}
return null;
}}
/>
);
}
return (
<LineSeries
key={item.metric.label}
id={item.metric.label}
groupId={item.metric.group}
timeZone={timezone}
color={item.color}
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>
);
})}
</Skeleton>
</div>
</div>
);
};

View File

@ -178,6 +178,9 @@ export default ({ clusterID, timezone, timeRange, handleTimeChange }) => {
{metrics[e].map((metric) => {
let axis = metric.axis;
let lines = metric.lines;
if (lines && lines[0].data && lines[0].data.length == 0) {
return null;
}
let disableHeaderFormat = false;
let headerUnit = "";
return (