[Stack Monitoring] Migrate Index Views to React (#113660)
* index views * fix type Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
4693c3812e
commit
3d0da7f0f6
|
@ -27,6 +27,8 @@ import { KibanaOverviewPage } from './pages/kibana/overview';
|
|||
import { CODE_PATH_ELASTICSEARCH, CODE_PATH_BEATS, CODE_PATH_KIBANA } from '../../common/constants';
|
||||
import { ElasticsearchNodesPage } from './pages/elasticsearch/nodes_page';
|
||||
import { ElasticsearchIndicesPage } from './pages/elasticsearch/indices_page';
|
||||
import { ElasticsearchIndexPage } from './pages/elasticsearch/index_page';
|
||||
import { ElasticsearchIndexAdvancedPage } from './pages/elasticsearch/index_advanced_page';
|
||||
import { ElasticsearchNodePage } from './pages/elasticsearch/node_page';
|
||||
import { MonitoringTimeContainer } from './hooks/use_monitoring_time';
|
||||
import { BreadcrumbContainer } from './hooks/use_breadcrumbs';
|
||||
|
@ -84,6 +86,21 @@ const MonitoringApp: React.FC<{
|
|||
/>
|
||||
|
||||
{/* ElasticSearch Views */}
|
||||
|
||||
<RouteInit
|
||||
path="/elasticsearch/indices/:index/advanced"
|
||||
component={ElasticsearchIndexAdvancedPage}
|
||||
codePaths={[CODE_PATH_ELASTICSEARCH]}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
|
||||
<RouteInit
|
||||
path="/elasticsearch/indices/:index"
|
||||
component={ElasticsearchIndexPage}
|
||||
codePaths={[CODE_PATH_ELASTICSEARCH]}
|
||||
fetchAllClusters={false}
|
||||
/>
|
||||
|
||||
<RouteInit
|
||||
path="/elasticsearch/indices"
|
||||
component={ElasticsearchIndicesPage}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React, { useContext, useState, useCallback } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { GlobalStateContext } from '../../global_state_context';
|
||||
import { ComponentProps } from '../../route_init';
|
||||
import { SetupModeRenderer } from '../../setup_mode/setup_mode_renderer';
|
||||
import { SetupModeContext } from '../../../components/setup_mode/setup_mode_context';
|
||||
import { useCharts } from '../../hooks/use_charts';
|
||||
import { ItemTemplate } from './item_template';
|
||||
// @ts-ignore
|
||||
import { AdvancedIndex } from '../../../components/elasticsearch/index/advanced';
|
||||
|
||||
interface SetupModeProps {
|
||||
setupMode: any;
|
||||
flyoutComponent: any;
|
||||
bottomBarComponent: any;
|
||||
}
|
||||
|
||||
export const ElasticsearchIndexAdvancedPage: React.FC<ComponentProps> = ({ clusters }) => {
|
||||
const globalState = useContext(GlobalStateContext);
|
||||
const { services } = useKibana<{ data: any }>();
|
||||
const { index }: { index: string } = useParams();
|
||||
const { zoomInfo, onBrush } = useCharts();
|
||||
const clusterUuid = globalState.cluster_uuid;
|
||||
const [data, setData] = useState({} as any);
|
||||
|
||||
const title = i18n.translate('xpack.monitoring.elasticsearch.index.advanced.title', {
|
||||
defaultMessage: 'Elasticsearch - Indices - {indexName} - Advanced',
|
||||
values: {
|
||||
indexName: index,
|
||||
},
|
||||
});
|
||||
|
||||
const getPageData = useCallback(async () => {
|
||||
const bounds = services.data?.query.timefilter.timefilter.getBounds();
|
||||
const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/indices/${index}`;
|
||||
const response = await services.http?.fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
timeRange: {
|
||||
min: bounds.min.toISOString(),
|
||||
max: bounds.max.toISOString(),
|
||||
},
|
||||
is_advanced: true,
|
||||
}),
|
||||
});
|
||||
setData(response);
|
||||
}, [clusterUuid, services.data?.query.timefilter.timefilter, services.http, index]);
|
||||
|
||||
return (
|
||||
<ItemTemplate title={title} getPageData={getPageData} id={index} pageType="indices">
|
||||
<SetupModeRenderer
|
||||
render={({ setupMode, flyoutComponent, bottomBarComponent }: SetupModeProps) => (
|
||||
<SetupModeContext.Provider value={{ setupModeSupported: true }}>
|
||||
{flyoutComponent}
|
||||
<AdvancedIndex
|
||||
setupMode={setupMode}
|
||||
alerts={{}}
|
||||
indexSummary={data.indexSummary}
|
||||
metrics={data.metrics}
|
||||
onBrush={onBrush}
|
||||
zoomInfo={zoomInfo}
|
||||
/>
|
||||
{bottomBarComponent}
|
||||
</SetupModeContext.Provider>
|
||||
)}
|
||||
/>
|
||||
</ItemTemplate>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React, { useContext, useState, useCallback } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { GlobalStateContext } from '../../global_state_context';
|
||||
// @ts-ignore
|
||||
import { IndexReact } from '../../../components/elasticsearch/index/index_react';
|
||||
import { ComponentProps } from '../../route_init';
|
||||
import { SetupModeRenderer } from '../../setup_mode/setup_mode_renderer';
|
||||
import { SetupModeContext } from '../../../components/setup_mode/setup_mode_context';
|
||||
import { useCharts } from '../../hooks/use_charts';
|
||||
import { ItemTemplate } from './item_template';
|
||||
// @ts-ignore
|
||||
import { indicesByNodes } from '../../../components/elasticsearch/shard_allocation/transformers/indices_by_nodes';
|
||||
// @ts-ignore
|
||||
import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels';
|
||||
|
||||
interface SetupModeProps {
|
||||
setupMode: any;
|
||||
flyoutComponent: any;
|
||||
bottomBarComponent: any;
|
||||
}
|
||||
|
||||
export const ElasticsearchIndexPage: React.FC<ComponentProps> = ({ clusters }) => {
|
||||
const globalState = useContext(GlobalStateContext);
|
||||
const { services } = useKibana<{ data: any }>();
|
||||
const { index }: { index: string } = useParams();
|
||||
const { zoomInfo, onBrush } = useCharts();
|
||||
const clusterUuid = globalState.cluster_uuid;
|
||||
const [data, setData] = useState({} as any);
|
||||
const [indexLabel, setIndexLabel] = useState(labels.index as any);
|
||||
const [nodesByIndicesData, setNodesByIndicesData] = useState([]);
|
||||
|
||||
const title = i18n.translate('xpack.monitoring.elasticsearch.index.overview.title', {
|
||||
defaultMessage: 'Elasticsearch - Indices - {indexName} - Overview',
|
||||
values: {
|
||||
indexName: index,
|
||||
},
|
||||
});
|
||||
|
||||
const pageTitle = i18n.translate('xpack.monitoring.elasticsearch.index.overview.pageTitle', {
|
||||
defaultMessage: 'Index: {indexName}',
|
||||
values: {
|
||||
indexName: index,
|
||||
},
|
||||
});
|
||||
|
||||
const getPageData = useCallback(async () => {
|
||||
const bounds = services.data?.query.timefilter.timefilter.getBounds();
|
||||
const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/indices/${index}`;
|
||||
const response = await services.http?.fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
timeRange: {
|
||||
min: bounds.min.toISOString(),
|
||||
max: bounds.max.toISOString(),
|
||||
},
|
||||
is_advanced: false,
|
||||
}),
|
||||
});
|
||||
setData(response);
|
||||
const transformer = indicesByNodes();
|
||||
setNodesByIndicesData(transformer(response.shards, response.nodes));
|
||||
|
||||
const shards = response.shards;
|
||||
if (shards.some((shard: any) => shard.state === 'UNASSIGNED')) {
|
||||
setIndexLabel(labels.indexWithUnassigned);
|
||||
}
|
||||
}, [clusterUuid, services.data?.query.timefilter.timefilter, services.http, index]);
|
||||
|
||||
return (
|
||||
<ItemTemplate
|
||||
title={title}
|
||||
pageTitle={pageTitle}
|
||||
getPageData={getPageData}
|
||||
id={index}
|
||||
pageType="indices"
|
||||
>
|
||||
<SetupModeRenderer
|
||||
render={({ setupMode, flyoutComponent, bottomBarComponent }: SetupModeProps) => (
|
||||
<SetupModeContext.Provider value={{ setupModeSupported: true }}>
|
||||
{flyoutComponent}
|
||||
<IndexReact
|
||||
setupMode={setupMode}
|
||||
labels={indexLabel}
|
||||
alerts={{}}
|
||||
onBrush={onBrush}
|
||||
indexUuid={index}
|
||||
clusterUuid={clusterUuid}
|
||||
zoomInfo={zoomInfo}
|
||||
nodesByIndices={nodesByIndicesData}
|
||||
{...data}
|
||||
/>
|
||||
{bottomBarComponent}
|
||||
</SetupModeContext.Provider>
|
||||
)}
|
||||
/>
|
||||
</ItemTemplate>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { PageTemplate } from '../page_template';
|
||||
import { TabMenuItem, PageTemplateProps } from '../page_template';
|
||||
|
||||
interface ItemTemplateProps extends PageTemplateProps {
|
||||
id: string;
|
||||
pageType: string;
|
||||
}
|
||||
export const ItemTemplate: React.FC<ItemTemplateProps> = (props) => {
|
||||
const { pageType, id, ...rest } = props;
|
||||
const tabs: TabMenuItem[] = [
|
||||
{
|
||||
id: 'overview',
|
||||
label: i18n.translate('xpack.monitoring.esItemNavigation.overviewLinkText', {
|
||||
defaultMessage: 'Overview',
|
||||
}),
|
||||
route: `/elasticsearch/${pageType}/${id}`,
|
||||
},
|
||||
{
|
||||
id: 'advanced',
|
||||
label: i18n.translate('xpack.monitoring.esItemNavigation.advancedLinkText', {
|
||||
defaultMessage: 'Advanced',
|
||||
}),
|
||||
route: `/elasticsearch/${pageType}/${id}/advanced`,
|
||||
},
|
||||
];
|
||||
|
||||
return <PageTemplate {...rest} tabs={tabs} product="elasticsearch" />;
|
||||
};
|
|
@ -7,8 +7,7 @@
|
|||
import React, { useContext, useState, useCallback } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { find } from 'lodash';
|
||||
import { ElasticsearchTemplate } from './elasticsearch_template';
|
||||
import { ItemTemplate } from './item_template';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { GlobalStateContext } from '../../global_state_context';
|
||||
import { NodeReact } from '../../../components/elasticsearch';
|
||||
|
@ -18,6 +17,8 @@ import { SetupModeContext } from '../../../components/setup_mode/setup_mode_cont
|
|||
import { useLocalStorage } from '../../hooks/use_local_storage';
|
||||
import { useCharts } from '../../hooks/use_charts';
|
||||
import { nodesByIndices } from '../../../components/elasticsearch/shard_allocation/transformers/nodes_by_indices';
|
||||
// @ts-ignore
|
||||
import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels';
|
||||
|
||||
interface SetupModeProps {
|
||||
setupMode: any;
|
||||
|
@ -38,9 +39,6 @@ export const ElasticsearchNodePage: React.FC<ComponentProps> = ({ clusters }) =>
|
|||
|
||||
const clusterUuid = globalState.cluster_uuid;
|
||||
const ccs = globalState.ccs;
|
||||
const cluster = find(clusters, {
|
||||
cluster_uuid: clusterUuid,
|
||||
});
|
||||
const [data, setData] = useState({} as any);
|
||||
const [nodesByIndicesData, setNodesByIndicesData] = useState([]);
|
||||
|
||||
|
@ -92,33 +90,33 @@ export const ElasticsearchNodePage: React.FC<ComponentProps> = ({ clusters }) =>
|
|||
}, [showSystemIndices, setShowSystemIndices]);
|
||||
|
||||
return (
|
||||
<ElasticsearchTemplate
|
||||
<ItemTemplate
|
||||
title={title}
|
||||
pageTitle={pageTitle}
|
||||
getPageData={getPageData}
|
||||
cluster={cluster}
|
||||
id={node}
|
||||
pageType="nodes"
|
||||
>
|
||||
<div data-test-subj="elasticsearchNodeListingPage">
|
||||
<SetupModeRenderer
|
||||
render={({ setupMode, flyoutComponent, bottomBarComponent }: SetupModeProps) => (
|
||||
<SetupModeContext.Provider value={{ setupModeSupported: true }}>
|
||||
{flyoutComponent}
|
||||
<NodeReact
|
||||
alerts={{}}
|
||||
nodeId={node}
|
||||
clusterUuid={clusterUuid}
|
||||
onBrush={onBrush}
|
||||
zoomInfo={zoomInfo}
|
||||
toggleShowSystemIndices={toggleShowSystemIndices}
|
||||
showSystemIndices={showSystemIndices}
|
||||
nodesByIndices={nodesByIndicesData}
|
||||
{...data}
|
||||
/>
|
||||
{bottomBarComponent}
|
||||
</SetupModeContext.Provider>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</ElasticsearchTemplate>
|
||||
<SetupModeRenderer
|
||||
render={({ setupMode, flyoutComponent, bottomBarComponent }: SetupModeProps) => (
|
||||
<SetupModeContext.Provider value={{ setupModeSupported: true }}>
|
||||
{flyoutComponent}
|
||||
<NodeReact
|
||||
alerts={{}}
|
||||
labels={labels.node}
|
||||
nodeId={node}
|
||||
clusterUuid={clusterUuid}
|
||||
onBrush={onBrush}
|
||||
zoomInfo={zoomInfo}
|
||||
toggleShowSystemIndices={toggleShowSystemIndices}
|
||||
showSystemIndices={showSystemIndices}
|
||||
nodesByIndices={nodesByIndicesData}
|
||||
{...data}
|
||||
/>
|
||||
{bottomBarComponent}
|
||||
</SetupModeContext.Provider>
|
||||
)}
|
||||
/>
|
||||
</ItemTemplate>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiPage,
|
||||
EuiPageContent,
|
||||
EuiPageBody,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
EuiFlexGrid,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
import { IndexDetailStatus } from '../index_detail_status';
|
||||
import { MonitoringTimeseriesContainer } from '../../chart';
|
||||
import { ShardAllocationReact } from '../shard_allocation/shard_allocation_react';
|
||||
import { Logs } from '../../logs';
|
||||
import { AlertsCallout } from '../../../alerts/callout';
|
||||
|
||||
export const IndexReact = ({
|
||||
indexSummary,
|
||||
metrics,
|
||||
clusterUuid,
|
||||
indexUuid,
|
||||
logs,
|
||||
alerts,
|
||||
...props
|
||||
}) => {
|
||||
const metricsToShow = [
|
||||
metrics.index_mem,
|
||||
metrics.index_size,
|
||||
metrics.index_search_request_rate,
|
||||
metrics.index_request_rate,
|
||||
metrics.index_segment_count,
|
||||
metrics.index_document_count,
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiPage>
|
||||
<EuiPageBody>
|
||||
<EuiPanel>
|
||||
<IndexDetailStatus stats={indexSummary} alerts={alerts} />
|
||||
</EuiPanel>
|
||||
<EuiSpacer size="m" />
|
||||
<AlertsCallout alerts={alerts} />
|
||||
<EuiSpacer size="m" />
|
||||
<EuiPageContent>
|
||||
<EuiFlexGrid columns={2} gutterSize="s">
|
||||
{metricsToShow.map((metric, index) => (
|
||||
<EuiFlexItem key={index}>
|
||||
<MonitoringTimeseriesContainer series={metric} {...props} />
|
||||
<EuiSpacer />
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiPanel>
|
||||
<Logs logs={logs} indexUuid={indexUuid} clusterUuid={clusterUuid} />
|
||||
</EuiPanel>
|
||||
<EuiSpacer size="m" />
|
||||
<ShardAllocationReact {...props} />
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
);
|
||||
};
|
|
@ -8,13 +8,12 @@
|
|||
import React from 'react';
|
||||
import { TableHeadReact } from './table_head_react';
|
||||
import { TableBody } from './table_body';
|
||||
import { labels } from '../lib/labels';
|
||||
|
||||
export const ClusterViewReact = (props) => {
|
||||
return (
|
||||
<table cellPadding="0" cellSpacing="0" className="table">
|
||||
<TableHeadReact
|
||||
labels={labels.node}
|
||||
labels={props.labels}
|
||||
toggleShowSystemIndices={props.toggleShowSystemIndices}
|
||||
showSystemIndices={props.showSystemIndices}
|
||||
/>
|
||||
|
@ -22,7 +21,7 @@ export const ClusterViewReact = (props) => {
|
|||
filter={props.filter}
|
||||
totalCount={props.totalCount}
|
||||
rows={props.nodesByIndices}
|
||||
cols={labels.node.length}
|
||||
cols={props.labels.length}
|
||||
shardStats={props.shardStats}
|
||||
/>
|
||||
</table>
|
||||
|
|
Loading…
Reference in a new issue