-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Stack monitoring] No-data page #110432
[Stack monitoring] No-data page #110432
Changes from 10 commits
3436b35
9d8b938
59f04bd
0d1963a
fe56aaf
bcd68ad
a63c210
b13375c
4cf97bf
14cfc03
aa5a9ba
01938a9
cfac638
bac9264
4aac00b
dd5d735
6efd0c6
03bae1c
dccaaa7
9183221
0156e3c
2cf8005
c8f01b7
c371ed2
6b7908c
8a62652
ad924d8
ee89f73
93f866c
917bf43
3987326
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,180 @@ | ||||||||||||||||||||
/* | ||||||||||||||||||||
* 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 { GlobalStateContext } from '../global_state_context'; | ||||||||||||||||||||
|
||||||||||||||||||||
const CODE_PATHS = [CODE_PATH_LICENSE]; | ||||||||||||||||||||
|
||||||||||||||||||||
export const NoDataPage = () => { | ||||||||||||||||||||
const title = i18n.translate('xpack.monitoring.noData.routeTitle', { | ||||||||||||||||||||
defaultMessage: 'Setup Monitoring', | ||||||||||||||||||||
}); | ||||||||||||||||||||
|
||||||||||||||||||||
const { services } = useKibana<{ data: any }>(); | ||||||||||||||||||||
|
||||||||||||||||||||
const state = useContext(GlobalStateContext); | ||||||||||||||||||||
const clusterUuid = state.cluster_uuid; | ||||||||||||||||||||
const ccs = state.ccs; | ||||||||||||||||||||
|
||||||||||||||||||||
const [shouldRedirect, setShouldRedirect] = useState(false); | ||||||||||||||||||||
const [isLoading, setIsLoading] = useState(true); | ||||||||||||||||||||
|
||||||||||||||||||||
// TODO work on porting these checkers over | ||||||||||||||||||||
// const checkers = [new ClusterSettingsChecker($http), new NodeSettingsChecker($http)]; | ||||||||||||||||||||
// await startChecks(checkers, updateModel); | ||||||||||||||||||||
|
||||||||||||||||||||
const model = { | ||||||||||||||||||||
errors: [], // errors can happen from trying to check or set ES settings | ||||||||||||||||||||
checkMessage: null, // message to show while waiting for api response | ||||||||||||||||||||
isLoading: isLoading, // 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, | ||||||||||||||||||||
}; | ||||||||||||||||||||
|
||||||||||||||||||||
const getPageData = useCallback(async () => { | ||||||||||||||||||||
setIsLoading(true); | ||||||||||||||||||||
const bounds = services.data?.query.timefilter.timefilter.getBounds(); | ||||||||||||||||||||
const min = bounds.min.toISOString(); | ||||||||||||||||||||
const max = bounds.max.toISOString(); | ||||||||||||||||||||
|
||||||||||||||||||||
const url = '../api/monitoring/v1/clusters'; | ||||||||||||||||||||
|
||||||||||||||||||||
try { | ||||||||||||||||||||
const response = await services.http?.fetch(url, { | ||||||||||||||||||||
method: 'POST', | ||||||||||||||||||||
body: JSON.stringify({ | ||||||||||||||||||||
css: undefined, | ||||||||||||||||||||
timeRange: { | ||||||||||||||||||||
min, | ||||||||||||||||||||
max, | ||||||||||||||||||||
}, | ||||||||||||||||||||
codePaths: CODE_PATHS, | ||||||||||||||||||||
}), | ||||||||||||||||||||
}); | ||||||||||||||||||||
|
||||||||||||||||||||
const clusters = formatClusters(response); | ||||||||||||||||||||
setIsLoading(false); | ||||||||||||||||||||
console.log('did a refresh from nodatapage'); | ||||||||||||||||||||
|
||||||||||||||||||||
if (clusters && clusters.length) { | ||||||||||||||||||||
setShouldRedirect(true); | ||||||||||||||||||||
} | ||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||
// TODO something useful with the error reason | ||||||||||||||||||||
// if (err && err.status === 503) { | ||||||||||||||||||||
// catchReason = { | ||||||||||||||||||||
// property: 'custom', | ||||||||||||||||||||
// message: err.data.message, | ||||||||||||||||||||
// }; | ||||||||||||||||||||
// } | ||||||||||||||||||||
console.log(err); | ||||||||||||||||||||
} | ||||||||||||||||||||
}, [ccs, clusterUuid, services.data?.query.timefilter.timefilter, services.http, setIsLoading]); | ||||||||||||||||||||
|
||||||||||||||||||||
const { updateModel } = new ModelUpdater(model); | ||||||||||||||||||||
const enabler = new Enabler(updateModel); | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need the ModelUpdater class, if we make the model part of the state of the component, we could do something like this:
Suggested change
EDIT: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIce, thanks! I'll try out model as a state object and see show that goes. |
||||||||||||||||||||
|
||||||||||||||||||||
return ( | ||||||||||||||||||||
<PageTemplate title={title} getPageData={getPageData}> | ||||||||||||||||||||
{shouldRedirect ? ( | ||||||||||||||||||||
<Redirect to="/home" /> | ||||||||||||||||||||
) : ( | ||||||||||||||||||||
<NoData {...model} enabler={enabler} isCloudEnabled={Legacy.shims.isCloud} /> | ||||||||||||||||||||
)} | ||||||||||||||||||||
</PageTemplate> | ||||||||||||||||||||
); | ||||||||||||||||||||
}; | ||||||||||||||||||||
|
||||||||||||||||||||
function formatClusters(clusters: any) { | ||||||||||||||||||||
return clusters.map(formatCluster); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
function formatCluster(cluster: any) { | ||||||||||||||||||||
if (cluster.cluster_uuid === STANDALONE_CLUSTER_CLUSTER_UUID) { | ||||||||||||||||||||
cluster.cluster_name = 'Standalone Cluster'; | ||||||||||||||||||||
} | ||||||||||||||||||||
return cluster; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
// From x-pack/plugins/monitoring/public/lib/elasticsearch_settings/enabler.js | ||||||||||||||||||||
class Enabler { | ||||||||||||||||||||
updateModel: any; | ||||||||||||||||||||
|
||||||||||||||||||||
constructor(updateModel: (properties: any) => void) { | ||||||||||||||||||||
this.updateModel = updateModel; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
async enableCollectionInterval() { | ||||||||||||||||||||
try { | ||||||||||||||||||||
this.updateModel({ isCollectionIntervalUpdating: true }); | ||||||||||||||||||||
// TODO actually set it | ||||||||||||||||||||
// await this.$http.put('../api/monitoring/v1/elasticsearch_settings/set/collection_interval'); | ||||||||||||||||||||
this.updateModel({ | ||||||||||||||||||||
isCollectionIntervalUpdated: true, | ||||||||||||||||||||
isCollectionIntervalUpdating: false, | ||||||||||||||||||||
}); | ||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||
this.updateModel({ | ||||||||||||||||||||
errors: err.data, | ||||||||||||||||||||
isCollectionIntervalUpdated: false, | ||||||||||||||||||||
isCollectionIntervalUpdating: false, | ||||||||||||||||||||
}); | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
async enableCollectionEnabled() { | ||||||||||||||||||||
try { | ||||||||||||||||||||
this.updateModel({ isCollectionEnabledUpdating: true }); | ||||||||||||||||||||
// TODO actually set it | ||||||||||||||||||||
// await this.$http.put('../api/monitoring/v1/elasticsearch_settings/set/collection_enabled'); | ||||||||||||||||||||
this.updateModel({ | ||||||||||||||||||||
isCollectionEnabledUpdated: true, | ||||||||||||||||||||
isCollectionEnabledUpdating: false, | ||||||||||||||||||||
}); | ||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||
this.updateModel({ | ||||||||||||||||||||
errors: err.data, | ||||||||||||||||||||
isCollectionEnabledUpdated: false, | ||||||||||||||||||||
isCollectionEnabledUpdating: false, | ||||||||||||||||||||
}); | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
// From x-pack/plugins/monitoring/public/views/no_data/model_updater.js | ||||||||||||||||||||
class ModelUpdater { | ||||||||||||||||||||
model: any; | ||||||||||||||||||||
|
||||||||||||||||||||
constructor(model: any) { | ||||||||||||||||||||
this.model = model; | ||||||||||||||||||||
this.updateModel = this.updateModel.bind(this); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
updateModel(properties: any) { | ||||||||||||||||||||
const model = this.model; | ||||||||||||||||||||
const keys = Object.keys(properties); | ||||||||||||||||||||
keys.forEach((key) => { | ||||||||||||||||||||
if (Array.isArray(model[key])) { | ||||||||||||||||||||
model[key].push(properties[key]); | ||||||||||||||||||||
} else { | ||||||||||||||||||||
model[key] = properties[key]; | ||||||||||||||||||||
} | ||||||||||||||||||||
}); | ||||||||||||||||||||
} | ||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be part of the state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks! I was thinking the same but not sure if it should be one state object or discrete state variables for each (like I did with isLoading).