split cluster metric and change cluster health metric from line to bar
This commit is contained in:
parent
da07a41fee
commit
5253cdc779
|
@ -36,6 +36,7 @@ import { EuiSuperDatePicker } from "@elastic/eui";
|
||||||
import { calculateBounds } from "../../components/kibana/data/common/query/timefilter";
|
import { calculateBounds } from "../../components/kibana/data/common/query/timefilter";
|
||||||
import NodeMetric from "./components/node_metric";
|
import NodeMetric from "./components/node_metric";
|
||||||
import IndexMetric from "./components/index_metric";
|
import IndexMetric from "./components/index_metric";
|
||||||
|
import ClusterMetric from "./components/cluster_metric";
|
||||||
import { formatter, getFormatter, getNumFormatter } from "./format";
|
import { formatter, getFormatter, getNumFormatter } from "./format";
|
||||||
|
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
|
@ -169,7 +170,6 @@ class ClusterMonitor extends PureComponent {
|
||||||
super(props);
|
super(props);
|
||||||
//this.timePicker = React.createRef();
|
//this.timePicker = React.createRef();
|
||||||
this.handleChartBrush = this.handleChartBrush.bind(this);
|
this.handleChartBrush = this.handleChartBrush.bind(this);
|
||||||
this.chartRefs = [];
|
|
||||||
this.handleTimeChange = this.handleTimeChange.bind(this);
|
this.handleTimeChange = this.handleTimeChange.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
spinning: false,
|
spinning: false,
|
||||||
|
@ -214,9 +214,6 @@ class ClusterMonitor extends PureComponent {
|
||||||
cluster_id: this.state.clusterID,
|
cluster_id: this.state.clusterID,
|
||||||
},
|
},
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.chartRefs = Object.keys(res?.metrics || {}).map(() => {
|
|
||||||
return React.createRef();
|
|
||||||
});
|
|
||||||
this.setState({
|
this.setState({
|
||||||
spinning: false,
|
spinning: false,
|
||||||
});
|
});
|
||||||
|
@ -592,107 +589,19 @@ class ClusterMonitor extends PureComponent {
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Tabs animated={false}>
|
<Tabs destroyInactiveTabPane animated={false}>
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
key="cluster"
|
key="cluster"
|
||||||
tab={formatMessage({
|
tab={formatMessage({
|
||||||
id: "cluster.monitor.cluster.title",
|
id: "cluster.monitor.cluster.title",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{Object.keys(clusterMetrics).map((e, i) => {
|
<ClusterMetric
|
||||||
let axis = clusterMetrics[e].axis;
|
clusterID={this.props.selectedCluster.id}
|
||||||
let lines = clusterMetrics[e].lines;
|
timezone={timezone}
|
||||||
let disableHeaderFormat = false;
|
timeRange={this.state.timeRange}
|
||||||
let headerUnit = "";
|
handleTimeChange={this.handleTimeChange}
|
||||||
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>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
key="node"
|
key="node"
|
||||||
|
|
|
@ -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>
|
||||||
|
);
|
||||||
|
};
|
|
@ -178,6 +178,9 @@ export default ({ clusterID, timezone, timeRange, handleTimeChange }) => {
|
||||||
{metrics[e].map((metric) => {
|
{metrics[e].map((metric) => {
|
||||||
let axis = metric.axis;
|
let axis = metric.axis;
|
||||||
let lines = metric.lines;
|
let lines = metric.lines;
|
||||||
|
if (lines && lines[0].data && lines[0].data.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
let disableHeaderFormat = false;
|
let disableHeaderFormat = false;
|
||||||
let headerUnit = "";
|
let headerUnit = "";
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in New Issue