Skip to content

Commit

Permalink
[Monitoring] Metricbeat migration for logstash, beats and apm (#40442) (
Browse files Browse the repository at this point in the history
#42455)

* Support for logstash

* Beats support

* Fix cherry-pick api issue

* Support for logstash

* Updates for beats and logstash

* APM migration working

* Tweaks for beats migration

* Update copy for setup new button

* If on cloud, disable setup mode

* Handle new beat flow better

* Better phrasing for APM

* Add beat type to disable step

* Fix i18n issue

* Fix jest tests

* Fix api tests

* PR feedback

* Update copy

* Remove unnecessary code

* Undo changes that are now in a separate PR

* Disable more links

* Fix overview link for logstash

* PR feedback

* Fix tests

* PR feedback

* PR feedback

* Capitalize Beat per PR feedback
  • Loading branch information
chrisronline authored Aug 1, 2019
1 parent ba516a4 commit 1597b30
Show file tree
Hide file tree
Showing 53 changed files with 2,426 additions and 221 deletions.
1 change: 1 addition & 0 deletions x-pack/legacy/plugins/monitoring/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export const METRICBEAT_INDEX_NAME_UNIQUE_TOKEN = '-mb-';

// We use this for metricbeat migration to identify specific products that we do not have constants for
export const ELASTICSEARCH_CUSTOM_ID = 'elasticsearch';
export const APM_CUSTOM_ID = 'apm';
/**
* The id of the infra source owned by the monitoring plugin.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import React, { Fragment } from 'react';
import moment from 'moment';
import { uniq } from 'lodash';
import { uniq, get } from 'lodash';
import { EuiMonitoringTable } from '../../table';
import { EuiLink, EuiPage, EuiPageBody, EuiPageContent, EuiSpacer } from '@elastic/eui';
import { EuiLink, EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiCallOut } from '@elastic/eui';
import { Status } from './status';
import { formatMetric } from '../../../lib/format_number';
import { formatTimestampToDuration } from '../../../../common';
Expand Down Expand Up @@ -83,14 +83,37 @@ const columns = [
},
];

export function ApmServerInstances({ apms }) {
export function ApmServerInstances({ apms, setupMode }) {
const {
pagination,
sorting,
onTableChange,
data
data,
} = apms;

let detectedInstanceMessage = null;
if (setupMode.enabled && setupMode.data && get(setupMode.data, 'detected.mightExist')) {
detectedInstanceMessage = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.apm.instances.metricbeatMigration.detectedInstanceTitle', {
defaultMessage: 'APM server detected',
})}
color="warning"
iconType="help"
>
<p>
{i18n.translate('xpack.monitoring.apm.instances.metricbeatMigration.detectedInstanceDescription', {
defaultMessage: `Based on your indices, we think you might have an APM server. Click the 'Setup monitoring'
button below to start monitoring this APM server.`
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}

const versions = uniq(data.apms.map(item => item.version)).map(version => {
return { value: version };
});
Expand All @@ -101,12 +124,19 @@ export function ApmServerInstances({ apms }) {
<EuiPageContent>
<Status stats={data.stats} />
<EuiSpacer size="m"/>
{detectedInstanceMessage}
<EuiMonitoringTable
className="apmInstancesTable"
rows={data.apms}
columns={columns}
sorting={sorting}
pagination={pagination}
setupMode={setupMode}
uuidField="uuid"
nameField="name"
setupNewButtonLabel={i18n.translate('xpack.monitoring.apm.metricbeatMigration.setupNewButtonLabel', {
defaultMessage: 'Setup monitoring for new APM server'
})}
search={{
box: {
incremental: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { PureComponent } from 'react';
import { uniq } from 'lodash';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLink } from '@elastic/eui';
import React, { PureComponent, Fragment } from 'react';
import { uniq, get } from 'lodash';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLink, EuiCallOut } from '@elastic/eui';
import { Stats } from 'plugins/monitoring/components/beats';
import { formatMetric } from 'plugins/monitoring/lib/format_number';
import { EuiMonitoringTable } from 'plugins/monitoring/components/table';
Expand Down Expand Up @@ -74,9 +74,32 @@ export class Listing extends PureComponent {
data,
sorting,
pagination,
onTableChange
onTableChange,
setupMode
} = this.props;

let detectedInstanceMessage = null;
if (setupMode.enabled && setupMode.data && get(setupMode.data, 'detected.mightExist')) {
detectedInstanceMessage = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.beats.instances.metricbeatMigration.detectedInstanceTitle', {
defaultMessage: 'Beats instance detected',
})}
color="warning"
iconType="help"
>
<p>
{i18n.translate('xpack.monitoring.beats.instances.metricbeatMigration.detectedInstanceDescription', {
defaultMessage: `Based on your indices, we think you might have a beats instance. Click the 'Setup monitoring'
button below to start monitoring this instance.`
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}

const types = uniq(data.map(item => item.type)).map(type => {
return { value: type };
Expand All @@ -92,9 +115,16 @@ export class Listing extends PureComponent {
<EuiPageContent>
<Stats stats={stats} />
<EuiSpacer size="m"/>
{detectedInstanceMessage}
<EuiMonitoringTable
className="beatsTable"
rows={data}
setupMode={setupMode}
uuidField="uuid"
nameField="name"
setupNewButtonLabel={i18n.translate('xpack.monitoring.beats.metricbeatMigration.setupNewButtonLabel', {
defaultMessage: 'Setup monitoring for new Beats instance'
})}
columns={this.getColumns()}
sorting={sorting}
pagination={pagination}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import React from 'react';
import moment from 'moment';
import { get } from 'lodash';
import { formatMetric } from 'plugins/monitoring/lib/format_number';
import { ClusterItemContainer, BytesPercentageUsage } from './helpers';
import { ClusterItemContainer, BytesPercentageUsage, DisabledIfNoDataAndInSetupModeLink } from './helpers';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';

import {
EuiFlexGrid,
EuiFlexItem,
Expand All @@ -22,18 +21,55 @@ import {
EuiDescriptionListTitle,
EuiDescriptionListDescription,
EuiHorizontalRule,
EuiFlexGroup,
EuiToolTip,
EuiBadge
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../common/constants';

export function ApmPanel(props) {
if (!get(props, 'apms.total', 0) > 0) {
const { setupMode } = props;
const apmsTotal = get(props, 'apms.total') || 0;
// Do not show if we are not in setup mode
if (apmsTotal === 0 && !setupMode.enabled) {
return null;
}

const goToApm = () => props.changeUrl('apm');
const goToInstances = () => props.changeUrl('apm/instances');

const setupModeApmData = get(setupMode.data, 'apm');
let setupModeInstancesData = null;
if (setupMode.enabled && setupMode.data) {
const migratedNodesCount = Object.values(setupModeApmData.byUuid).filter(node => node.isFullyMigrated).length;
let totalNodesCount = Object.values(setupModeApmData.byUuid).length;
if (totalNodesCount === 0 && get(setupMode.data, 'apm.detected.mightExist', false)) {
totalNodesCount = 1;
}

const badgeColor = migratedNodesCount === totalNodesCount
? 'secondary'
: 'danger';

setupModeInstancesData = (
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
content={i18n.translate('xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip', {
defaultMessage: `These numbers indicate how many detected monitored APM servers versus how many ` +
`detected total APM servers. If there are more detected APM servers than monitored APM servers, click the Nodes ` +
`link and you will be guided in how to setup monitoring for the missing node.`
})}
>
<EuiBadge color={badgeColor}>
{migratedNodesCount}/{totalNodesCount}
</EuiBadge>
</EuiToolTip>
</EuiFlexItem>
);
}

return (
<ClusterItemContainer
{...props}
Expand All @@ -47,7 +83,9 @@ export function ApmPanel(props) {
<EuiPanel paddingSize="m">
<EuiTitle size="s">
<h3>
<EuiLink
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeApmData}
onClick={goToApm}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.apmPanel.overviewLinkAriaLabel', {
defaultMessage: 'APM Overview'
Expand All @@ -58,7 +96,7 @@ export function ApmPanel(props) {
id="xpack.monitoring.cluster.overview.apmPanel.overviewLinkLabel"
defaultMessage="Overview"
/>
</EuiLink>
</DisabledIfNoDataAndInSetupModeLink>
</h3>
</EuiTitle>
<EuiHorizontalRule margin="m" />
Expand Down Expand Up @@ -90,27 +128,32 @@ export function ApmPanel(props) {
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel paddingSize="m">
<EuiTitle size="s">
<h3>
<EuiLink
onClick={goToInstances}
aria-label={i18n.translate(
'xpack.monitoring.cluster.overview.apmPanel.instancesTotalLinkAriaLabel',
{
defaultMessage: 'Apm Instances: {apmsTotal}',
values: { apmsTotal: props.apms.total }
}
)}
data-test-subj="apmListing"
>
<FormattedMessage
id="xpack.monitoring.cluster.overview.apmPanel.serversTotalLinkLabel"
defaultMessage="APM Servers: {apmsTotal}"
values={{ apmsTotal: (<span data-test-subj="apmsTotal">{props.apms.total}</span>) }}
/>
</EuiLink>
</h3>
</EuiTitle>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiTitle size="s">
<h3>
<EuiLink
onClick={goToInstances}
aria-label={i18n.translate(
'xpack.monitoring.cluster.overview.apmPanel.instancesTotalLinkAriaLabel',
{
defaultMessage: 'APM Instances: {apmsTotal}',
values: { apmsTotal }
}
)}
data-test-subj="apmListing"
>
<FormattedMessage
id="xpack.monitoring.cluster.overview.apmPanel.serversTotalLinkLabel"
defaultMessage="APM Servers: {apmsTotal}"
values={{ apmsTotal: (<span data-test-subj="apmsTotal">{apmsTotal}</span>) }}
/>
</EuiLink>
</h3>
</EuiTitle>
</EuiFlexItem>
{setupModeInstancesData}
</EuiFlexGroup>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList type="column">
<EuiDescriptionListTitle>
Expand Down
Loading

0 comments on commit 1597b30

Please sign in to comment.