mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[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:
parent
08fd427125
commit
faa57fd7a9
21 changed files with 355 additions and 446 deletions
|
@ -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>
|
||||
|
|
|
@ -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'
|
||||
},
|
||||
|
|
|
@ -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'
|
||||
},
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import './main';
|
||||
import './chart';
|
||||
import './sparkline';
|
||||
import './cluster/overview';
|
||||
import './cluster/listing';
|
||||
import './elasticsearch/cluster_status';
|
||||
import './elasticsearch/index_summary';
|
||||
|
|
|
@ -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]);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
});
|
|
@ -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">
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue