[Monitoring] Stop a new request when one is inflight (#27253)

* Convert all pages to use the base controlller, then add logic in there to stop a new request when one is inflight

* Reuse the promise

* Undo logstash changes

* Update in catch too

* Add unit test

* Fix cluster name showing up

* Update broken test

* Just use updateDataPromise
This commit is contained in:
Chris Roberson 2018-12-17 14:38:21 -05:00 committed by GitHub
parent 08fd427125
commit faa57fd7a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 355 additions and 446 deletions

View file

@ -18,9 +18,9 @@ import { MonitoringTimeseriesContainer } from '../../chart';
import { ShardAllocation } from '../shard_allocation/shard_allocation';
export const Index = ({
scope,
indexSummary,
metrics,
scope,
kbnUrl,
...props
}) => {
@ -51,7 +51,7 @@ export const Index = ({
))}
</EuiFlexGrid>
<EuiSpacer size="m"/>
<ShardAllocation scope={scope} kbnUrl={kbnUrl} type="index" />
<ShardAllocation scope={scope} {...props} kbnUrl={kbnUrl} type="index" />
</EuiPageContent>
</EuiPageBody>
</EuiPage>

View file

@ -21,6 +21,10 @@ function DetailStatusUI({ stats, intl }) {
const metrics = [
{
label: intl.formatMessage({
id: 'xpack.monitoring.kibana.detailStatus.transportAddressLabel',
defaultMessage: 'Transport Address'
}),
value: transportAddress,
'data-test-subj': 'transportAddress'
},

View file

@ -22,6 +22,9 @@ function DetailStatusUi({ stats, intl }) {
const firstMetrics = [
{
label: intl.formatMessage({
id: 'xpack.monitoring.logstash.detailStatus.transportAddressLabel', defaultMessage: 'Transport Address'
}),
value: httpAddress,
'data-test-subj': 'httpAddress'
},

View file

@ -7,7 +7,6 @@
import './main';
import './chart';
import './sparkline';
import './cluster/overview';
import './cluster/listing';
import './elasticsearch/cluster_status';
import './elasticsearch/index_summary';

View file

@ -1,40 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import { Overview } from 'plugins/monitoring/components/cluster/overview';
import { uiModules } from 'ui/modules';
import { I18nProvider } from '@kbn/i18n/react';
const uiModule = uiModules.get('monitoring/directives', []);
uiModule.directive('monitoringClusterOverview', (kbnUrl, showLicenseExpiration) => {
return {
restrict: 'E',
scope: { cluster: '=' },
link(scope, $el) {
const changeUrl = target => {
scope.$evalAsync(() => {
kbnUrl.changePath(target);
});
};
scope.$watch('cluster', cluster => {
ReactDOM.render((
<I18nProvider>
<Overview
cluster={cluster}
changeUrl={changeUrl}
showLicenseExpiration={showLicenseExpiration}
/>
</I18nProvider>
), $el[0]);
});
}
};
});

View file

@ -253,7 +253,7 @@
</div>
<div ng-if="monitoringMain.inOverview" class="kuiLocalTabs" role="navigation">
<a class="kuiLocalTab" data-test-subj="clusterName">{{ cluster.cluster_name }}</a>
<a class="kuiLocalTab" data-test-subj="clusterName">{{ pageData.cluster_name }}</a>
</div>
<div ng-if="monitoringMain.inAlerts" class="kuiLocalTabs" role="navigation">

View file

@ -101,6 +101,8 @@ uiModule.directive('monitoringMain', (breadcrumbs, license, kbnUrl, config) => {
clusterName: get(scope, 'cluster.cluster_name')
});
attributes.$observe('instance', instance => controller.instance = instance);
attributes.$observe('resolver', resolver => controller.resolver = resolver);
}
};
});

View file

@ -69,6 +69,25 @@ describe('MonitoringViewBaseController', function () {
expect(executorService.start.calledOnce).to.be(true);
});
it('does not allow for a new request if one is inflight', done => {
let counter = 0;
const opts = {
title: 'testo',
getPageData: () => Promise.resolve(++counter),
$injector,
$scope
};
const ctrl = new MonitoringViewBaseController(opts);
Promise.all([
ctrl.updateData(),
ctrl.updateData(),
]).then(() => {
expect(counter).to.be(1);
done();
});
});
describe('time filter', () => {
it('enables timepicker and auto refresh #1', () => {
expect(timefilter.isTimeRangeSelectorEnabled).to.be(true);

View file

@ -75,7 +75,7 @@ export class MonitoringViewBaseController {
titleService($scope.cluster, title);
this.data = { ...defaultData };
$scope.pageData = this.data = { ...defaultData };
this._isDataInitialized = false;
this.reactNodeId = reactNodeId;
@ -96,12 +96,22 @@ export class MonitoringViewBaseController {
timefilter.enableAutoRefreshSelector();
}
this.updateDataPromise = null;
this.updateData = () => {
if (this.updateDataPromise) {
// Do not sent another request if one is inflight
// See https://github.com/elastic/kibana/issues/24082
return this.updateDataPromise;
}
const _api = apiUrlFn ? apiUrlFn() : api;
return _getPageData($injector, _api)
return this.updateDataPromise = _getPageData($injector, _api)
.then(pageData => {
this._isDataInitialized = true; // render will replace loading screen with the react component
this.data = pageData; // update the view's data with the fetch result
$scope.pageData = this.data = pageData; // update the view's data with the fetch result
this.updateDataPromise = null;
})
.catch(() => {
this.updateDataPromise = null;
});
};
this.updateData();
@ -126,6 +136,8 @@ export class MonitoringViewBaseController {
mode: 'absolute'
});
};
this.setTitle = title => titleService($scope.cluster, title);
}
renderReact(component) {

View file

@ -1,3 +1,3 @@
<monitoring-main name="overview" data-test-subj="clusterOverviewContainer">
<monitoring-cluster-overview cluster="cluster"></monitoring-cluster-overview>
<div id="monitoringClusterOverviewApp"></div>
</monitoring-main>

View file

@ -3,11 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import uiRoutes from 'ui/routes';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { MonitoringViewBaseController } from '../../';
import { Overview } from 'plugins/monitoring/components/cluster/overview';
import { I18nProvider } from '@kbn/i18n/react';
uiRoutes.when('/overview', {
template,
@ -21,28 +23,40 @@ uiRoutes.when('/overview', {
return monitoringClusters(globalState.cluster_uuid, globalState.ccs);
}
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
const kbnUrl = $injector.get('kbnUrl');
const monitoringClusters = $injector.get('monitoringClusters');
const globalState = $injector.get('globalState');
const $route = $injector.get('$route');
$scope.cluster = $route.current.locals.cluster;
super({
title: i18n('xpack.monitoring.cluster.overviewTitle', {
defaultMessage: 'Overview'
}),
defaultData: {},
getPageData: () => monitoringClusters(globalState.cluster_uuid, globalState.ccs),
reactNodeId: 'monitoringClusterOverviewApp',
$scope,
$injector
});
const title = $injector.get('title');
title($scope.cluster, i18n('xpack.monitoring.cluster.overviewTitle', { defaultMessage: 'Overview' }));
const changeUrl = target => {
$scope.$evalAsync(() => {
kbnUrl.changePath(target);
});
};
const $executor = $injector.get('$executor');
const monitoringClusters = $injector.get('monitoringClusters');
const globalState = $injector.get('globalState');
$executor.register({
execute: () => monitoringClusters(globalState.cluster_uuid, globalState.ccs),
handleResponse(cluster) {
$scope.cluster = cluster;
}
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
$scope.$watch(() => this.data, data => {
this.renderReact(
<I18nProvider>
<Overview
cluster={data}
changeUrl={changeUrl}
showLicenseExpiration={true}
/>
</I18nProvider>
);
});
}
}
});

View file

@ -1,7 +1,7 @@
<monitoring-main
product="elasticsearch" name="indices"
instance="{{ indexName }}"
resolver="{{ indexName }}"
instance="{{ monitoringElasticsearchAdvancedIndexApp.indexName }}"
resolver="{{ monitoringElasticsearchAdvancedIndexApp.indexName }}"
page="advanced"
>
<div id="monitoringElasticsearchAdvancedIndexApp"></div>

View file

@ -8,8 +8,6 @@
* Controller for Advanced Index Detail
*/
import React from 'react';
import { render } from 'react-dom';
import { find } from 'lodash';
import uiRoutes from 'ui/routes';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
@ -17,7 +15,7 @@ import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { AdvancedIndex } from '../../../../components/elasticsearch/index/advanced';
import { I18nProvider } from '@kbn/i18n/react';
import moment from 'moment';
import { MonitoringViewBaseController } from '../../../base_controller';
function getPageData($injector) {
const globalState = $injector.get('globalState');
@ -51,57 +49,39 @@ uiRoutes.when('/elasticsearch/indices/:index/advanced', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controllerAs: 'monitoringElasticsearchAdvancedIndexApp',
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
const $route = $injector.get('$route');
const indexName = $route.current.params.index;
const $route = $injector.get('$route');
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.indexName = $route.current.params.index;
$scope.pageData = $route.current.locals.pageData;
super({
title: i18n('xpack.monitoring.elasticsearch.indices.advanced.routeTitle', {
defaultMessage: 'Elasticsearch - Indices - {indexName} - Advanced',
values: {
indexName,
}
}),
defaultData: {},
getPageData,
reactNodeId: 'monitoringElasticsearchAdvancedIndexApp',
$scope,
$injector
});
const title = $injector.get('title');
const routeTitle = i18n('xpack.monitoring.elasticsearch.indices.advanced.routeTitle', {
defaultMessage: 'Elasticsearch - Indices - {indexName} - Advanced',
values: {
indexName: $scope.indexName
}
});
this.indexName = indexName;
title($scope.cluster, routeTitle);
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
function onBrush({ xaxis }) {
timefilter.setTime({
from: moment(xaxis.from),
to: moment(xaxis.to),
mode: 'absolute',
$scope.$watch(() => this.data, data => {
this.renderReact(
<I18nProvider>
<AdvancedIndex
indexSummary={data.indexSummary}
metrics={data.metrics}
onBrush={this.onBrush}
/>
</I18nProvider>
);
});
}
this.renderReact = () => {
render(
<I18nProvider>
<AdvancedIndex
indexSummary={$scope.pageData.indexSummary}
metrics={$scope.pageData.metrics}
onBrush={onBrush}
/>
</I18nProvider>,
document.getElementById('monitoringElasticsearchAdvancedIndexApp')
);
};
$scope.$watch('pageData', this.renderReact);
}
});

View file

@ -1,8 +1,8 @@
<monitoring-main
product="elasticsearch"
name="indices"
instance="{{ indexName }}"
resolver="{{ indexName }}"
instance="{{ monitoringElasticsearchIndexApp.indexName }}"
resolver="{{ monitoringElasticsearchIndexApp.indexName }}"
page="overview"
>
<div id="monitoringElasticsearchIndexApp"></div>

View file

@ -8,9 +8,6 @@
* Controller for single index detail
*/
import React from 'react';
import { render } from 'react-dom';
import { find } from 'lodash';
import moment from 'moment';
import uiRoutes from 'ui/routes';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
@ -20,6 +17,7 @@ import { I18nProvider } from '@kbn/i18n/react';
import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels';
import { indicesByNodes } from '../../../components/elasticsearch/shard_allocation/transformers/indices_by_nodes';
import { Index } from '../../../components/elasticsearch/index/index';
import { MonitoringViewBaseController } from '../../base_controller';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -53,69 +51,55 @@ uiRoutes.when('/elasticsearch/indices/:index', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controllerAs: 'monitoringElasticsearchIndexApp',
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
const $route = $injector.get('$route');
const kbnUrl = $injector.get('kbnUrl');
const indexName = $route.current.params.index;
const $route = $injector.get('$route');
const kbnUrl = $injector.get('kbnUrl');
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.pageData = $route.current.locals.pageData;
$scope.indexName = $route.current.params.index;
super({
title: i18n('xpack.monitoring.elasticsearch.indices.overview.routeTitle', {
defaultMessage: 'Elasticsearch - Indices - {indexName} - Overview',
values: {
indexName,
}
}),
defaultData: {},
getPageData,
reactNodeId: 'monitoringElasticsearchIndexApp',
$scope,
$injector
});
const title = $injector.get('title');
const routeTitle = i18n('xpack.monitoring.elasticsearch.indices.overview.routeTitle', {
defaultMessage: 'Elasticsearch - Indices - {indexName} - Overview',
values: {
indexName: $scope.indexName
}
});
this.indexName = indexName;
const transformer = indicesByNodes();
title($scope.cluster, routeTitle);
$scope.$watch(() => this.data, data => {
if (!data || !data.shards) {
return;
}
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
const shards = data.shards;
data.totalCount = shards.length;
data.showing = transformer(shards, data.nodes);
if (shards.some((shard) => shard.state === 'UNASSIGNED')) {
data.labels = labels.indexWithUnassigned;
} else {
data.labels = labels.index;
}
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
function onBrush({ xaxis }) {
timefilter.setTime({
from: moment(xaxis.from),
to: moment(xaxis.to),
mode: 'absolute',
this.renderReact(
<I18nProvider>
<Index
scope={$scope}
kbnUrl={kbnUrl}
onBrush={this.onBrush}
{...data}
/>
</I18nProvider>
);
});
}
const transformer = indicesByNodes();
this.renderReact = () => {
const shards = $scope.pageData.shards;
$scope.totalCount = shards.length;
$scope.showing = transformer(shards, $scope.pageData.nodes);
if (shards.some((shard) => shard.state === 'UNASSIGNED')) {
$scope.labels = labels.indexWithUnassigned;
} else {
$scope.labels = labels.index;
}
render(
<I18nProvider>
<Index
scope={$scope}
kbnUrl={kbnUrl}
onBrush={onBrush}
{...$scope.pageData}
/>
</I18nProvider>,
document.getElementById('monitoringElasticsearchIndexApp')
);
};
$scope.$watch('pageData', this.renderReact);
}
});

View file

@ -8,8 +8,6 @@
* Controller for Advanced Node Detail
*/
import React from 'react';
import { render } from 'react-dom';
import { find } from 'lodash';
import uiRoutes from 'ui/routes';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
@ -17,7 +15,7 @@ import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { I18nProvider } from '@kbn/i18n/react';
import { AdvancedNode } from '../../../../components/elasticsearch/node/advanced';
import moment from 'moment';
import { MonitoringViewBaseController } from '../../../base_controller';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -51,58 +49,38 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
super({
defaultData: {},
getPageData,
reactNodeId: 'monitoringElasticsearchAdvancedNodeApp',
$scope,
$injector
});
const $route = $injector.get('$route');
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.pageData = $route.current.locals.pageData;
$scope.$watch(() => this.data, data => {
if (!data || !data.nodeSummary) {
return;
}
const title = $injector.get('title');
const routeTitle = i18n('xpack.monitoring.elasticsearch.node.advanced.routeTitle', {
defaultMessage: 'Elasticsearch - Nodes - {nodeSummaryName} - Advanced',
values: {
nodeSummaryName: $scope.pageData.nodeSummary.name
}
});
this.setTitle(i18n('xpack.monitoring.elasticsearch.node.advanced.routeTitle', {
defaultMessage: 'Elasticsearch - Nodes - {nodeSummaryName} - Advanced',
values: {
nodeSummaryName: data.nodeSummary.name
}
}));
title($scope.cluster, routeTitle);
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => {
$scope.pageData = response;
}
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
function onBrush({ xaxis }) {
timefilter.setTime({
from: moment(xaxis.from),
to: moment(xaxis.to),
mode: 'absolute',
this.renderReact(
<I18nProvider>
<AdvancedNode
nodeSummary={data.nodeSummary}
metrics={data.metrics}
onBrush={this.onBrush}
/>
</I18nProvider>
);
});
}
this.renderReact = () => {
render(
<I18nProvider>
<AdvancedNode
nodeSummary={$scope.pageData.nodeSummary}
metrics={$scope.pageData.metrics}
onBrush={onBrush}
/>
</I18nProvider>,
document.getElementById('monitoringElasticsearchAdvancedNodeApp')
);
};
$scope.$watch('pageData', this.renderReact);
}
});

View file

@ -1,11 +1,11 @@
<monitoring-main
product="elasticsearch"
name="nodes"
instance="{{ pageData.nodeSummary.name }}"
resolver="{{ pageData.nodeSummary.resolver }}"
instance="{{ monitoringElasticsearchNodeApp.nodeName }}"
resolver="{{ monitoringElasticsearchNodeApp.data.nodeSummary.resolver }}"
page="overview"
tab-icon-class="{{ pageData.nodeSummary.nodeTypeClass }}"
tab-icon-class="{{ pageData.nodeSummary.nodeTypeLabel }}"
tab-icon-class="{{ monitoringElasticsearchNodeApp.data.nodeSummary.nodeTypeClass }}"
tab-icon-class="{{ monitoringElasticsearchNodeApp.data.nodeSummary.nodeTypeLabel }}"
>
<div id="monitoringElasticsearchNodeApp"></div>
</monitoring-main>

View file

@ -8,18 +8,16 @@
* Controller for Node Detail
*/
import React from 'react';
import { render } from 'react-dom';
import { find, partial } from 'lodash';
import { partial } from 'lodash';
import uiRoutes from 'ui/routes';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import { getPageData } from './get_page_data';
import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { Node } from '../../../components/elasticsearch/node/node';
import { I18nProvider } from '@kbn/i18n/react';
import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels';
import { nodesByIndices } from '../../../components/elasticsearch/shard_allocation/transformers/nodes_by_indices';
import moment from 'moment';
import { MonitoringViewBaseController } from '../../base_controller';
uiRoutes.when('/elasticsearch/nodes/:node', {
template,
@ -30,78 +28,63 @@ uiRoutes.when('/elasticsearch/nodes/:node', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controllerAs: 'monitoringElasticsearchNodeApp',
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
const $route = $injector.get('$route');
const kbnUrl = $injector.get('kbnUrl');
const nodeName = $route.current.params.node;
const $route = $injector.get('$route');
const kbnUrl = $injector.get('kbnUrl');
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.pageData = $route.current.locals.pageData;
super({
title: i18n('xpack.monitoring.elasticsearch.node.overview.routeTitle', {
defaultMessage: 'Elasticsearch - Nodes - {nodeName} - Overview',
values: {
nodeName,
}
}),
defaultData: {},
getPageData,
reactNodeId: 'monitoringElasticsearchNodeApp',
$scope,
$injector
});
const title = $injector.get('title');
const routeTitle = i18n('xpack.monitoring.elasticsearch.node.overview.routeTitle', {
defaultMessage: 'Elasticsearch - Nodes - {nodeSummaryName} - Overview',
values: {
nodeSummaryName: $scope.pageData.nodeSummary.name
}
});
this.nodeName = nodeName;
title($scope.cluster, routeTitle);
const features = $injector.get('features');
const callPageData = partial(getPageData, $injector);
// show/hide system indices in shard allocation view
$scope.showSystemIndices = features.isEnabled('showSystemIndices', false);
$scope.toggleShowSystemIndices = (isChecked) => {
$scope.showSystemIndices = isChecked;
// preserve setting in localStorage
features.update('showSystemIndices', isChecked);
// update the page
callPageData().then(data => this.data = data);
};
const features = $injector.get('features');
const callPageData = partial(getPageData, $injector);
// show/hide system indices in shard allocation view
$scope.showSystemIndices = features.isEnabled('showSystemIndices', false);
$scope.toggleShowSystemIndices = (isChecked) => {
$scope.showSystemIndices = isChecked;
// preserve setting in localStorage
features.update('showSystemIndices', isChecked);
// update the page
callPageData().then((pageData) => $scope.pageData = pageData);
};
const transformer = nodesByIndices();
$scope.$watch(() => this.data, data => {
if (!data || !data.shards) {
return;
}
const $executor = $injector.get('$executor');
$executor.register({
execute: () => callPageData(),
handleResponse: (response) => {
$scope.pageData = response;
}
});
const shards = data.shards;
$scope.totalCount = shards.length;
$scope.showing = transformer(shards, data.nodes);
$scope.labels = labels.node;
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
function onBrush({ xaxis }) {
timefilter.setTime({
from: moment(xaxis.from),
to: moment(xaxis.to),
mode: 'absolute',
this.renderReact(
<I18nProvider>
<Node
scope={$scope}
kbnUrl={kbnUrl}
onBrush={this.onBrush}
{...data}
/>
</I18nProvider>
);
});
}
const transformer = nodesByIndices();
this.renderReact = () => {
const shards = $scope.pageData.shards;
$scope.totalCount = shards.length;
$scope.showing = transformer(shards, $scope.pageData.nodes);
$scope.labels = labels.node;
render(
<I18nProvider>
<Node
scope={$scope}
kbnUrl={kbnUrl}
onBrush={onBrush}
{...$scope.pageData}
/>
</I18nProvider>,
document.getElementById('monitoringElasticsearchNodeApp')
);
};
$scope.$watch('pageData', this.renderReact);
}
});

View file

@ -8,8 +8,7 @@
* Kibana Instance
*/
import React from 'react';
import { render } from 'react-dom';
import { get, find } from 'lodash';
import { get } from 'lodash';
import uiRoutes from'ui/routes';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
@ -19,6 +18,7 @@ import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiFlexGroup, EuiFlexI
import { MonitoringTimeseriesContainer } from '../../../components/chart';
import { DetailStatus } from 'plugins/monitoring/components/kibana/detail_status';
import { I18nProvider } from '@kbn/i18n/react';
import { MonitoringViewBaseController } from '../../base_controller';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -51,87 +51,74 @@ uiRoutes.when('/kibana/instances/:uuid', {
},
pageData: getPageData
},
controller($injector, $scope) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controllerAs: 'monitoringKibanaInstanceApp',
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope) {
super({
title: `Kibana - ${get($scope.pageData, 'kibanaSummary.name')}`,
defaultData: {},
getPageData,
reactNodeId: 'monitoringKibanaInstanceApp',
$scope,
$injector
});
const $route = $injector.get('$route');
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.pageData = $route.current.locals.pageData;
$scope.$watch(() => this.data, data => {
if (!data || !data.metrics) {
return;
}
const title = $injector.get('title');
title($scope.cluster, `Kibana - ${get($scope.pageData, 'kibanaSummary.name')}`);
this.setTitle(`Kibana - ${get(data, 'kibanaSummary.name')}`);
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
$scope.$watch('pageData', renderReact);
renderReact();
function renderReact() {
const app = document.getElementById('monitoringKibanaInstanceApp');
if (!app) {
return;
}
const overviewPage = (
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<DetailStatus stats={$scope.pageData.kibanaSummary} />
<EuiSpacer size="m"/>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_requests}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_response_times}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_memory}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_average_concurrent_connections}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_os_load}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_process_delay}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
render(overviewPage, app);
this.renderReact(
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<DetailStatus stats={data.kibanaSummary} />
<EuiSpacer size="m"/>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_requests}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_response_times}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_memory}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_average_concurrent_connections}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_os_load}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_process_delay}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
});
}
}
});

View file

@ -8,8 +8,6 @@
* Kibana Overview
*/
import React from 'react';
import { render } from 'react-dom';
import { find } from 'lodash';
import uiRoutes from'ui/routes';
import { MonitoringTimeseriesContainer } from '../../../components/chart';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
@ -19,6 +17,7 @@ import { timefilter } from 'ui/timefilter';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { ClusterStatus } from '../../../components/kibana/cluster_status';
import { I18nProvider } from '@kbn/i18n/react';
import { MonitoringViewBaseController } from '../../base_controller';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -50,64 +49,49 @@ uiRoutes.when('/kibana', {
},
pageData: getPageData
},
controller($injector, $scope) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controllerAs: 'monitoringKibanaOverviewApp',
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope) {
super({
title: `Kibana`,
defaultData: {},
getPageData,
reactNodeId: 'monitoringKibanaOverviewApp',
$scope,
$injector
});
const $route = $injector.get('$route');
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.pageData = $route.current.locals.pageData;
$scope.$watch(() => this.data, data => {
if (!data || !data.clusterStatus) {
return;
}
const title = $injector.get('title');
title($scope.cluster, 'Kibana');
this.renderReact(
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<ClusterStatus stats={data.clusterStatus} />
<EuiSpacer size="m"/>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_cluster_requests}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={data.metrics.kibana_cluster_response_times}
/>
</EuiFlexItem>
</EuiFlexGroup>
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
$scope.$watch('pageData', renderReact);
renderReact();
function renderReact() {
const app = document.getElementById('monitoringKibanaOverviewApp');
if (!app) {
return;
}
const overviewPage = (
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<ClusterStatus stats={$scope.pageData.clusterStatus} />
<EuiSpacer size="m"/>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_cluster_requests}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<MonitoringTimeseriesContainer
series={$scope.pageData.metrics.kibana_cluster_response_times}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
render(overviewPage, app);
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
});
}
}
});

View file

@ -36,7 +36,7 @@ export default function ({ getService, getPageObjects }) {
it('should have Instance Summary Status showing correct info', async () => {
expect(await instance.getSummary()).to.eql({
transportAddress: 'tsullivan.local:5601',
transportAddress: 'Transport Address:\ntsullivan.local:5601',
osFreeMemory: 'OS Free Memory:\n1.5 GB',
version: 'Version:\n7.0.0-alpha1',
uptime: 'Uptime:\n3 minutes',