Skip to content
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

Merged
merged 31 commits into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3436b35
Basic no-data page
matschaffer Aug 30, 2021
9d8b938
Rename to NoDataPage
matschaffer Aug 31, 2021
59f04bd
Merge branch 'master' into no-data-page-migration
kibanamachine Aug 31, 2021
0d1963a
Merge remote-tracking branch 'upstream/master' into no-data-page-migr…
matschaffer Sep 1, 2021
fe56aaf
Add getData property to pass into EuiSuperDatePicker from pages
matschaffer Sep 1, 2021
bcd68ad
Wire getData and redirect for no data page
matschaffer Sep 1, 2021
a63c210
Merge remote-tracking branch 'upstream/master' into no-data-page-migr…
matschaffer Sep 6, 2021
b13375c
Merge remote-tracking branch 'upstream/master' into no-data-page-migr…
matschaffer Sep 8, 2021
4cf97bf
Draft port of isLoading & model updating
matschaffer Sep 8, 2021
14cfc03
Add todo on handling checkers
matschaffer Sep 8, 2021
aa5a9ba
Merge branch 'master' into no-data-page-migration
kibanamachine Sep 10, 2021
01938a9
Switch to model as state object
matschaffer Sep 10, 2021
cfac638
Add checkers
matschaffer Sep 10, 2021
bac9264
Porting enabler
matschaffer Sep 10, 2021
4aac00b
Fix build checks
matschaffer Sep 10, 2021
dd5d735
Attempting to smooth out enablement
matschaffer Sep 10, 2021
6efd0c6
Clean up CI errors
matschaffer Sep 10, 2021
03bae1c
Merge remote-tracking branch 'upstream/master' into no-data-page-migr…
matschaffer Sep 14, 2021
dccaaa7
Fix breadcrumbs
matschaffer Sep 14, 2021
9183221
Fix linter warning
matschaffer Sep 14, 2021
0156e3c
Fix checkers dependency (I hope)
matschaffer Sep 14, 2021
2cf8005
Hook up catchReason
matschaffer Sep 14, 2021
c8f01b7
Add a stub for react setup mode
matschaffer Sep 14, 2021
c371ed2
Clean warnings
matschaffer Sep 14, 2021
6b7908c
Fix toggleSetupMode by calling initSetupModeState first
matschaffer Sep 15, 2021
8a62652
Merge branch 'master' into no-data-page-migration
kibanamachine Sep 15, 2021
ad924d8
Merge remote-tracking branch 'upstream/master' into no-data-page-migr…
matschaffer Sep 16, 2021
ee89f73
Merge branch 'master' into no-data-page-migration
kibanamachine Sep 21, 2021
93f866c
Translating checker strings
matschaffer Sep 21, 2021
917bf43
typo on "xpack"
matschaffer Sep 21, 2021
3987326
Move isCollection/reason check in NoData
matschaffer Sep 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions x-pack/plugins/monitoring/public/application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ExternalConfigContext, ExternalConfig } from './external_config_context
import { createPreserveQueryHistory } from './preserve_query_history';
import { RouteInit } from './route_init';
import { MonitoringTimeContainer } from './pages/use_monitoring_time';
import { NoDataPage } from './pages/no_data_page';

export const renderApp = (
core: CoreStart,
Expand Down Expand Up @@ -50,7 +51,7 @@ const MonitoringApp: React.FC<{
<MonitoringTimeContainer.Provider>
<Router history={history}>
<Switch>
<Route path="/no-data" component={NoData} />
<Route path="/no-data" component={NoDataPage} />
<Route path="/loading" component={LoadingPage} />
<RouteInit
path="/license"
Expand Down Expand Up @@ -85,10 +86,6 @@ const MonitoringApp: React.FC<{
);
};

const NoData: React.FC<{}> = () => {
return <div>No data page</div>;
};

const Home: React.FC<{}> = () => {
return <div>Home page (Cluster listing)</div>;
};
180 changes: 180 additions & 0 deletions x-pack/plugins/monitoring/public/application/pages/no_data_page.tsx
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,
};
Copy link
Contributor

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

Copy link
Contributor Author

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).


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);
Copy link
Contributor

@estermv estermv Sep 8, 2021

Choose a reason for hiding this comment

The 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
const { updateModel } = new ModelUpdater(model);
const enabler = new Enabler(updateModel);
const updateModel = (properties) => {
setModel({
...model,
...properties
})
}
const enabler = new Enabler(updateModel);

EDIT: setModel is not that simple... I didn't see that errors is an array

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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];
}
});
}
}