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 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"
|
||||
|
|
|
@ -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) => {
|
||||
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 (
|
||||
|
|
Loading…
Reference in New Issue