-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Stack Monitoring][Angular removal] No-data page (#110432)
* Basic no-data page * Rename to NoDataPage * Add getData property to pass into EuiSuperDatePicker from pages * Wire getData and redirect for no data page * Draft port of isLoading & model updating * Add todo on handling checkers * Switch to model as state object * Add checkers * Porting enabler * Fix build checks * Attempting to smooth out enablement * Clean up CI errors * Fix breadcrumbs * Fix linter warning * Fix checkers dependency (I hope) * Hook up catchReason * Add a stub for react setup mode * Clean warnings * Fix toggleSetupMode by calling initSetupModeState first * Translating checker strings * typo on "xpack" * Move isCollection/reason check in NoData This replicates how the angular app did selective re-rendering of the react component, but while still being able to render the component. Co-authored-by: Kibana Machine <[email protected]>
- Loading branch information
1 parent
fd0f423
commit d37ad90
Showing
6 changed files
with
311 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
x-pack/plugins/monitoring/public/application/pages/no_data/enabler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
// From x-pack/plugins/monitoring/public/lib/elasticsearch_settings/enabler.js | ||
export class Enabler { | ||
http: any; | ||
updateModel: any; | ||
|
||
constructor(http: any, updateModel: (properties: any) => void) { | ||
this.http = http; | ||
this.updateModel = updateModel; | ||
} | ||
|
||
async enableCollectionInterval() { | ||
try { | ||
this.updateModel({ isCollectionIntervalUpdating: true }); | ||
|
||
await this.http.fetch('../api/monitoring/v1/elasticsearch_settings/set/collection_interval', { | ||
method: 'PUT', | ||
}); | ||
this.updateModel({ | ||
isCollectionIntervalUpdated: true, | ||
isCollectionIntervalUpdating: false, | ||
}); | ||
} catch (err) { | ||
this.updateModel({ | ||
errors: (err as any).data, | ||
isCollectionIntervalUpdated: false, | ||
isCollectionIntervalUpdating: false, | ||
}); | ||
} | ||
} | ||
|
||
async enableCollectionEnabled() { | ||
try { | ||
this.updateModel({ isCollectionEnabledUpdating: true }); | ||
await this.http.fetch('../api/monitoring/v1/elasticsearch_settings/set/collection_enabled', { | ||
method: 'PUT', | ||
}); | ||
|
||
this.updateModel({ | ||
isCollectionEnabledUpdated: true, | ||
isCollectionEnabledUpdating: false, | ||
}); | ||
} catch (err) { | ||
this.updateModel({ | ||
errors: (err as any).data, | ||
isCollectionEnabledUpdated: false, | ||
isCollectionEnabledUpdating: false, | ||
}); | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
x-pack/plugins/monitoring/public/application/pages/no_data/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
export { NoDataPage } from './no_data_page'; |
240 changes: 240 additions & 0 deletions
240
x-pack/plugins/monitoring/public/application/pages/no_data/no_data_page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
/* | ||
* 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, { useCallback, useContext, useState } from 'react'; | ||
import { Redirect } from 'react-router-dom'; | ||
|
||
import { i18n } from '@kbn/i18n'; | ||
// @ts-ignore | ||
import { NoData } from '../../../components/no_data'; | ||
import { PageTemplate } from '../page_template'; | ||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; | ||
import { CODE_PATH_LICENSE, STANDALONE_CLUSTER_CLUSTER_UUID } from '../../../../common/constants'; | ||
import { Legacy } from '../../../legacy_shims'; | ||
import { Enabler } from './enabler'; | ||
import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs'; | ||
import { initSetupModeState } from '../../setup_mode/setup_mode'; | ||
import { GlobalStateContext } from '../../global_state_context'; | ||
|
||
const CODE_PATHS = [CODE_PATH_LICENSE]; | ||
|
||
interface NoDataPageSetupDeps { | ||
http: any; | ||
data: any; | ||
} | ||
|
||
interface SettingsChecker { | ||
message: string; | ||
api: string; | ||
next?: SettingsChecker; | ||
} | ||
|
||
const clusterCheckers: SettingsChecker[] = [ | ||
{ | ||
message: i18n.translate('xpack.monitoring.noData.checker.clusterSettings', { | ||
defaultMessage: 'Checking cluster settings API on production cluster', | ||
}), | ||
api: '../api/monitoring/v1/elasticsearch_settings/check/cluster', | ||
}, | ||
{ | ||
message: i18n.translate('xpack.monitoring.noData.checker.nodesSettings', { | ||
defaultMessage: 'Checking nodes settings API on production cluster', | ||
}), | ||
api: '../api/monitoring/v1/elasticsearch_settings/check/nodes', | ||
}, | ||
]; | ||
|
||
export const NoDataPage = () => { | ||
const title = i18n.translate('xpack.monitoring.noData.routeTitle', { | ||
defaultMessage: 'Setup Monitoring', | ||
}); | ||
|
||
const { services } = useKibana<NoDataPageSetupDeps>(); | ||
const [shouldRedirect, setShouldRedirect] = useState(false); | ||
|
||
const [model, setModel] = useState({ | ||
errors: [], // errors can happen from trying to check or set ES settings | ||
checkMessage: null, // message to show while waiting for api response | ||
isLoading: true, // flag for in-progress state of checking for no data reason | ||
isCollectionEnabledUpdating: false, // flags to indicate whether to show a spinner while waiting for ajax | ||
isCollectionEnabledUpdated: false, | ||
isCollectionIntervalUpdating: false, | ||
isCollectionIntervalUpdated: false, | ||
} as any); | ||
|
||
const { update: updateBreadcrumbs } = useContext(BreadcrumbContainer.Context); | ||
updateBreadcrumbs([ | ||
{ | ||
'data-test-subj': 'breadcrumbClusters', | ||
text: 'Clusters', | ||
href: '#/home', | ||
ignoreGlobalState: true, | ||
}, | ||
]); | ||
|
||
const globalState = useContext(GlobalStateContext); | ||
initSetupModeState(globalState, services.http); | ||
|
||
// From x-pack/plugins/monitoring/public/views/no_data/model_updater.js | ||
const updateModel = useCallback( | ||
(properties: any) => { | ||
setModel((previousModel: any) => { | ||
const updated = { ...previousModel }; | ||
const keys = Object.keys(properties); | ||
|
||
keys.forEach((key) => { | ||
if (Array.isArray(updated[key])) { | ||
updated[key].push(properties[key]); | ||
} else { | ||
updated[key] = properties[key]; | ||
} | ||
}); | ||
|
||
return updated; | ||
}); | ||
}, | ||
[setModel] | ||
); | ||
|
||
const getPageData = useCallback(async () => { | ||
let catchReason; | ||
try { | ||
const clusters = await getClusters(services); | ||
|
||
if (clusters && clusters.length) { | ||
setShouldRedirect(true); | ||
return; | ||
} | ||
} catch (err) { | ||
if (err && err.status === 503) { | ||
catchReason = { | ||
property: 'custom', | ||
message: err.data.message, | ||
}; | ||
} | ||
} | ||
|
||
if (catchReason) { | ||
updateModel({ reason: catchReason }); | ||
} else { | ||
await startChecks(clusterCheckers, services.http, updateModel); | ||
} | ||
}, [services, updateModel]); | ||
|
||
const enabler = new Enabler(services.http, updateModel); | ||
|
||
return ( | ||
<PageTemplate title={title} getPageData={getPageData}> | ||
{shouldRedirect ? ( | ||
<Redirect to="/home" /> | ||
) : ( | ||
<NoData {...model} enabler={enabler} isCloudEnabled={Legacy.shims.isCloud} /> | ||
)} | ||
</PageTemplate> | ||
); | ||
}; | ||
|
||
async function getClusters(services: NoDataPageSetupDeps): Promise<any[]> { | ||
const url = '../api/monitoring/v1/clusters'; | ||
const bounds = services.data?.query.timefilter.timefilter.getBounds(); | ||
const min = bounds.min.toISOString(); | ||
const max = bounds.max.toISOString(); | ||
|
||
const response = await services.http?.fetch(url, { | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
css: undefined, | ||
timeRange: { | ||
min, | ||
max, | ||
}, | ||
codePaths: CODE_PATHS, | ||
}), | ||
}); | ||
|
||
return formatClusters(response); | ||
} | ||
|
||
// From x-pack/plugins/monitoring/public/lib/elasticsearch_settings/start_checks.js | ||
const mapCheckers = (_checkers: SettingsChecker[]) => { | ||
return _checkers.map((current, checkerIndex) => { | ||
const next = _checkers[checkerIndex + 1]; | ||
if (next !== undefined) { | ||
current.next = next; | ||
} | ||
|
||
return current; | ||
}); | ||
}; | ||
|
||
// From x-pack/plugins/monitoring/public/lib/elasticsearch_settings/start_checks.js | ||
function startChecks( | ||
checkers: SettingsChecker[], | ||
http: { fetch: any }, | ||
updateModel: (properties: any) => void | ||
) { | ||
const runCheck = async (currentChecker: SettingsChecker): Promise<any> => { | ||
updateModel({ checkMessage: currentChecker.message }); | ||
|
||
const { found, reason, error, errorReason } = await executeCheck(currentChecker, http); | ||
|
||
if (error) { | ||
updateModel({ errors: errorReason }); | ||
if (currentChecker.next) { | ||
return runCheck(currentChecker.next); | ||
} | ||
} else if (found) { | ||
return updateModel({ | ||
reason, | ||
isLoading: false, | ||
checkMessage: null, | ||
}); | ||
} else if (currentChecker.next) { | ||
return runCheck(currentChecker.next); | ||
} | ||
|
||
// dead end | ||
updateModel({ | ||
reason: null, | ||
isLoading: false, | ||
checkMessage: null, | ||
}); | ||
}; | ||
|
||
const _checkers = mapCheckers(checkers); | ||
return runCheck(_checkers[0]); | ||
} | ||
|
||
async function executeCheck(checker: SettingsChecker, http: { fetch: any }): Promise<any> { | ||
try { | ||
const response = await http.fetch(checker.api, { | ||
method: 'GET', | ||
}); | ||
const { found, reason } = response; | ||
|
||
return { found, reason }; | ||
} catch (err: any) { | ||
const { data } = err; | ||
|
||
return { | ||
error: true, | ||
found: false, | ||
errorReason: data, | ||
}; | ||
} | ||
} | ||
|
||
function formatClusters(clusters: any): any[] { | ||
return clusters.map(formatCluster); | ||
} | ||
|
||
function formatCluster(cluster: any) { | ||
if (cluster.cluster_uuid === STANDALONE_CLUSTER_CLUSTER_UUID) { | ||
cluster.cluster_name = 'Standalone Cluster'; | ||
} | ||
return cluster; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters