[Monitoring] Update missed logstash pages to EUI (#27258)

* Update logstash to EUI pages

* Adding missed functionality

* Ensure columns are sortable and update the nodes view to use the right base controller methods
This commit is contained in:
Chris Roberson 2018-12-19 13:14:46 -05:00 committed by GitHub
parent 24cb299ba4
commit 8283ea5c30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 258 additions and 670 deletions

View file

@ -19,6 +19,7 @@ class ListingUI extends PureComponent {
{
name: 'Name',
field: 'logstash.name',
sortable: true,
render: (name, node) => (
<div>
<div>
@ -41,25 +42,30 @@ class ListingUI extends PureComponent {
{
name: 'CPU Usage',
field: 'process.cpu.percent',
sortable: true,
render: value => formatPercentageUsage(value, 100)
},
{
name: 'Load Average',
field: 'os.cpu.load_average.1m',
sortable: true,
render: value => formatNumber(value, '0.00')
},
{
name: 'JVM Heap Used',
field: 'jvm.mem.heap_used_percent',
sortable: true,
render: value => formatPercentageUsage(value, 100)
},
{
name: 'Events Ingested',
field: 'events.out',
sortable: true,
render: value => formatNumber(value, '0.[0]a')
},
{
name: 'Config Reloads',
sortable: true,
render: node => (
<div>
<div>{ node.reloads.successes } successes</div>
@ -70,6 +76,7 @@ class ListingUI extends PureComponent {
{
name: 'Version',
field: 'logstash.version',
sortable: true,
render: value => formatNumber(value)
}
];

View file

@ -12,11 +12,6 @@ import './elasticsearch/cluster_status';
import './elasticsearch/index_summary';
import './elasticsearch/node_summary';
import './elasticsearch/ml_job_listing';
import './logstash/cluster_status';
import './logstash/listing';
import './logstash/node_summary';
import './logstash/pipeline_viewer';
import './logstash/pipeline_listing';
import './kibana/cluster_status';
import './kibana/listing';
import './kibana/summary';

View file

@ -1,26 +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 { render } from 'react-dom';
import { uiModules } from 'ui/modules';
import { ClusterStatus } from 'plugins/monitoring/components/logstash/cluster_status';
import { I18nProvider } from '@kbn/i18n/react';
const uiModule = uiModules.get('monitoring/directives', []);
uiModule.directive('monitoringClusterStatusLogstash', () => {
return {
restrict: 'E',
scope: {
status: '='
},
link(scope, $el) {
scope.$watch('status', status => {
render(<I18nProvider><ClusterStatus stats={status} /></I18nProvider>, $el[0]);
});
}
};
});

View file

@ -1,177 +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 { get } from 'lodash';
import React from 'react';
import { render } from 'react-dom';
import { uiModules } from 'ui/modules';
import {
KuiTableRowCell,
KuiTableRow
} from '@kbn/ui-framework/components';
import {
EuiLink,
} from '@elastic/eui';
import { MonitoringTable } from 'plugins/monitoring/components/table';
import { SORT_ASCENDING } from '../../../../common/constants';
import {
formatNumber,
formatPercentageUsage
} from '../../../lib/format_number';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
const filterFields = [ 'logstash.name', 'logstash.host', 'logstash.http_address' ];
const columns = [
{
title: i18n.translate('xpack.monitoring.logstash.nodes.nameTitle', {
defaultMessage: 'Name'
}),
sortKey: 'logstash.name',
sortOrder: SORT_ASCENDING
},
{
title: i18n.translate('xpack.monitoring.logstash.nodes.cpuUsageTitle', {
defaultMessage: 'CPU Usage'
}),
sortKey: 'process.cpu.percent'
},
{
title: i18n.translate('xpack.monitoring.logstash.nodes.loadAverageTitle', {
defaultMessage: 'Load Average'
}),
sortKey: 'os.cpu.load_average.1m',
},
{
title: i18n.translate('xpack.monitoring.logstash.nodes.jvmHeapUsedTitle', {
defaultMessage: '{javaVirtualMachine} Heap Used',
values: { javaVirtualMachine: 'JVM' }
}),
sortKey: 'jvm.mem.heap_used_percent'
},
{
title: i18n.translate('xpack.monitoring.logstash.nodes.eventsIngestedTitle', {
defaultMessage: 'Events Ingested'
}),
sortKey: 'events.out'
},
{
title: i18n.translate('xpack.monitoring.logstash.nodes.configReloadsTitle', {
defaultMessage: 'Config Reloads'
})
},
{
title: i18n.translate('xpack.monitoring.logstash.nodes.versionTitle', {
defaultMessage: 'Version'
}),
sortKey: 'logstash.version'
}
];
const nodeRowFactory = (scope, kbnUrl) => {
const goToNode = uuid => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/logstash/node/${uuid}`);
});
};
return function NodeRow(props) {
return (
<KuiTableRow>
<KuiTableRowCell>
<div className="monTableCell__name">
<EuiLink
onClick={goToNode.bind(null, get(props, 'logstash.uuid'))}
>
{ get(props, 'logstash.name') }
</EuiLink>
</div>
<div className="monTableCell__transportAddress">{ get(props, 'logstash.http_address') }</div>
</KuiTableRowCell>
<KuiTableRowCell>
<div className="monTableCell__number">
{ formatPercentageUsage(props.process.cpu.percent, 100) }
</div>
</KuiTableRowCell>
<KuiTableRowCell>
<div className="monTableCell__number">
{ formatNumber(get(props, 'os.cpu.load_average["1m"]'), '0.00') }
</div>
</KuiTableRowCell>
<KuiTableRowCell>
<div className="monTableCell__number">
{ formatPercentageUsage(props.jvm.mem.heap_used_percent, 100) }
</div>
</KuiTableRowCell>
<KuiTableRowCell>
<div className="monTableCell__number">
{ formatNumber(props.events.out, '0.[0]a') }
</div>
</KuiTableRowCell>
<KuiTableRowCell>
<div className="monTableCell__splitNumber">
<FormattedMessage
id="xpack.monitoring.logstash.nodes.configReloadsSuccessCountLabel"
defaultMessage="{reloadsSuccesses} successes"
values={{ reloadsSuccesses: props.reloads.successes }}
/>
</div>
<div className="monTableCell__splitNumber">
<FormattedMessage
id="xpack.monitoring.logstash.nodes.configReloadsFailuresCountLabel"
defaultMessage="{reloadsFailures} failures"
values={{ reloadsFailures: props.reloads.failures }}
/>
</div>
</KuiTableRowCell>
<KuiTableRowCell>
<div className="monTableCell__version">
{ formatNumber(get(props, 'logstash.version')) }
</div>
</KuiTableRowCell>
</KuiTableRow>
);
};
};
const uiModule = uiModules.get('monitoring/directives', []);
uiModule.directive('monitoringLogstashNodeListing', (kbnUrl, i18n) => {
return {
restrict: 'E',
scope: {
nodes: '=',
pageIndex: '=',
filterText: '=',
sortKey: '=',
sortOrder: '=',
onNewState: '=',
},
link: function (scope, $el) {
scope.$watch('nodes', (nodes = []) => {
const filterNodesPlaceholder = i18n('xpack.monitoring.logstash.filterNodesPlaceholder', { defaultMessage: 'Filter Nodes…' });
const nodesTable = (
<I18nProvider>
<MonitoringTable
className="logstashNodesTable"
rows={nodes}
pageIndex={scope.pageIndex}
filterText={scope.filterText}
sortKey={scope.sortKey}
sortOrder={scope.sortOrder}
onNewState={scope.onNewState}
placeholder={filterNodesPlaceholder}
filterFields={filterFields}
columns={columns}
rowComponent={nodeRowFactory(scope, kbnUrl)}
/>
</I18nProvider>
);
render(nodesTable, $el[0]);
});
}
};
});

View file

@ -1,26 +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 { render } from 'react-dom';
import { uiModules } from 'ui/modules';
import { DetailStatus } from 'plugins/monitoring/components/logstash/detail_status';
import { I18nProvider } from '@kbn/i18n/react';
const uiModule = uiModules.get('monitoring/directives', []);
uiModule.directive('monitoringLogstashNodeSummary', () => {
return {
restrict: 'E',
scope: {
logstash: '='
},
link(scope, $el) {
scope.$watch('logstash', logstash => {
render(<I18nProvider><DetailStatus stats={logstash} /></I18nProvider>, $el[0]);
});
}
};
});

View file

@ -1,198 +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 { render, unmountComponentAtNode } from 'react-dom';
import moment from 'moment';
import { partialRight } from 'lodash';
import { uiModules } from 'ui/modules';
import {
KuiTableRowCell,
KuiTableRow,
KuiEmptyTablePrompt
} from '@kbn/ui-framework/components';
import {
EuiFlexGroup,
EuiFlexItem,
EuiLink,
} from '@elastic/eui';
import { MonitoringTable } from 'plugins/monitoring/components/table';
import { Sparkline } from 'plugins/monitoring/components/sparkline';
import { SORT_ASCENDING } from '../../../../common/constants';
import { formatMetric } from '../../../lib/format_number';
import { timefilter } from 'ui/timefilter';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
const filterFields = [ 'id' ];
const columns = [
{
title: i18n.translate('xpack.monitoring.logstash.pipelines.idTitle', {
defaultMessage: 'ID'
}),
sortKey: 'id',
sortOrder: SORT_ASCENDING
},
{
title: i18n.translate('xpack.monitoring.logstash.pipelines.eventsEmittedRateTitle', {
defaultMessage: 'Events Emitted Rate'
}),
sortKey: 'latestThroughput'
},
{
title: i18n.translate('xpack.monitoring.logstash.pipelines.numberOfNodesTitle', {
defaultMessage: 'Number of Nodes'
}),
sortKey: 'latestNodesCount',
}
];
const pipelineRowFactory = (onPipelineClick, onBrush, tooltipXValueFormatter, tooltipYValueFormatter) => {
return function PipelineRow({ id, metrics, latestThroughput, latestNodesCount }) {
const throughputMetric = metrics.throughput;
const nodesCountMetric = metrics.nodesCount;
return (
<KuiTableRow>
<KuiTableRowCell>
<div className="monTableCell__name">
<EuiLink
onClick={onPipelineClick.bind(null, id)}
data-test-subj="id"
>
{ id }
</EuiLink>
</div>
</KuiTableRowCell>
<KuiTableRowCell>
<EuiFlexGroup
gutterSize="none"
alignItems="center"
>
<EuiFlexItem>
<Sparkline
series={throughputMetric.data}
onBrush={onBrush}
tooltip={{
xValueFormatter: tooltipXValueFormatter,
yValueFormatter: partialRight(tooltipYValueFormatter, throughputMetric.metric.format, throughputMetric.metric.units)
}}
options={{ xaxis: throughputMetric.timeRange }}
/>
</EuiFlexItem>
<EuiFlexItem
className="monTableCell__number"
data-test-subj="eventsEmittedRate"
>
{ formatMetric(latestThroughput, '0.[0]a', throughputMetric.metric.units) }
</EuiFlexItem>
</EuiFlexGroup>
</KuiTableRowCell>
<KuiTableRowCell>
<EuiFlexGroup
gutterSize="none"
alignItems="center"
>
<EuiFlexItem>
<Sparkline
series={nodesCountMetric.data}
onBrush={onBrush}
tooltip={{
xValueFormatter: tooltipXValueFormatter,
yValueFormatter: partialRight(tooltipYValueFormatter, nodesCountMetric.metric.format, nodesCountMetric.metric.units)
}}
options={{ xaxis: nodesCountMetric.timeRange }}
/>
</EuiFlexItem>
<EuiFlexItem
className="monTableCell__number"
data-test-subj="nodeCount"
>
{ formatMetric(latestNodesCount, '0a') }
</EuiFlexItem>
</EuiFlexGroup>
</KuiTableRowCell>
</KuiTableRow>
);
};
};
const uiModule = uiModules.get('monitoring/directives', []);
uiModule.directive('monitoringLogstashPipelineListing', ($injector, i18n) => {
const kbnUrl = $injector.get('kbnUrl');
const config = $injector.get('config');
const dateFormat = config.get('dateFormat');
return {
restrict: 'E',
scope: {
pipelines: '=',
pageIndex: '=',
filterText: '=',
sortKey: '=',
sortOrder: '=',
onNewState: '=',
upgradeMessage: '@',
},
link: function (scope, $el) {
function onBrush(xaxis) {
timefilter.setTime({
from: moment(xaxis.from),
to: moment(xaxis.to),
mode: 'absolute'
});
}
function onPipelineClick(id) {
const url = `/logstash/pipelines/${id}`;
scope.$evalAsync(() => kbnUrl.changePath(url));
}
function tooltipXValueFormatter(xValue) {
return moment(xValue).format(dateFormat);
}
function tooltipYValueFormatter(yValue, format, units) {
return formatMetric(yValue, format, units);
}
scope.$watch('pipelines', (pipelines = []) => {
if (scope.upgradeMessage) {
render(<KuiEmptyTablePrompt message={scope.upgradeMessage} />, $el[0]);
return;
}
const filterPipelinesPlaceholder = i18n('xpack.monitoring.logstash.filterPipelinesPlaceholder', {
defaultMessage: 'Filter Pipelines…'
});
const pipelinesTable = (
<I18nProvider>
<MonitoringTable
className="logstashPipelinesTable"
rows={pipelines}
pageIndex={scope.pageIndex}
filterText={scope.filterText}
sortKey={scope.sortKey}
sortOrder={scope.sortOrder}
onNewState={scope.onNewState}
placeholder={filterPipelinesPlaceholder}
filterFields={filterFields}
columns={columns}
rowComponent={pipelineRowFactory(onPipelineClick, onBrush, tooltipXValueFormatter, tooltipYValueFormatter)}
/>
</I18nProvider>
);
render(pipelinesTable, $el[0]);
});
scope.$on('$destroy', () => unmountComponentAtNode($el[0]));
}
};
});

View file

@ -1,50 +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 { render } from 'react-dom';
import moment from 'moment';
import { uiModules } from 'ui/modules';
import { PipelineViewer } from 'plugins/monitoring/components/logstash/pipeline_viewer';
import { Pipeline } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline';
import { List } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/list';
import { PipelineState } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline_state';
import { I18nProvider } from '@kbn/i18n/react';
const uiModule = uiModules.get('monitoring/directives', []);
uiModule.directive('monitoringLogstashPipelineViewer', $injector => {
const config = $injector.get('config');
const dateFormat = config.get('dateFormat');
const timeseriesTooltipXValueFormatter = xValue =>
moment(xValue).format(dateFormat);
return {
restrict: 'E',
scope: {
pipeline: '=',
},
link: (scope, $el) => {
const pipelineState = new PipelineState(scope.pipeline);
scope.$watch('pipeline', updatedPipeline => {
pipelineState.update(updatedPipeline);
render(
<I18nProvider>
<PipelineViewer
pipeline={List.fromPipeline(
Pipeline.fromPipelineGraph(pipelineState.config.graph)
)}
timeseriesTooltipXValueFormatter={timeseriesTooltipXValueFormatter}
/>
</I18nProvider>,
$el[0]
);
});
},
};
});

View file

@ -1,12 +1,9 @@
<monitoring-main product="logstash" name="nodes" instance="{{ pageData.nodeSummary.name }}" resolver="{{ pageData.nodeSummary.uuid }}" page="advanced">
<monitoring-logstash-node-summary logstash="pageData.nodeSummary"></monitoring-logstash-node-summary>
<div class="page-row">
<div class="row" ng-if="pageData.metrics">
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_node_cpu_utilization"/></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_queue_events_count"/></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_node_cgroup_cpu"/></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_pipeline_queue_size"/></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_node_cgroup_stats"/></div>
</div>
</div>
<monitoring-main
product="logstash"
name="nodes"
instance="{{ pageData.nodeSummary.name }}"
resolver="{{ pageData.nodeSummary.uuid }}"
page="advanced"
>
<div id="monitoringLogstashNodeAdvancedApp"></div>
</monitoring-main>

View file

@ -7,12 +7,17 @@
/*
* Logstash Node Advanced View
*/
import { find } from 'lodash';
import React from 'react';
import uiRoutes from'ui/routes';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { MonitoringViewBaseController } from '../../../base_controller';
import { DetailStatus } from 'plugins/monitoring/components/logstash/detail_status';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
import { MonitoringTimeseriesContainer } from '../../../../components/chart';
import { I18nProvider } from '@kbn/i18n/react';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -46,32 +51,60 @@ uiRoutes.when('/logstash/node/:uuid/advanced', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
super({
defaultData: {},
getPageData,
reactNodeId: 'monitoringLogstashNodeAdvancedApp',
$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.logstash.node.advanced.routeTitle', {
defaultMessage: 'Logstash - {nodeName} - Advanced',
values: {
nodeName: $scope.pageData.nodeSummary.name
}
});
title($scope.cluster, routeTitle);
this.setTitle(i18n('xpack.monitoring.logstash.node.advanced.routeTitle', {
defaultMessage: 'Logstash - {nodeName} - Advanced',
values: {
nodeName: data.nodeSummary.name
}
}));
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
const metricsToShow = [
data.metrics.logstash_node_cpu_utilization,
data.metrics.logstash_queue_events_count,
data.metrics.logstash_node_cgroup_cpu,
data.metrics.logstash_pipeline_queue_size,
data.metrics.logstash_node_cgroup_stats,
];
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
this.renderReact(
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<DetailStatus stats={data.nodeSummary}/>
<EuiSpacer size="m"/>
<EuiFlexGrid columns={2} gutterSize="none">
{metricsToShow.map((metric, index) => (
<EuiFlexItem key={index} style={{ width: '50%' }}>
<MonitoringTimeseriesContainer
series={metric}
{...data}
/>
<EuiSpacer size="m"/>
</EuiFlexItem>
))}
</EuiFlexGrid>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
});
}
}
});

View file

@ -5,15 +5,5 @@
resolver="{{ pageData.nodeSummary.uuid }}"
page="overview"
>
<monitoring-logstash-node-summary logstash="pageData.nodeSummary"></monitoring-logstash-node-summary>
<div class="page-row">
<div class="row" ng-if="pageData.metrics">
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_events_input_rate"></monitoring-chart></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_jvm_usage"></monitoring-chart></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_events_output_rate"></monitoring-chart></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_node_cpu_metric"></monitoring-chart></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_events_latency"></monitoring-chart></div>
<div class="col-md-6"><monitoring-chart series="pageData.metrics.logstash_os_load"></monitoring-chart></div>
</div>
</div>
<div id="monitoringLogstashNodeApp"></div>
</monitoring-main>

View file

@ -7,12 +7,17 @@
/*
* Logstash Node
*/
import { find } from 'lodash';
import React from 'react';
import uiRoutes from'ui/routes';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { DetailStatus } from 'plugins/monitoring/components/logstash/detail_status';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
import { MonitoringTimeseriesContainer } from '../../../components/chart';
import { I18nProvider } from '@kbn/i18n/react';
import { MonitoringViewBaseController } from '../../base_controller';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -46,32 +51,61 @@ uiRoutes.when('/logstash/node/:uuid', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
super({
defaultData: {},
getPageData,
reactNodeId: 'monitoringLogstashNodeApp',
$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.logstash.node.routeTitle', {
defaultMessage: 'Logstash - {nodeName}',
values: {
nodeName: $scope.pageData.nodeSummary.name
}
});
title($scope.cluster, routeTitle);
this.setTitle(i18n('xpack.monitoring.logstash.node.routeTitle', {
defaultMessage: 'Logstash - {nodeName}',
values: {
nodeName: data.nodeSummary.name
}
}));
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
const metricsToShow = [
data.metrics.logstash_events_input_rate,
data.metrics.logstash_jvm_usage,
data.metrics.logstash_events_output_rate,
data.metrics.logstash_node_cpu_metric,
data.metrics.logstash_events_latency,
data.metrics.logstash_os_load,
];
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
this.renderReact(
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<DetailStatus stats={data.nodeSummary}/>
<EuiSpacer size="m"/>
<EuiFlexGrid columns={2} gutterSize="none">
{metricsToShow.map((metric, index) => (
<EuiFlexItem key={index} style={{ width: '50%' }}>
<MonitoringTimeseriesContainer
series={metric}
{...data}
/>
<EuiSpacer size="m"/>
</EuiFlexItem>
))}
</EuiFlexGrid>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
});
}
}
});

View file

@ -4,11 +4,5 @@
resolver="{{ pageData.nodeSummary.uuid }}"
page="pipelines"
>
<monitoring-logstash-node-summary logstash="pageData.nodeSummary"></monitoring-logstash-node-summary>
<div class="page-row">
<monitoring-logstash-pipeline-listing
pipelines="pageData.pipelines"
upgrade-message="{{ upgradeMessage }}"
></monitoring-logstash-pipeline-listing>
</div>
<div id="monitoringLogstashNodePipelinesApp"></div>
</monitoring-main>

View file

@ -8,7 +8,7 @@
* Logstash Node Pipelines Listing
*/
import { find } from 'lodash';
import React from 'react';
import uiRoutes from 'ui/routes';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
@ -17,6 +17,9 @@ import {
} from 'plugins/monitoring/lib/logstash/pipelines';
import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { MonitoringViewBaseEuiTableController } from '../../../';
import { I18nProvider } from '@kbn/i18n/react';
import { PipelineListing } from '../../../../components/logstash/pipeline_listing/pipeline_listing';
const getPageData = ($injector) => {
const $route = $injector.get('$route');
@ -66,34 +69,49 @@ uiRoutes
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
const $route = $injector.get('$route');
const globalState = $injector.get('globalState');
const title = $injector.get('title');
const $executor = $injector.get('$executor');
controller: class extends MonitoringViewBaseEuiTableController {
constructor($injector, $scope, i18n) {
const kbnUrl = $injector.get('kbnUrl');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
$scope.pageData = $route.current.locals.pageData;
super({
defaultData: {},
getPageData,
reactNodeId: 'monitoringLogstashNodePipelinesApp',
$scope,
$injector
});
$scope.upgradeMessage = makeUpgradeMessage($scope.pageData.nodeSummary.version, i18n);
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
$scope.$watch(() => this.data, data => {
if (!data || !data.nodeSummary) {
return;
}
const routeTitle = i18n('xpack.monitoring.logstash.node.pipelines.routeTitle', {
defaultMessage: 'Logstash - {nodeName} - Pipelines',
values: {
nodeName: $scope.pageData.nodeSummary.name
}
});
title($scope.cluster, routeTitle);
this.setTitle(i18n('xpack.monitoring.logstash.node.pipelines.routeTitle', {
defaultMessage: 'Logstash - {nodeName} - Pipelines',
values: {
nodeName: data.nodeSummary.name
}
}));
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
this.renderReact(
<I18nProvider>
<PipelineListing
className="monitoringLogstashPipelinesTable"
onBrush={this.onBrush}
stats={data.nodeSummary}
data={data.pipelines}
sorting={this.sorting}
pagination={this.pagination}
onTableChange={this.onTableChange}
upgradeMessage={makeUpgradeMessage(data.nodeSummary.version, i18n)}
angular={{
kbnUrl,
scope: $scope,
}}
/>
</I18nProvider>
);
});
}
}
});

View file

@ -4,8 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { render } from 'react-dom';
import { find } from 'lodash';
import uiRoutes from'ui/routes';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import { MonitoringViewBaseEuiTableController } from '../../';
@ -27,26 +25,19 @@ uiRoutes.when('/logstash/nodes', {
controller: class LsNodesList extends MonitoringViewBaseEuiTableController {
constructor($injector, $scope) {
const kbnUrl = $injector.get('kbnUrl');
super({
title: 'Logstash - Nodes',
storageKey: 'logstash.nodes',
getPageData,
reactNodeId: 'monitoringLogstashNodesApp',
$scope,
$injector
});
const $route = $injector.get('$route');
const kbnUrl = $injector.get('kbnUrl');
this.data = $route.current.locals.pageData;
const globalState = $injector.get('globalState');
$scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid });
const renderReact = (data) => {
if (!data) {
return;
}
render(
$scope.$watch(() => this.data, data => {
this.renderReact(
<I18nProvider>
<Listing
data={data.nodes}
@ -56,13 +47,8 @@ uiRoutes.when('/logstash/nodes', {
onTableChange={this.onTableChange}
angular={{ kbnUrl, scope: $scope }}
/>
</I18nProvider>,
document.getElementById('monitoringLogstashNodesApp')
</I18nProvider>
);
};
$scope.$watch(() => this.data, data => {
renderReact(data);
});
}
}

View file

@ -8,8 +8,6 @@
* Logstash Overview
*/
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,6 +15,7 @@ import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { I18nProvider } from '@kbn/i18n/react';
import { Overview } from '../../../components/logstash/overview';
import { MonitoringViewBaseController } from '../../base_controller';
function getPageData($injector) {
const $http = $injector.get('$http');
@ -48,40 +47,26 @@ uiRoutes.when('/logstash', {
},
pageData: getPageData
},
controller($injector, $scope) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope) {
super({
title: 'Logstash',
getPageData,
reactNodeId: 'monitoringLogstashOverviewApp',
$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;
const title = $injector.get('title');
title($scope.cluster, 'Logstash');
const $executor = $injector.get('$executor');
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => $scope.pageData = response
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
function renderReact(pageData) {
render(
<I18nProvider>
<Overview
stats={pageData.clusterStatus}
metrics={pageData.metrics}
/>
</I18nProvider>,
document.getElementById('monitoringLogstashOverviewApp')
);
$scope.$watch(() => this.data, data => {
this.renderReact(
<I18nProvider>
<Overview
stats={data.clusterStatus}
metrics={data.metrics}
/>
</I18nProvider>
);
});
}
$scope.$watch('pageData', pageData => {
renderReact(pageData);
});
}
});

View file

@ -8,7 +8,5 @@
pipeline-hash="{{ pageData.pipeline.hash }}"
pipeline-versions="pageData.versions"
>
<div class="page-row">
<monitoring-logstash-pipeline-viewer pipeline="pageData.pipeline"></monitoring-logstash-pipeline-viewer>
</div>
<div id="monitoringLogstashPipelineApp"></div>
</monitoring-main>

View file

@ -7,15 +7,26 @@
/*
* Logstash Node Pipeline View
*/
import { find } from 'lodash';
import React from 'react';
import uiRoutes from'ui/routes';
import moment from 'moment';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
import { CALCULATE_DURATION_SINCE } from '../../../../common/constants';
import { formatTimestampToDuration } from '../../../../common/format_timestamp_to_duration';
import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { i18n } from '@kbn/i18n';
import { List } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/list';
import { PipelineState } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline_state';
import { PipelineViewer } from 'plugins/monitoring/components/logstash/pipeline_viewer';
import { Pipeline } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline';
import { MonitoringViewBaseController } from '../../base_controller';
import { I18nProvider } from '@kbn/i18n/react';
import {
EuiPageBody,
EuiPage,
EuiPageContent,
} from '@elastic/eui';
function getPageData($injector) {
const $route = $injector.get('$route');
@ -27,7 +38,9 @@ function getPageData($injector) {
const { ccs, cluster_uuid: clusterUuid } = globalState;
const pipelineId = $route.current.params.id;
const pipelineHash = $route.current.params.hash || '';
const url = `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}/${pipelineHash}`;
const url = pipelineHash
? `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}/${pipelineHash}`
: `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}`;
return $http.post(url, {
ccs
})
@ -72,32 +85,47 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', {
},
pageData: getPageData
},
controller($injector, $scope, i18n) {
const $route = $injector.get('$route');
const $executor = $injector.get('$executor');
const globalState = $injector.get('globalState');
const title = $injector.get('title');
controller: class extends MonitoringViewBaseController {
constructor($injector, $scope, i18n) {
const config = $injector.get('config');
const dateFormat = config.get('dateFormat');
timefilter.disableTimeRangeSelector(); // Do not display time picker in UI
timefilter.enableAutoRefreshSelector();
super({
title: i18n('xpack.monitoring.logstash.pipeline.routeTitle', {
defaultMessage: 'Logstash - Pipeline'
}),
storageKey: 'logstash.pipelines',
getPageData,
reactNodeId: 'monitoringLogstashPipelineApp',
$scope,
$injector
});
function setClusters(clusters) {
$scope.clusters = clusters;
$scope.cluster = find($scope.clusters, { cluster_uuid: globalState.cluster_uuid });
const timeseriesTooltipXValueFormatter = xValue =>
moment(xValue).format(dateFormat);
$scope.$watch(() => this.data, data => {
if (!data || !data.pipeline) {
return;
}
this.pipelineState = new PipelineState(data.pipeline);
this.renderReact(
<I18nProvider>
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<PipelineViewer
pipeline={List.fromPipeline(
Pipeline.fromPipelineGraph(this.pipelineState.config.graph)
)}
timeseriesTooltipXValueFormatter={timeseriesTooltipXValueFormatter}
/>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</I18nProvider>
);
});
}
setClusters($route.current.locals.clusters);
$scope.pageData = $route.current.locals.pageData;
title($scope.cluster, i18n('xpack.monitoring.logstash.pipeline.routeTitle', {
defaultMessage: 'Logstash - Pipeline'
}));
$executor.register({
execute: () => getPageData($injector),
handleResponse: (response) => {
$scope.pageData = response;
}
});
$executor.start($scope);
$scope.$on('$destroy', $executor.destroy);
}
});