[Monitoring] Metricbeat Migration Wizard (last step!!) (#45799)

* Enable setup mode UI toggles

* We want to keep the no data page but update the copy

* More updated copy

* Remove manual checks for logstash, beats, apm and kibana

* Hide the setup mode controls on the no data page. There is nothing different in setup mode

* Setup mode test

* Fix bug with disabling internal collection for ES

* First steps towards the redesign of setup mode

* Consolidate UI code, design changes, use constants defined in our plugin

* Fix tooltips

* Design/copy feedback

* Use badge and onClick

* More feedback

* Only detect usage on the live cluster

* Fix existing tests, remove test that will be added in other PR

* Fix failing test

* Fix issue with wrong callout showing

* Ensure we check for live nodes if no cluster uuid is provided

* We need a custom listing callout for ES

* Custom callout for kibana instances

* More space from the bottom bar

* Disable switching if they enabled internal collection

* Copy updates

* Fix broken tests

* Fix more tests

* Fix i18n

* Update copy

* Fix a couple i18n issues

* Fixing a couple of missing scenarios

* Fix translations

* Update snapshots

* PR feedback

* PR feedback

* We also need totalUniqueInternallyCollectedCount to identify when we have detected products but they are not monitored (thinking ES and Kibana)

* Remove why documentation link until we have the resource available

* Ensure tabs are properly disabled

* Address issue with the ES nodes callout not working at times

* Ensure we check if setup mode is enabled

* Change internal collection to self monitoring, and remove the word 'collection' usage

* Only show Enter setup mode on pages with valid setup mode options

* Copy updates

* Copy updates

* Ensure we update the top nav item when we toggle setup mode on or off
This commit is contained in:
Chris Roberson 2019-10-02 12:31:26 -04:00 committed by GitHub
parent d243697e81
commit d935b3da08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
70 changed files with 1803 additions and 2283 deletions

View file

@ -154,8 +154,11 @@ export const INDEX_PATTERN_FILEBEAT = 'filebeat-*';
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';
export const ELASTICSEARCH_SYSTEM_ID = 'elasticsearch';
export const KIBANA_SYSTEM_ID = 'kibana';
export const BEATS_SYSTEM_ID = 'beats';
export const APM_SYSTEM_ID = 'apm';
export const LOGSTASH_SYSTEM_ID = 'logstash';
/**
* The id of the infra source owned by the monitoring plugin.
*/

View file

@ -8,80 +8,111 @@ import React, { Fragment } from 'react';
import moment from 'moment';
import { uniq, get } from 'lodash';
import { EuiMonitoringTable } from '../../table';
import { EuiLink, EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiCallOut } from '@elastic/eui';
import { EuiLink, EuiPage, EuiPageBody, EuiPageContent, EuiSpacer } from '@elastic/eui';
import { Status } from './status';
import { formatMetric } from '../../../lib/format_number';
import { formatTimestampToDuration } from '../../../../common';
import { i18n } from '@kbn/i18n';
import { APM_SYSTEM_ID } from '../../../../common/constants';
import { ListingCallOut } from '../../setup_mode/listing_callout';
import { SetupModeBadge } from '../../setup_mode/badge';
const columns = [
{
name: i18n.translate('xpack.monitoring.apm.instances.nameTitle', {
defaultMessage: 'Name'
}),
field: 'name',
render: (name, instance) => (
<EuiLink
href={`#/apm/instances/${instance.uuid}`}
data-test-subj={`apmLink-${name}`}
>
{name}
</EuiLink>
)
},
{
name: i18n.translate('xpack.monitoring.apm.instances.outputEnabledTitle', {
defaultMessage: 'Output Enabled'
}),
field: 'output'
},
{
name: i18n.translate('xpack.monitoring.apm.instances.totalEventsRateTitle', {
defaultMessage: 'Total Events Rate'
}),
field: 'total_events_rate',
render: value => formatMetric(value, '', '/s')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.bytesSentRateTitle', {
defaultMessage: 'Bytes Sent Rate'
}),
field: 'bytes_sent_rate',
render: value => formatMetric(value, 'byte', '/s')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.outputErrorsTitle', {
defaultMessage: 'Output Errors'
}),
field: 'errors',
render: value => formatMetric(value, '0')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.lastEventTitle', {
defaultMessage: 'Last Event'
}),
field: 'time_of_last_event',
render: value => i18n.translate('xpack.monitoring.apm.instances.lastEventValue', {
defaultMessage: '{timeOfLastEvent} ago',
values: {
timeOfLastEvent: formatTimestampToDuration(+moment(value), 'since')
function getColumns(setupMode) {
return [
{
name: i18n.translate('xpack.monitoring.apm.instances.nameTitle', {
defaultMessage: 'Name'
}),
field: 'name',
render: (name, apm) => {
let setupModeStatus = null;
if (setupMode && setupMode.enabled) {
const list = get(setupMode, 'data.byUuid', {});
const status = list[apm.uuid] || {};
const instance = {
uuid: apm.uuid,
name: apm.name
};
setupModeStatus = (
<div className="monTableCell__setupModeStatus">
<SetupModeBadge
setupMode={setupMode}
status={status}
instance={instance}
productName={APM_SYSTEM_ID}
/>
</div>
);
}
return (
<Fragment>
<EuiLink
href={`#/apm/instances/${apm.uuid}`}
data-test-subj={`apmLink-${name}`}
>
{name}
</EuiLink>
{setupModeStatus}
</Fragment>
);
}
})
},
{
name: i18n.translate('xpack.monitoring.apm.instances.allocatedMemoryTitle', {
defaultMessage: 'Allocated Memory'
}),
field: 'memory',
render: value => formatMetric(value, 'byte')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.versionTitle', {
defaultMessage: 'Version'
}),
field: 'version'
},
];
},
{
name: i18n.translate('xpack.monitoring.apm.instances.outputEnabledTitle', {
defaultMessage: 'Output Enabled'
}),
field: 'output'
},
{
name: i18n.translate('xpack.monitoring.apm.instances.totalEventsRateTitle', {
defaultMessage: 'Total Events Rate'
}),
field: 'total_events_rate',
render: value => formatMetric(value, '', '/s')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.bytesSentRateTitle', {
defaultMessage: 'Bytes Sent Rate'
}),
field: 'bytes_sent_rate',
render: value => formatMetric(value, 'byte', '/s')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.outputErrorsTitle', {
defaultMessage: 'Output Errors'
}),
field: 'errors',
render: value => formatMetric(value, '0')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.lastEventTitle', {
defaultMessage: 'Last Event'
}),
field: 'time_of_last_event',
render: value => i18n.translate('xpack.monitoring.apm.instances.lastEventValue', {
defaultMessage: '{timeOfLastEvent} ago',
values: {
timeOfLastEvent: formatTimestampToDuration(+moment(value), 'since')
}
})
},
{
name: i18n.translate('xpack.monitoring.apm.instances.allocatedMemoryTitle', {
defaultMessage: 'Allocated Memory'
}),
field: 'memory',
render: value => formatMetric(value, 'byte')
},
{
name: i18n.translate('xpack.monitoring.apm.instances.versionTitle', {
defaultMessage: 'Version'
}),
field: 'version'
},
];
}
export function ApmServerInstances({ apms, setupMode }) {
const {
@ -91,26 +122,14 @@ export function ApmServerInstances({ apms, setupMode }) {
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>
let setupModeCallout = null;
if (setupMode.enabled && setupMode.data) {
setupModeCallout = (
<ListingCallOut
setupModeData={setupMode.data}
useNodeIdentifier={false}
productName={APM_SYSTEM_ID}
/>
);
}
@ -124,19 +143,15 @@ export function ApmServerInstances({ apms, setupMode }) {
<EuiPageContent>
<Status stats={data.stats} />
<EuiSpacer size="m"/>
{detectedInstanceMessage}
{setupModeCallout}
<EuiMonitoringTable
className="apmInstancesTable"
rows={data.apms}
columns={columns}
columns={getColumns(setupMode)}
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'
})}
productName={APM_SYSTEM_ID}
search={{
box: {
incremental: true,

View file

@ -4,34 +4,64 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { PureComponent, Fragment } from 'react';
import React, { PureComponent } from 'react';
import { uniq, get } from 'lodash';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLink, EuiCallOut } from '@elastic/eui';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLink } 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';
import { i18n } from '@kbn/i18n';
import { BEATS_SYSTEM_ID } from '../../../../common/constants';
import { ListingCallOut } from '../../setup_mode/listing_callout';
import { SetupModeBadge } from '../../setup_mode/badge';
export class Listing extends PureComponent {
getColumns() {
const { kbnUrl, scope } = this.props.angular;
const setupMode = this.props.setupMode;
return [
{
name: i18n.translate('xpack.monitoring.beats.instances.nameTitle', { defaultMessage: 'Name' }),
field: 'name',
render: (name, beat) => (
<EuiLink
onClick={() => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/beats/beat/${beat.uuid}`);
});
}}
data-test-subj={`beatLink-${name}`}
>
{name}
</EuiLink>
)
render: (name, beat) => {
let setupModeStatus = null;
if (setupMode && setupMode.enabled) {
const list = get(setupMode, 'data.byUuid', {});
const status = list[beat.uuid] || {};
const instance = {
uuid: beat.uuid,
name: beat.name
};
setupModeStatus = (
<div className="monTableCell__setupModeStatus">
<SetupModeBadge
setupMode={setupMode}
status={status}
instance={instance}
productName={BEATS_SYSTEM_ID}
/>
</div>
);
}
return (
<div>
<EuiLink
onClick={() => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/beats/beat/${beat.uuid}`);
});
}}
data-test-subj={`beatLink-${name}`}
>
{name}
</EuiLink>
{setupModeStatus}
</div>
);
}
},
{
name: i18n.translate('xpack.monitoring.beats.instances.typeTitle', { defaultMessage: 'Type' }),
@ -78,26 +108,14 @@ export class Listing extends PureComponent {
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>
let setupModeCallOut = null;
if (setupMode.enabled && setupMode.data) {
setupModeCallOut = (
<ListingCallOut
setupModeData={setupMode.data}
useNodeIdentifier={false}
productName={BEATS_SYSTEM_ID}
/>
);
}
@ -115,16 +133,12 @@ export class Listing extends PureComponent {
<EuiPageContent>
<Stats stats={stats} />
<EuiSpacer size="m"/>
{detectedInstanceMessage}
{setupModeCallOut}
<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'
})}
productName={BEATS_SYSTEM_ID}
columns={this.getColumns()}
sorting={sorting}
pagination={pagination}

View file

@ -22,11 +22,10 @@ import {
EuiDescriptionListDescription,
EuiHorizontalRule,
EuiFlexGroup,
EuiToolTip,
EuiIcon
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../common/constants';
import { CALCULATE_DURATION_SINCE, APM_SYSTEM_ID } from '../../../../common/constants';
import { SetupModeTooltip } from '../../setup_mode/tooltip';
export function ApmPanel(props) {
const { setupMode } = props;
@ -39,48 +38,16 @@ export function ApmPanel(props) {
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 {
totalUniqueInstanceCount,
totalUniqueFullyMigratedCount,
totalUniquePartiallyMigratedCount
} = setupModeAPMData;
const hasInstances = totalUniqueInstanceCount > 0 || get(setupModeAPMData, 'detected.mightExist', false);
const allMonitoredByMetricbeat = totalUniqueInstanceCount > 0 &&
(totalUniqueFullyMigratedCount === totalUniqueInstanceCount || totalUniquePartiallyMigratedCount === totalUniqueInstanceCount);
const internalCollectionOn = totalUniquePartiallyMigratedCount > 0;
if (hasInstances && (!allMonitoredByMetricbeat || internalCollectionOn)) {
let tooltipText = null;
if (!allMonitoredByMetricbeat) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip.oneInternal', {
defaultMessage: `There's at least one server that isn't being monitored using Metricbeat. Click the flag
icon to visit the servers listing page and find out more information about the status of each server.`
});
}
else if (internalCollectionOn) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip.disableInternal', {
defaultMessage: `All servers are being monitored using Metricbeat but internal collection still needs to be turned
off. Click the flag icon to visit the servers listing page and disable internal collection.`
});
}
setupModeInstancesData = (
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
content={tooltipText}
>
<EuiLink onClick={goToInstances}>
<EuiIcon type="flag" color="warning"/>
</EuiLink>
</EuiToolTip>
</EuiFlexItem>
);
}
}
const setupModeData = get(setupMode.data, 'apm');
const setupModeTooltip = setupMode && setupMode.enabled
? (
<SetupModeTooltip
setupModeData={setupModeData}
badgeClickAction={goToInstances}
productName={APM_SYSTEM_ID}
/>
)
: null;
return (
<ClusterItemContainer
@ -97,7 +64,7 @@ export function ApmPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeAPMData}
setupModeData={setupModeData}
onClick={goToApm}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.apmPanel.overviewLinkAriaLabel', {
defaultMessage: 'APM Overview'
@ -164,7 +131,7 @@ export function ApmPanel(props) {
</h3>
</EuiTitle>
</EuiFlexItem>
{setupModeInstancesData}
{setupModeTooltip}
</EuiFlexGroup>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList type="column">

View file

@ -18,12 +18,12 @@ import {
EuiDescriptionListDescription,
EuiHorizontalRule,
EuiFlexGroup,
EuiToolTip,
EuiIcon
} from '@elastic/eui';
import { ClusterItemContainer, DisabledIfNoDataAndInSetupModeLink } from './helpers';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { SetupModeTooltip } from '../../setup_mode/tooltip';
import { BEATS_SYSTEM_ID } from '../../../../common/constants';
export function BeatsPanel(props) {
const { setupMode } = props;
@ -36,48 +36,16 @@ export function BeatsPanel(props) {
const goToBeats = () => props.changeUrl('beats');
const goToInstances = () => props.changeUrl('beats/beats');
const setupModeBeatsData = get(setupMode.data, 'beats');
let setupModeInstancesData = null;
if (setupMode.enabled && setupMode.data) {
const {
totalUniqueInstanceCount,
totalUniqueFullyMigratedCount,
totalUniquePartiallyMigratedCount
} = setupModeBeatsData;
const hasInstances = totalUniqueInstanceCount > 0 || get(setupModeBeatsData, 'detected.mightExist', false);
const allMonitoredByMetricbeat = totalUniqueInstanceCount > 0 &&
(totalUniqueFullyMigratedCount === totalUniqueInstanceCount || totalUniquePartiallyMigratedCount === totalUniqueInstanceCount);
const internalCollectionOn = totalUniquePartiallyMigratedCount > 0;
if (hasInstances && (!allMonitoredByMetricbeat || internalCollectionOn)) {
let tooltipText = null;
if (!allMonitoredByMetricbeat) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.beatsPanel.setupModeNodesTooltip.oneInternal', {
defaultMessage: `There's at least one instance that isn't being monitored using Metricbeat. Click the flag
icon to visit the instances listing page and find out more information about the status of each instance.`
});
}
else if (internalCollectionOn) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.beatsPanel.setupModeNodesTooltip.disableInternal', {
defaultMessage: `All instances are being monitored using Metricbeat but internal collection still needs to be turned
off. Click the flag icon to visit the instances listing page and disable internal collection.`
});
}
setupModeInstancesData = (
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
content={tooltipText}
>
<EuiLink onClick={goToInstances}>
<EuiIcon type="flag" color="warning"/>
</EuiLink>
</EuiToolTip>
</EuiFlexItem>
);
}
}
const setupModeData = get(setupMode.data, 'beats');
const setupModeTooltip = setupMode && setupMode.enabled
? (
<SetupModeTooltip
setupModeData={setupModeData}
productName={BEATS_SYSTEM_ID}
badgeClickAction={goToInstances}
/>
)
: null;
const beatTypes = props.beats.types.map((beat, index) => {
return [
@ -111,7 +79,7 @@ export function BeatsPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeBeatsData}
setupModeData={setupModeData}
onClick={goToBeats}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.beatsPanel.overviewLinkAriaLabel', {
defaultMessage: 'Beats Overview'
@ -174,7 +142,7 @@ export function BeatsPanel(props) {
</h3>
</EuiTitle>
</EuiFlexItem>
{setupModeInstancesData}
{setupModeTooltip}
</EuiFlexGroup>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList type="column">

View file

@ -27,12 +27,13 @@ import {
EuiBadge,
EuiToolTip,
EuiFlexGroup,
EuiIcon
} from '@elastic/eui';
import { LicenseText } from './license_text';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { Reason } from '../../logs/reason';
import { SetupModeTooltip } from '../../setup_mode/tooltip';
import { ELASTICSEARCH_SYSTEM_ID } from '../../../../common/constants';
const calculateShards = shards => {
const total = get(shards, 'total', 0);
@ -160,47 +161,16 @@ export function ElasticsearchPanel(props) {
const licenseText = <LicenseText license={props.license} showLicenseExpiration={props.showLicenseExpiration} />;
const setupModeElasticsearchData = get(setupMode.data, 'elasticsearch');
let setupModeNodesData = null;
if (setupMode.enabled && setupModeElasticsearchData) {
const {
totalUniqueInstanceCount,
totalUniqueFullyMigratedCount,
totalUniquePartiallyMigratedCount
} = setupModeElasticsearchData;
const allMonitoredByMetricbeat = totalUniqueInstanceCount > 0 &&
(totalUniqueFullyMigratedCount === totalUniqueInstanceCount || totalUniquePartiallyMigratedCount === totalUniqueInstanceCount);
const internalCollectionOn = totalUniquePartiallyMigratedCount > 0;
if (!allMonitoredByMetricbeat || internalCollectionOn) {
let tooltipText = null;
if (!allMonitoredByMetricbeat) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.elasticsearchPanel.setupModeNodesTooltip.oneInternal', {
defaultMessage: `There's at least one node that isn't being monitored using Metricbeat. Click the flag icon to visit the nodes
listing page and find out more information about the status of each node.`
});
}
else if (internalCollectionOn) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.elasticsearchPanel.setupModeNodesTooltip.disableInternal', {
defaultMessage: `All nodes are being monitored using Metricbeat but internal collection still needs to be turned off. Click the
flag icon to visit the nodes listing page and disable internal collection.`
});
}
setupModeNodesData = (
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
content={tooltipText}
>
<EuiLink onClick={goToNodes}>
<EuiIcon type="flag" color="warning"/>
</EuiLink>
</EuiToolTip>
</EuiFlexItem>
);
}
}
const setupModeData = get(setupMode.data, 'elasticsearch');
const setupModeTooltip = setupMode && setupMode.enabled
? (
<SetupModeTooltip
setupModeData={setupModeData}
productName={ELASTICSEARCH_SYSTEM_ID}
badgeClickAction={goToNodes}
/>
)
: null;
const showMlJobs = () => {
// if license doesn't support ML, then `ml === null`
@ -211,7 +181,7 @@ export function ElasticsearchPanel(props) {
<EuiDescriptionListTitle>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeElasticsearchData}
setupModeData={setupModeData}
href={gotoURL}
>
<FormattedMessage
@ -223,7 +193,7 @@ export function ElasticsearchPanel(props) {
<EuiDescriptionListDescription data-test-subj="esMlJobs">
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeElasticsearchData}
setupModeData={setupModeData}
href={gotoURL}
>
{props.ml.jobs}
@ -251,7 +221,7 @@ export function ElasticsearchPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeElasticsearchData}
setupModeData={setupModeData}
onClick={goToElasticsearch}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.esPanel.overviewLinkAriaLabel', {
defaultMessage: 'Elasticsearch Overview'
@ -314,7 +284,7 @@ export function ElasticsearchPanel(props) {
</h3>
</EuiTitle>
</EuiFlexItem>
{setupModeNodesData}
{setupModeTooltip}
</EuiFlexGroup>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList type="column">
@ -353,7 +323,7 @@ export function ElasticsearchPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeElasticsearchData}
setupModeData={setupModeData}
onClick={goToIndices}
data-test-subj="esNumberOfIndices"
aria-label={i18n.translate('xpack.monitoring.cluster.overview.esPanel.indicesCountLinkAriaLabel', {
@ -420,7 +390,7 @@ export function ElasticsearchPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeElasticsearchData}
setupModeData={setupModeData}
onClick={goToElasticsearch}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.esPanel.logsLinkAriaLabel', {
defaultMessage: 'Elasticsearch Logs'

View file

@ -19,11 +19,11 @@ import {
EuiDescriptionListTitle,
EuiDescriptionListDescription,
EuiHorizontalRule,
EuiIcon,
EuiToolTip
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { SetupModeTooltip } from '../../setup_mode/tooltip';
import { KIBANA_SYSTEM_ID } from '../../../../common/constants';
export function KibanaPanel(props) {
const setupMode = props.setupMode;
@ -39,47 +39,16 @@ export function KibanaPanel(props) {
const goToKibana = () => props.changeUrl('kibana');
const goToInstances = () => props.changeUrl('kibana/instances');
const setupModeKibanaData = get(setupMode.data, 'kibana');
let setupModeInstancesData = null;
if (setupMode.enabled && setupMode.data) {
const {
totalUniqueInstanceCount,
totalUniqueFullyMigratedCount,
totalUniquePartiallyMigratedCount
} = setupModeKibanaData;
const allMonitoredByMetricbeat = totalUniqueInstanceCount > 0 &&
(totalUniqueFullyMigratedCount === totalUniqueInstanceCount || totalUniquePartiallyMigratedCount === totalUniqueInstanceCount);
const internalCollectionOn = totalUniquePartiallyMigratedCount > 0;
if (!allMonitoredByMetricbeat || internalCollectionOn) {
let tooltipText = null;
if (!allMonitoredByMetricbeat) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.kibanaPanel.setupModeNodesTooltip.oneInternal', {
defaultMessage: `There's at least one instance that isn't being monitored using Metricbeat. Click the flag
icon to visit the instances listing page and find out more information about the status of each instance.`
});
}
else if (internalCollectionOn) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.kibanaPanel.setupModeNodesTooltip.disableInternal', {
defaultMessage: `All instances are being monitored using Metricbeat but internal collection still needs to be turned
off. Click the flag icon to visit the instances listing page and disable internal collection.`
});
}
setupModeInstancesData = (
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
content={tooltipText}
>
<EuiLink onClick={goToInstances}>
<EuiIcon type="flag" color="warning"/>
</EuiLink>
</EuiToolTip>
</EuiFlexItem>
);
}
}
const setupModeData = get(setupMode.data, 'kibana');
const setupModeTooltip = setupMode && setupMode.enabled
? (
<SetupModeTooltip
setupModeData={setupModeData}
productName={KIBANA_SYSTEM_ID}
badgeClickAction={goToInstances}
/>
)
: null;
return (
<ClusterItemContainer
@ -97,7 +66,7 @@ export function KibanaPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeKibanaData}
setupModeData={setupModeData}
onClick={goToKibana}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.kibanaPanel.overviewLinkAriaLabel', {
defaultMessage: 'Kibana Overview'
@ -164,7 +133,7 @@ export function KibanaPanel(props) {
</h3>
</EuiTitle>
</EuiFlexItem>
{setupModeInstancesData}
{setupModeTooltip}
</EuiFlexGroup>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList type="column">

View file

@ -7,7 +7,7 @@
import React from 'react';
import { formatNumber } from 'plugins/monitoring/lib/format_number';
import { ClusterItemContainer, BytesPercentageUsage, DisabledIfNoDataAndInSetupModeLink } from './helpers';
import { LOGSTASH } from '../../../../common/constants';
import { LOGSTASH, LOGSTASH_SYSTEM_ID } from '../../../../common/constants';
import {
EuiFlexGrid,
@ -21,12 +21,11 @@ import {
EuiDescriptionListDescription,
EuiHorizontalRule,
EuiIconTip,
EuiToolTip,
EuiIcon
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { SetupModeTooltip } from '../../setup_mode/tooltip';
export function LogstashPanel(props) {
const { setupMode } = props;
@ -42,48 +41,16 @@ export function LogstashPanel(props) {
const goToNodes = () => props.changeUrl('logstash/nodes');
const goToPipelines = () => props.changeUrl('logstash/pipelines');
const setupModeLogstashData = get(setupMode.data, 'logstash');
let setupModeInstancesData = null;
if (setupMode.enabled && setupMode.data) {
const {
totalUniqueInstanceCount,
totalUniqueFullyMigratedCount,
totalUniquePartiallyMigratedCount
} = setupModeLogstashData;
const hasInstances = totalUniqueInstanceCount > 0 || get(setupModeLogstashData, 'detected.mightExist', false);
const allMonitoredByMetricbeat = totalUniqueInstanceCount > 0 &&
(totalUniqueFullyMigratedCount === totalUniqueInstanceCount || totalUniquePartiallyMigratedCount === totalUniqueInstanceCount);
const internalCollectionOn = totalUniquePartiallyMigratedCount > 0;
if (hasInstances && (!allMonitoredByMetricbeat || internalCollectionOn)) {
let tooltipText = null;
if (!allMonitoredByMetricbeat) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.logstashPanel.setupModeNodesTooltip.oneInternal', {
defaultMessage: `There's at least one node that isn't being monitored using Metricbeat. Click the flag
icon to visit the nodes listing page and find out more information about the status of each node.`
});
}
else if (internalCollectionOn) {
tooltipText = i18n.translate('xpack.monitoring.cluster.overview.logstashPanel.setupModeNodesTooltip.disableInternal', {
defaultMessage: `All nodes are being monitored using Metricbeat but internal collection still needs to be turned
off. Click the flag icon to visit the nodes listing page and disable internal collection.`
});
}
setupModeInstancesData = (
<EuiFlexItem grow={false}>
<EuiToolTip
position="top"
content={tooltipText}
>
<EuiLink onClick={goToNodes}>
<EuiIcon type="flag" color="warning"/>
</EuiLink>
</EuiToolTip>
</EuiFlexItem>
);
}
}
const setupModeData = get(setupMode.data, 'logstash');
const setupModeTooltip = setupMode && setupMode.enabled
? (
<SetupModeTooltip
setupModeData={setupModeData}
productName={LOGSTASH_SYSTEM_ID}
badgeClickAction={goToNodes}
/>
)
: null;
return (
<ClusterItemContainer
@ -100,7 +67,7 @@ export function LogstashPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeLogstashData}
setupModeData={setupModeData}
onClick={goToLogstash}
aria-label={i18n.translate('xpack.monitoring.cluster.overview.logstashPanel.overviewLinkAriaLabel', {
defaultMessage: 'Logstash Overview'
@ -163,7 +130,7 @@ export function LogstashPanel(props) {
</h3>
</EuiTitle>
</EuiFlexItem>
{setupModeInstancesData}
{setupModeTooltip}
</EuiFlexGroup>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList type="column">
@ -198,7 +165,7 @@ export function LogstashPanel(props) {
<h3>
<DisabledIfNoDataAndInSetupModeLink
setupModeEnabled={setupMode.enabled}
setupModeData={setupModeLogstashData}
setupModeData={setupModeData}
onClick={goToPipelines}
data-test-subj="lsPipelines"
aria-label={i18n.translate(

View file

@ -47,14 +47,14 @@ export function ClusterStatus({ stats }) {
},
{
label: i18n.translate('xpack.monitoring.elasticsearch.clusterStatus.totalShardsLabel', {
defaultMessage: 'Total Shards'
defaultMessage: 'Total shards'
}),
value: totalShards,
'data-test-subj': 'totalShards'
},
{
label: i18n.translate('xpack.monitoring.elasticsearch.clusterStatus.unassignedShardsLabel', {
defaultMessage: 'Unassigned Shards'
defaultMessage: 'Unassigned shards'
}),
value: unassignedShards,
'data-test-subj': 'unassignedShards'

View file

@ -44,7 +44,7 @@ export function IndexDetailStatus({ stats }) {
},
{
label: i18n.translate('xpack.monitoring.elasticsearch.indexDetailStatus.totalShardsTitle', {
defaultMessage: 'Total Shards'
defaultMessage: 'Total shards'
}),
value: formatMetric(totalShards, 'int_commas'),
'data-test-subj': 'totalShards'
@ -53,7 +53,7 @@ export function IndexDetailStatus({ stats }) {
label: i18n.translate(
'xpack.monitoring.elasticsearch.indexDetailStatus.unassignedShardsTitle',
{
defaultMessage: 'Unassigned Shards'
defaultMessage: 'Unassigned shards'
}
),
value: formatMetric(unassignedShards, 'int_commas'),

View file

@ -10,6 +10,7 @@ import { extractIp } from '../../../lib/extract_ip'; // TODO this is only used f
import { ClusterStatus } from '../cluster_status';
import { EuiMonitoringTable } from '../../table';
import { MetricCell, OfflineCell } from './cells';
import { SetupModeBadge } from '../../setup_mode/badge';
import {
EuiLink,
EuiToolTip,
@ -24,9 +25,11 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import { ELASTICSEARCH_SYSTEM_ID } from '../../../../common/constants';
import { ListingCallOut } from '../../setup_mode/listing_callout';
const getSortHandler = (type) => (item) => _.get(item, [type, 'summary', 'lastVal']);
const getColumns = (showCgroupMetricsElasticsearch, setupMode) => {
const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid) => {
const cols = [];
const cpuUsageColumnTitle = i18n.translate('xpack.monitoring.elasticsearch.nodes.cpuUsageColumnTitle', {
@ -50,9 +53,26 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode) => {
</EuiLink>
);
let setupModeStatus = null;
if (setupMode && setupMode.enabled) {
const list = _.get(setupMode, 'data.byUuid', {});
const status = list[node.resolver] || {};
const instance = {
uuid: node.resolver,
name: node.name
};
setupModeStatus = (
<div className="monTableCell__setupModeStatus">
<SetupModeBadge
setupMode={setupMode}
status={status}
instance={instance}
productName={ELASTICSEARCH_SYSTEM_ID}
clusterUuid={clusterUuid}
/>
</div>
);
if (status.isNetNewUser) {
nameLink = value;
}
@ -77,6 +97,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode) => {
<div className="monTableCell__transportAddress">
{extractIp(node.transport_address)}
</div>
{setupModeStatus}
</div>
);
}
@ -223,7 +244,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode) => {
export function ElasticsearchNodes({ clusterStatus, showCgroupMetricsElasticsearch, ...props }) {
const { sorting, pagination, onTableChange, clusterUuid, setupMode } = props;
const columns = getColumns(showCgroupMetricsElasticsearch, setupMode);
const columns = getColumns(showCgroupMetricsElasticsearch, setupMode, clusterUuid);
// Merge the nodes data with the setup data if enabled
const nodes = props.nodes || [];
@ -238,70 +259,89 @@ export function ElasticsearchNodes({ clusterStatus, showCgroupMetricsElasticsear
nodes.push(...Object.entries(setupMode.data.byUuid)
.reduce((nodes, [nodeUuid, instance]) => {
if (!nodesByUuid[nodeUuid]) {
if (!nodesByUuid[nodeUuid] && instance.node) {
nodes.push(instance.node);
}
return nodes;
}, []));
}
let netNewUserMessage = null;
let disableInternalCollectionForMigrationMessage = null;
if (setupMode.data) {
// Think net new user scenario
const hasInstances = setupMode.data.totalUniqueInstanceCount > 0;
if (hasInstances && setupMode.data.totalUniquePartiallyMigratedCount === setupMode.data.totalUniqueInstanceCount) {
const finishMigrationAction = _.get(setupMode.meta, 'liveClusterUuid') === clusterUuid
? setupMode.shortcutToFinishMigration
: setupMode.openFlyout;
let setupModeCallout = null;
if (setupMode.enabled && setupMode.data) {
setupModeCallout = (
<ListingCallOut
setupModeData={setupMode.data}
useNodeIdentifier
productName={ELASTICSEARCH_SYSTEM_ID}
customRenderer={() => {
const customRenderResponse = {
shouldRender: false,
componentToRender: null
};
disableInternalCollectionForMigrationMessage = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionTitle', {
defaultMessage: 'Disable internal collection to finish the migration',
})}
color="warning"
iconType="help"
>
<p>
{i18n.translate('xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionDescription', {
defaultMessage: `All of your Elasticsearch servers are monitored using Metricbeat,
but you need to disable internal collection to finish the migration.`
})}
</p>
<EuiButton onClick={finishMigrationAction} size="s" color="warning" fill>
{i18n.translate('xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionMigrationButtonLabel', {
defaultMessage: 'Disable and finish migration'
})}
</EuiButton>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
else if (!hasInstances) {
netNewUserMessage = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserTitle', {
defaultMessage: 'No monitoring data detected',
})}
color="danger"
iconType="cross"
>
<p>
{i18n.translate('xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserDescription', {
defaultMessage: `We did not detect any monitoring data, but we did detect the following Elasticsearch nodes.
Each detected node is listed below along with a Setup button. Clicking this button will guide you through
the process of enabling monitoring for each node.`
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
const isNetNewUser = setupMode.data.totalUniqueInstanceCount === 0;
const hasNoInstances = setupMode.data.totalUniqueInternallyCollectedCount === 0
&& setupMode.data.totalUniqueFullyMigratedCount === 0
&& setupMode.data.totalUniquePartiallyMigratedCount === 0;
if (isNetNewUser || hasNoInstances) {
customRenderResponse.shouldRender = true;
customRenderResponse.componentToRender = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.elasticsearch.nodes.metricbeatMigration.detectedNodeTitle', {
defaultMessage: 'Elasticsearch node detected',
})}
color={setupMode.data.totalUniqueInstanceCount > 0 ? 'danger' : 'warning'}
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.elasticsearch.nodes.metricbeatMigration.detectedNodeDescription', {
defaultMessage: `The following nodes are not monitored. Click 'Monitor with Metricbeat' below to start monitoring.`,
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
else if (setupMode.data.totalUniquePartiallyMigratedCount === setupMode.data.totalUniqueInstanceCount) {
const finishMigrationAction = _.get(setupMode.meta, 'liveClusterUuid') === clusterUuid
? setupMode.shortcutToFinishMigration
: setupMode.openFlyout;
customRenderResponse.shouldRender = true;
customRenderResponse.componentToRender = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.elasticsearch.nodes.metricbeatMigration.disableInternalCollectionTitle', {
defaultMessage: 'Metricbeat is now monitoring your Elasticsearch nodes',
})}
color="warning"
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.elasticsearch.nodes.metricbeatMigration.disableInternalCollectionDescription', {
defaultMessage: `Disable self monitoring to finish the migration.`
})}
</p>
<EuiButton onClick={finishMigrationAction} size="s" color="warning" fill>
{i18n.translate(
'xpack.monitoring.elasticsearch.nodes.metricbeatMigration.disableInternalCollectionMigrationButtonLabel', {
defaultMessage: 'Disable self monitoring'
}
)}
</EuiButton>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
return customRenderResponse;
}}
/>
);
}
function renderClusterStatus() {
@ -322,8 +362,7 @@ export function ElasticsearchNodes({ clusterStatus, showCgroupMetricsElasticsear
<EuiPage>
<EuiPageBody>
{renderClusterStatus()}
{disableInternalCollectionForMigrationMessage}
{netNewUserMessage}
{setupModeCallout}
<EuiPageContent>
<EuiMonitoringTable
className="elasticsearchNodesTable"
@ -332,11 +371,7 @@ export function ElasticsearchNodes({ clusterStatus, showCgroupMetricsElasticsear
sorting={sorting}
pagination={pagination}
setupMode={setupMode}
uuidField="resolver"
nameField="name"
setupNewButtonLabel={i18n.translate('xpack.monitoring.elasticsearch.metricbeatMigration.setupNewButtonLabel', {
defaultMessage: 'Setup monitoring for new Elasticsearch node'
})}
productName={ELASTICSEARCH_SYSTEM_ID}
search={{
box: {
incremental: true,

View file

@ -12,7 +12,7 @@ import {
EuiPanel,
EuiSpacer,
EuiLink,
EuiCallOut,
EuiCallOut
} from '@elastic/eui';
import { capitalize, get } from 'lodash';
import { ClusterStatus } from '../cluster_status';
@ -22,6 +22,9 @@ import { StatusIcon } from 'plugins/monitoring/components/status_icon';
import { formatMetric, formatNumber } from '../../../lib/format_number';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { SetupModeBadge } from '../../setup_mode/badge';
import { KIBANA_SYSTEM_ID } from '../../../../common/constants';
import { ListingCallOut } from '../../setup_mode/listing_callout';
const getColumns = (kbnUrl, scope, setupMode) => {
const columns = [
@ -31,25 +34,50 @@ const getColumns = (kbnUrl, scope, setupMode) => {
}),
field: 'name',
render: (name, kibana) => {
let setupModeStatus = null;
if (setupMode && setupMode.enabled) {
const list = get(setupMode, 'data.byUuid', {});
const status = list[get(kibana, 'kibana.uuid')] || {};
const uuid = get(kibana, 'kibana.uuid');
const status = list[uuid] || {};
const instance = {
uuid,
name: kibana.name
};
setupModeStatus = (
<div className="monTableCell__setupModeStatus">
<SetupModeBadge
setupMode={setupMode}
status={status}
instance={instance}
productName={KIBANA_SYSTEM_ID}
/>
</div>
);
if (status.isNetNewUser) {
return name;
return (
<div>
{name}
{setupModeStatus}
</div>
);
}
}
return (
<EuiLink
onClick={() => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/kibana/instances/${kibana.kibana.uuid}`);
});
}}
data-test-subj={`kibanaLink-${name}`}
>
{ name }
</EuiLink>
<div>
<EuiLink
onClick={() => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/kibana/instances/${kibana.kibana.uuid}`);
});
}}
data-test-subj={`kibanaLink-${name}`}
>
{ name }
</EuiLink>
{setupModeStatus}
</div>
);
}
},
@ -152,7 +180,7 @@ export class KibanaInstances extends PureComponent {
onTableChange
} = this.props;
let netNewUserMessage = null;
let setupModeCallOut = null;
// Merge the instances data with the setup data if enabled
const instances = this.props.instances || [];
if (setupMode.enabled && setupMode.data) {
@ -177,29 +205,45 @@ export class KibanaInstances extends PureComponent {
return instances;
}, []));
const hasInstances = setupMode.data.totalUniqueInstanceCount > 0;
if (!hasInstances) {
netNewUserMessage = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserTitle', {
defaultMessage: 'No monitoring data detected',
})}
color="danger"
iconType="cross"
>
<p>
{i18n.translate('xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserDescription', {
defaultMessage: `We did not detect any monitoring data, but we did detect the following Kibana instance.
This detected instance is listed below along with a Setup button. Clicking this button will guide you through
the process of enabling monitoring for this instance.`
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
setupModeCallOut = (
<ListingCallOut
setupModeData={setupMode.data}
useNodeIdentifier={false}
productName={KIBANA_SYSTEM_ID}
customRenderer={() => {
const customRenderResponse = {
shouldRender: false,
componentToRender: null
};
const hasInstances = setupMode.data.totalUniqueInstanceCount > 0;
if (!hasInstances) {
customRenderResponse.shouldRender = true;
customRenderResponse.componentToRender = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.kibana.instances.metricbeatMigration.detectedNodeTitle', {
defaultMessage: 'Kibana instance detected',
})}
color="warning"
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.kibana.instances.metricbeatMigration.detectedNodeDescription', {
defaultMessage: `The following instances are not monitored.
Click 'Monitor with Metricbeat' below to start monitoring.`,
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
return customRenderResponse;
}}
/>
);
}
const dataFlattened = instances.map(item => ({
@ -216,7 +260,7 @@ export class KibanaInstances extends PureComponent {
<ClusterStatus stats={clusterStatus} />
</EuiPanel>
<EuiSpacer size="m" />
{netNewUserMessage}
{setupModeCallOut}
<EuiPageContent>
<EuiMonitoringTable
className="kibanaInstancesTable"
@ -225,11 +269,7 @@ export class KibanaInstances extends PureComponent {
sorting={sorting}
pagination={pagination}
setupMode={setupMode}
uuidField="kibana.uuid"
nameField="name"
setupNewButtonLabel={i18n.translate('xpack.monitoring.kibana.metricbeatMigration.setupNewButtonLabel', {
defaultMessage: 'Setup monitoring for new Kibana instance'
})}
productName={KIBANA_SYSTEM_ID}
search={{
box: {
incremental: true,

View file

@ -55,7 +55,7 @@ exports[`Listing should render with certain data pieces missing 1`] = `
],
}
}
nameField="name"
productName="logstash"
rows={
Array [
Object {
@ -82,7 +82,6 @@ exports[`Listing should render with certain data pieces missing 1`] = `
}
}
setupMode={Object {}}
setupNewButtonLabel="Setup monitoring for new Logstash node"
sorting={
Object {
"sort": Object {
@ -93,7 +92,6 @@ exports[`Listing should render with certain data pieces missing 1`] = `
},
}
}
uuidField="logstash.uuid"
/>
`;
@ -152,7 +150,7 @@ exports[`Listing should render with expected props 1`] = `
],
}
}
nameField="name"
productName="logstash"
rows={
Array [
Object {
@ -211,7 +209,6 @@ exports[`Listing should render with expected props 1`] = `
}
}
setupMode={Object {}}
setupNewButtonLabel="Setup monitoring for new Logstash node"
sorting={
Object {
"sort": Object {
@ -222,6 +219,5 @@ exports[`Listing should render with expected props 1`] = `
},
}
}
uuidField="logstash.uuid"
/>
`;

View file

@ -4,18 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { PureComponent, Fragment } from 'react';
import React, { PureComponent } from 'react';
import { get } from 'lodash';
import { EuiPage, EuiLink, EuiPageBody, EuiPageContent, EuiPanel, EuiSpacer, EuiCallOut } from '@elastic/eui';
import { EuiPage, EuiLink, EuiPageBody, EuiPageContent, EuiPanel, EuiSpacer } from '@elastic/eui';
import { formatPercentageUsage, formatNumber } from '../../../lib/format_number';
import { ClusterStatus } from '..//cluster_status';
import { EuiMonitoringTable } from '../../table';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { LOGSTASH_SYSTEM_ID } from '../../../../common/constants';
import { SetupModeBadge } from '../../setup_mode/badge';
import { ListingCallOut } from '../../setup_mode/listing_callout';
export class Listing extends PureComponent {
getColumns() {
const { kbnUrl, scope } = this.props.angular;
const setupMode = this.props.setupMode;
return [
{
@ -24,24 +28,49 @@ export class Listing extends PureComponent {
}),
field: 'name',
sortable: true,
render: (name, node) => (
<div>
render: (name, node) => {
let setupModeStatus = null;
if (setupMode && setupMode.enabled) {
const list = get(setupMode, 'data.byUuid', {});
const uuid = get(node, 'logstash.uuid');
const status = list[uuid] || {};
const instance = {
uuid,
name: node.name
};
setupModeStatus = (
<div className="monTableCell__setupModeStatus">
<SetupModeBadge
setupMode={setupMode}
status={status}
instance={instance}
productName={LOGSTASH_SYSTEM_ID}
/>
</div>
);
}
return (
<div>
<EuiLink
onClick={() => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/logstash/node/${node.logstash.uuid}`);
});
}}
>
{name}
</EuiLink>
<div>
<EuiLink
onClick={() => {
scope.$evalAsync(() => {
kbnUrl.changePath(`/logstash/node/${node.logstash.uuid}`);
});
}}
>
{name}
</EuiLink>
</div>
<div>
{node.logstash.http_address}
</div>
{setupModeStatus}
</div>
<div>
{node.logstash.http_address}
</div>
</div>
)
);
}
},
{
name: i18n.translate('xpack.monitoring.logstash.nodes.cpuUsageTitle', {
@ -124,26 +153,14 @@ export class Listing extends PureComponent {
version: get(item, 'logstash.version', 'N/A'),
}));
let netNewUserMessage = null;
if (setupMode.enabled && setupMode.data && get(setupMode.data, 'detected.mightExist')) {
netNewUserMessage = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.logstash.nodes.metribeatMigration.netNewUserTitle', {
defaultMessage: 'No monitoring data detected',
})}
color="warning"
iconType="help"
>
<p>
{i18n.translate('xpack.monitoring.logstash.nodes.metribeatMigration.netNewUserDescription', {
defaultMessage: `Based on your indices, we think you might have a Logstash node. Click the 'Setup monitoring'
button below to start monitoring this node.`
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
let setupModeCallOut = null;
if (setupMode.enabled && setupMode.data) {
setupModeCallOut = (
<ListingCallOut
setupModeData={setupMode.data}
useNodeIdentifier
productName={LOGSTASH_SYSTEM_ID}
/>
);
}
@ -154,17 +171,13 @@ export class Listing extends PureComponent {
<ClusterStatus stats={stats} />
</EuiPanel>
<EuiSpacer size="m" />
{netNewUserMessage}
{setupModeCallOut}
<EuiPageContent>
<EuiMonitoringTable
className="logstashNodesTable"
rows={flattenedData}
setupMode={setupMode}
uuidField="logstash.uuid"
nameField="name"
setupNewButtonLabel={i18n.translate('xpack.monitoring.logstash.metricbeatMigration.setupNewButtonLabel', {
defaultMessage: 'Setup monitoring for new Logstash node'
})}
productName={LOGSTASH_SYSTEM_ID}
columns={columns}
sorting={{
...sorting,

View file

@ -26,7 +26,7 @@ import {
} from '@elastic/eui';
import { getInstructionSteps } from '../instruction_steps';
import { Storage } from 'ui/storage';
import { STORAGE_KEY, ELASTICSEARCH_CUSTOM_ID } from '../../../../common/constants';
import { STORAGE_KEY, ELASTICSEARCH_SYSTEM_ID, KIBANA_SYSTEM_ID } from '../../../../common/constants';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
@ -34,8 +34,8 @@ import {
INSTRUCTION_STEP_ENABLE_METRICBEAT,
INSTRUCTION_STEP_DISABLE_INTERNAL
} from '../constants';
import { KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID } from '../../../../../telemetry/common/constants';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getIdentifier, formatProductName } from '../../setup_mode/formatting';
const storage = new Storage(window.localStorage);
const ES_MONITORING_URL_KEY = `${STORAGE_KEY}.mb_migration.esMonitoringUrl`;
@ -93,11 +93,11 @@ export class Flyout extends Component {
<EuiFormRow
fullWidth
label={i18n.translate('xpack.monitoring.metricbeatMigration.flyout.step1.monitoringUrlLabel', {
defaultMessage: 'Monitoring cluster URL'
defaultMessage: 'URL of monitoring cluster'
})}
helpText={i18n.translate('xpack.monitoring.metricbeatMigration.flyout.step1.monitoringUrlHelpText', {
defaultMessage: `This is typically a single instance, but if you have multiple, enter all of instance urls comma-separated.
Keep in mind that the running metricbeat instance will need to be able to communicate with these Elasticsearch servers.`
defaultMessage: `Typically a single URL. If multiple URLs, separate with a comma.
The running Metricbeat instance must be able to communicate with these Elasticsearch servers.`
})}
>
<EuiFieldText
@ -110,9 +110,10 @@ export class Flyout extends Component {
);
case INSTRUCTION_STEP_ENABLE_METRICBEAT:
case INSTRUCTION_STEP_DISABLE_INTERNAL:
const esMonitoringUrls = esMonitoringUrl.split(',').map(url => `"${url}"`);
const instructionSteps = getInstructionSteps(productName, product, activeStep, meta, {
doneWithMigration: onClose,
esMonitoringUrl,
esMonitoringUrl: esMonitoringUrls,
hasCheckedStatus: checkedStatusByStep[activeStep],
});
@ -142,7 +143,7 @@ export class Flyout extends Component {
let willShowNextButton = activeStep !== INSTRUCTION_STEP_DISABLE_INTERNAL;
if (activeStep === INSTRUCTION_STEP_ENABLE_METRICBEAT) {
if (productName === ELASTICSEARCH_CUSTOM_ID) {
if (productName === ELASTICSEARCH_SYSTEM_ID) {
willShowNextButton = false;
// ES can be fully migrated for net new users
willDisableDoneButton = !product.isPartiallyMigrated && !product.isFullyMigrated;
@ -222,7 +223,7 @@ export class Flyout extends Component {
if (productName === KIBANA_SYSTEM_ID) {
documentationUrl = `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/monitoring-metricbeat.html`;
}
else if (productName === ELASTICSEARCH_CUSTOM_ID) {
else if (productName === ELASTICSEARCH_SYSTEM_ID) {
documentationUrl = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`;
}
@ -233,7 +234,9 @@ export class Flyout extends Component {
return (
<EuiText size="s">
<EuiLink href={documentationUrl} target="_blank">
Read more about this migration.
{i18n.translate('xpack.monitoring.metricbeatMigration.flyout.learnMore', {
defaultMessage: 'Learn about why.'
})}
</EuiLink>
</EuiText>
);
@ -242,59 +245,29 @@ export class Flyout extends Component {
render() {
const { onClose, instance, productName, product } = this.props;
let instanceType = null;
let instanceName = instance ? instance.name : null;
if (productName === KIBANA_SYSTEM_ID) {
instanceType = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.kibanaInstance', {
defaultMessage: 'instance',
});
}
else if (productName === ELASTICSEARCH_CUSTOM_ID) {
if (instance) {
instanceType = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.elasticsearchNode', {
defaultMessage: 'node',
});
}
else {
instanceName = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.elasticsearchNodesTitle', {
defaultMessage: 'Elasticsearch nodes',
});
}
}
const instanceIdentifier = getIdentifier(productName);
const instanceName = (instance && instance.name) || formatProductName(productName);
let title = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.flyoutTitle', {
defaultMessage: 'Migrate {instanceName} {instanceType} to Metricbeat',
defaultMessage: 'Monitor `{instanceName}` {instanceIdentifier} with Metricbeat',
values: {
instanceName,
instanceType
instanceIdentifier
}
});
if (product.isNetNewUser) {
title = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.flyoutTitleNewUser', {
defaultMessage: 'Monitor {instanceName} {instanceType} with Metricbeat',
defaultMessage: 'Monitor {instanceName} {instanceIdentifier} with Metricbeat',
values: {
instanceName,
instanceType
instanceIdentifier,
instanceName
}
});
}
let noClusterUuidPrompt = null;
if (product.isFullyMigrated && product.clusterUuid === null) {
const nodeText = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.node', {
defaultMessage: 'node'
});
const instanceText = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.instance', {
defaultMessage: 'instance'
});
let typeText = nodeText;
if (productName === BEATS_SYSTEM_ID) {
typeText = instanceText;
}
noClusterUuidPrompt = (
<Fragment>
<EuiCallOut
@ -310,11 +283,11 @@ export class Flyout extends Component {
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.flyout.noClusterUuidDescription"
defaultMessage="This {productName} {typeText} is not connected to an Elasticsearch cluster so once fully migrated,
this {productName} {typeText} will appear in the Standalone cluster instead of this one. {link}"
defaultMessage="This {productName} {instanceIdentifier} is not connected to an Elasticsearch cluster so once fully migrated,
this {productName} {instanceIdentifier} will appear in the Standalone cluster instead of this one. {link}"
values={{
productName,
typeText,
instanceIdentifier,
link: (
<EuiLink href={`#/overview?_g=(cluster_uuid:__standalone_cluster__)`} target="_blank">
Click here to view the Standalone cluster.
@ -330,10 +303,10 @@ export class Flyout extends Component {
'xpack.monitoring.metricbeatMigration.flyout.noClusterUuidCheckboxLabel',
{
defaultMessage: `Yes, I understand that I will need to look in the Standalone cluster for
this {productName} {typeText}.`,
this {productName} {instanceIdentifier}.`,
values: {
productName,
typeText
instanceIdentifier
}
}
)}
@ -357,13 +330,14 @@ export class Flyout extends Component {
{title}
</h2>
</EuiTitle>
{this.getDocumentationTitle()}
{/* Remove until we have a why article: https://github.com/elastic/kibana/pull/45799#issuecomment-536778656 */}
{/* {this.getDocumentationTitle()} */}
</EuiFlyoutHeader>
<EuiFlyoutBody>
{this.renderActiveStep()}
{noClusterUuidPrompt}
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlyoutFooter style={{ marginBottom: '64px' }}>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButtonEmpty

View file

@ -1,10 +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 { i18n } from '@kbn/i18n';
export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.apmInstructions.statusTitle', {
defaultMessage: `Migration status`
});

View file

@ -8,27 +8,16 @@ import React, { Fragment } from 'react';
import {
EuiSpacer,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../../common/constants';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle } from './common_apm_instructions';
import { getDisableStatusStep } from '../common_instructions';
export function getApmInstructionsForDisablingInternalCollection(product, meta, {
checkForMigrationStatus,
checkingMigrationStatus,
hasCheckedStatus,
autoCheckIntervalInMs,
}) {
export function getApmInstructionsForDisablingInternalCollection(product, meta) {
const disableInternalCollectionStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.title', {
defaultMessage: 'Disable internal collection of the APM server\'s monitoring metrics'
defaultMessage: 'Disable self monitoring of the APM server\'s monitoring metrics'
}),
children: (
<Fragment>
@ -65,130 +54,7 @@ export function getApmInstructionsForDisablingInternalCollection(product, meta,
)
};
let migrationStatusStep = null;
if (!product || !product.isFullyMigrated) {
let status = null;
if (hasCheckedStatus) {
let lastInternallyCollectedMessage = '';
// It is possible that, during the migration steps, products are not reporting
// monitoring data for a period of time outside the window of our server-side check
// and this is most likely temporary so we want to be defensive and not error out
// and hopefully wait for the next check and this state will be self-corrected.
if (product) {
const lastInternallyCollectedTimestamp = product.lastInternallyCollectedTimestamp || product.lastTimestamp;
const secondsSinceLastInternalCollectionLabel =
formatTimestampToDuration(lastInternallyCollectedTimestamp, CALCULATE_DURATION_SINCE);
lastInternallyCollectedMessage = (<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.partiallyMigratedStatusDescription"
defaultMessage="Last internal collection occurred {secondsSinceLastInternalCollectionLabel} ago."
values={{
secondsSinceLastInternalCollectionLabel,
}}
/>);
}
status = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.apmInstructions.partiallyMigratedStatusTitle',
{
defaultMessage: `We still see data coming from internal collection of this APM server.`
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.partiallyMigratedStatusDescription"
defaultMessage="Note that it can take up to {secondsAgo} seconds to detect, but
we will continuously check every {timePeriod} seconds in the background."
values={{
secondsAgo: meta.secondsAgo,
timePeriod: autoCheckIntervalInMs / 1000,
}}
/>
</p>
<p>
{lastInternallyCollectedMessage}
</p>
</EuiCallOut>
</Fragment>
);
}
let buttonLabel;
if (checkingMigrationStatus) {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.checkingStatusButtonLabel',
{
defaultMessage: 'Checking...'
}
);
} else {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.checkStatusButtonLabel',
{
defaultMessage: 'Check'
}
);
}
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<Fragment>
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiText>
<p>
{i18n.translate(
'xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.statusDescription',
{
defaultMessage: 'Check that no documents are coming from internal collection.'
}
)}
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={checkForMigrationStatus} isDisabled={checkingMigrationStatus}>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{status}
</Fragment>
)
};
}
else {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.fullyMigratedStatusDescription"
defaultMessage="We are not seeing any documents from internal collection. Migration complete!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getDisableStatusStep(product, meta);
return [
disableInternalCollectionStep,

View file

@ -9,50 +9,20 @@ import {
EuiSpacer,
EuiCodeBlock,
EuiLink,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle } from './common_apm_instructions';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getMigrationStatusStep, getSecurityStep } from '../common_instructions';
export function getApmInstructionsForEnablingMetricbeat(product, _meta, {
esMonitoringUrl,
}) {
const securitySetup = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
color="warning"
iconType="help"
title={(
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.metricbeatSecuritySetup"
defaultMessage="If security features are enabled, there may be more setup required.{link}"
values={{
link: (
<Fragment>
{` `}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/apm/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`}
target="_blank"
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.metricbeatSecuritySetupLinkText"
defaultMessage="View more information."
/>
</EuiLink>
</Fragment>
)
}}
/>
</EuiText>
)}
/>
</Fragment>
const securitySetup = getSecurityStep(
`${ELASTIC_WEBSITE_URL}guide/en/apm/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`
);
const installMetricbeatStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.apmInstructions.installMetricbeatTitle', {
defaultMessage: 'Install Metricbeat on the same server as the APM server'
@ -66,7 +36,7 @@ export function getApmInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.installMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -130,7 +100,7 @@ export function getApmInstructionsForEnablingMetricbeat(product, _meta, {
isCopyable
>
{`output.elasticsearch:
hosts: ["${esMonitoringUrl}"] ## Monitoring cluster
hosts: [${esMonitoringUrl}] ## Monitoring cluster
# Optional protocol and basic auth credentials.
#protocol: "https"
@ -157,7 +127,7 @@ export function getApmInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.startMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -165,48 +135,7 @@ export function getApmInstructionsForEnablingMetricbeat(product, _meta, {
)
};
let migrationStatusStep = null;
if (product.isInternalCollector || product.isNetNewUser) {
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.apmInstructions.isInternalCollectorStatusTitle', {
defaultMessage: `We have not detected any monitoring data coming from Metricbeat for this APM server.
We will continuously check in the background.`,
})}
/>
)
};
}
else if (product.isPartiallyMigrated || product.isFullyMigrated) {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.apmInstructions.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.apmInstructions.fullyMigratedStatusDescription"
defaultMessage="We are now seeing monitoring data shipping from Metricbeat!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getMigrationStatusStep(product);
return [
installMetricbeatStep,

View file

@ -3,11 +3,6 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.beatsInstructions.statusTitle', {
defaultMessage: `Migration status`
});
export const UNDETECTED_BEAT_TYPE = 'beat';
export const DEFAULT_BEAT_FOR_URLS = 'metricbeat';

View file

@ -8,28 +8,18 @@ import React, { Fragment } from 'react';
import {
EuiSpacer,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../../common/constants';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle, UNDETECTED_BEAT_TYPE } from './common_beats_instructions';
import { UNDETECTED_BEAT_TYPE } from './common_beats_instructions';
import { getDisableStatusStep } from '../common_instructions';
export function getBeatsInstructionsForDisablingInternalCollection(product, meta, {
checkForMigrationStatus,
checkingMigrationStatus,
hasCheckedStatus,
autoCheckIntervalInMs,
}) {
export function getBeatsInstructionsForDisablingInternalCollection(product, meta) {
const beatType = product.beatType;
const disableInternalCollectionStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.title', {
defaultMessage: 'Disable internal collection of {beatType}\'s monitoring metrics',
defaultMessage: 'Disable self monitoring of {beatType}\'s monitoring metrics',
values: {
beatType: beatType || UNDETECTED_BEAT_TYPE
}
@ -73,130 +63,7 @@ export function getBeatsInstructionsForDisablingInternalCollection(product, meta
)
};
let migrationStatusStep = null;
if (!product || !product.isFullyMigrated) {
let status = null;
if (hasCheckedStatus) {
let lastInternallyCollectedMessage = '';
// It is possible that, during the migration steps, products are not reporting
// monitoring data for a period of time outside the window of our server-side check
// and this is most likely temporary so we want to be defensive and not error out
// and hopefully wait for the next check and this state will be self-corrected.
if (product) {
const lastInternallyCollectedTimestamp = product.lastInternallyCollectedTimestamp || product.lastTimestamp;
const secondsSinceLastInternalCollectionLabel =
formatTimestampToDuration(lastInternallyCollectedTimestamp, CALCULATE_DURATION_SINCE);
lastInternallyCollectedMessage = (<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.partiallyMigratedStatusDescription"
defaultMessage="Last internal collection occurred {secondsSinceLastInternalCollectionLabel} ago."
values={{
secondsSinceLastInternalCollectionLabel,
}}
/>);
}
status = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.beatsInstructions.partiallyMigratedStatusTitle',
{
defaultMessage: `We still see data coming from internal collection of this beat.`
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.partiallyMigratedStatusDescription"
defaultMessage="Note that it can take up to {secondsAgo} seconds to detect, but
we will continuously check every {timePeriod} seconds in the background."
values={{
secondsAgo: meta.secondsAgo,
timePeriod: autoCheckIntervalInMs / 1000,
}}
/>
</p>
<p>
{lastInternallyCollectedMessage}
</p>
</EuiCallOut>
</Fragment>
);
}
let buttonLabel;
if (checkingMigrationStatus) {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.checkingStatusButtonLabel',
{
defaultMessage: 'Checking...'
}
);
} else {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.checkStatusButtonLabel',
{
defaultMessage: 'Check'
}
);
}
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<Fragment>
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiText>
<p>
{i18n.translate(
'xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.statusDescription',
{
defaultMessage: 'Check that no documents are coming from internal collection.'
}
)}
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={checkForMigrationStatus} isDisabled={checkingMigrationStatus}>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{status}
</Fragment>
)
};
}
else {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.fullyMigratedStatusDescription"
defaultMessage="We are not seeing any documents from internal collection. Migration complete!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getDisableStatusStep(product, meta);
return [
disableInternalCollectionStep,

View file

@ -14,46 +14,18 @@ import {
} from '@elastic/eui';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle, UNDETECTED_BEAT_TYPE, DEFAULT_BEAT_FOR_URLS } from './common_beats_instructions';
import { UNDETECTED_BEAT_TYPE, DEFAULT_BEAT_FOR_URLS } from './common_beats_instructions';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getMigrationStatusStep, getSecurityStep } from '../common_instructions';
export function getBeatsInstructionsForEnablingMetricbeat(product, _meta, {
esMonitoringUrl,
}) {
const beatType = product.beatType;
const securitySetup = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
color="warning"
iconType="help"
title={(
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.metricbeatSecuritySetup"
defaultMessage="If security features are enabled, there may be more setup required.{link}"
values={{
link: (
<Fragment>
{` `}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/beats/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`}
target="_blank"
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.metricbeatSecuritySetupLinkText"
defaultMessage="View more information."
/>
</EuiLink>
</Fragment>
)
}}
/>
</EuiText>
)}
/>
</Fragment>
const securitySetup = getSecurityStep(
`${ELASTIC_WEBSITE_URL}guide/en/beats/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`
);
const installMetricbeatStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.beatsInstructions.installMetricbeatTitle', {
defaultMessage: 'Install Metricbeat on the same server as this {beatType}',
@ -70,7 +42,7 @@ export function getBeatsInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.installMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -170,7 +142,7 @@ export function getBeatsInstructionsForEnablingMetricbeat(product, _meta, {
isCopyable
>
{`output.elasticsearch:
hosts: ["${esMonitoringUrl}"] ## Monitoring cluster
hosts: [${esMonitoringUrl}] ## Monitoring cluster
# Optional protocol and basic auth credentials.
#protocol: "https"
@ -197,7 +169,7 @@ export function getBeatsInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.startMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -205,48 +177,7 @@ export function getBeatsInstructionsForEnablingMetricbeat(product, _meta, {
)
};
let migrationStatusStep = null;
if (product.isInternalCollector || product.isNetNewUser) {
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.beatsInstructions.isInternalCollectorStatusTitle', {
defaultMessage: `We have not detected any monitoring data coming from Metricbeat for this Beat.
We will continuously check in the background.`,
})}
/>
)
};
}
else if (product.isPartiallyMigrated || product.isFullyMigrated) {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.beatsInstructions.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.beatsInstructions.fullyMigratedStatusDescription"
defaultMessage="We are now seeing monitoring data shipping from Metricbeat!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getMigrationStatusStep(product);
return [
installMetricbeatStep,

View file

@ -0,0 +1,176 @@
/*
* 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, { Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiCallOut,
EuiSpacer,
EuiText,
EuiLink
} from '@elastic/eui';
import { CALCULATE_DURATION_SINCE } from '../../../../common/constants';
import { formatTimestampToDuration } from '../../../../common';
export const MIGRATION_STATUS_LABEL = i18n.translate('xpack.monitoring.metricbeatMigration.migrationStatus', {
defaultMessage: `Migration status`
});
export const MONITORING_STATUS_LABEL = i18n.translate('xpack.monitoring.metricbeatMigration.monitoringStatus', {
defaultMessage: `Monitoring status`
});
export function getSecurityStep(url) {
return (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
color="warning"
iconType="help"
title={(
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.securitySetup"
defaultMessage="If security is enabled, {link} might be required."
values={{
link: (
<Fragment>
{` `}
<EuiLink
href={url}
target="_blank"
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.securitySetupLinkText"
defaultMessage="additional setup"
/>
</EuiLink>
</Fragment>
)
}}
/>
</EuiText>
)}
/>
</Fragment>
);
}
export function getMigrationStatusStep(product) {
if (product.isInternalCollector || product.isNetNewUser) {
return {
title: product.isNetNewUser ? MONITORING_STATUS_LABEL : MIGRATION_STATUS_LABEL,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.isInternalCollectorStatusTitle', {
defaultMessage: `No monitoring data detected, but well continue checking.`,
})}
/>
)
};
}
else if (product.isPartiallyMigrated || product.isFullyMigrated) {
return {
title: MIGRATION_STATUS_LABEL,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate('xpack.monitoring.metricbeatMigration.fullyMigratedStatusTitle', {
defaultMessage: 'Congratulations!'
})}
>
<p>
{i18n.translate('xpack.monitoring.metricbeatMigration.fullyMigratedStatusDescription', {
defaultMessage: 'Metricbeat is shipping monitoring data.'
})}
</p>
</EuiCallOut>
)
};
}
return null;
}
export function getDisableStatusStep(product, meta) {
if (!product || !product.isFullyMigrated) {
let lastInternallyCollectedMessage = '';
// It is possible that, during the migration steps, products are not reporting
// monitoring data for a period of time outside the window of our server-side check
// and this is most likely temporary so we want to be defensive and not error out
// and hopefully wait for the next check and this state will be self-corrected.
if (product) {
const lastInternallyCollectedTimestamp = product.lastInternallyCollectedTimestamp || product.lastTimestamp;
const secondsSinceLastInternalCollectionLabel =
formatTimestampToDuration(lastInternallyCollectedTimestamp, CALCULATE_DURATION_SINCE);
lastInternallyCollectedMessage = i18n.translate(
'xpack.monitoring.metricbeatMigration.disableInternalCollection.partiallyMigratedStatusDescription',
{
defaultMessage: 'Last self monitoring was {secondsSinceLastInternalCollectionLabel} ago.',
values: {
secondsSinceLastInternalCollectionLabel
}
}
);
}
return {
title: MIGRATION_STATUS_LABEL,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.partiallyMigratedStatusTitle',
{
defaultMessage: `Data is still coming from self monitoring`
}
)}
>
<p>
{i18n.translate('xpack.monitoring.metricbeatMigration.partiallyMigratedStatusDescription', {
defaultMessage: `It can take up to {secondsAgo} seconds to detect data.`,
values: {
secondsAgo: meta.secondsAgo
}
})}
</p>
<p>
{lastInternallyCollectedMessage}
</p>
</EuiCallOut>
)
};
}
return {
title: MIGRATION_STATUS_LABEL,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.disableInternalCollection.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
{i18n.translate('xpack.monitoring.metricbeatMigration.disableInternalCollection.fullyMigratedStatusDescription', {
defaultMessage: 'We are not seeing any documents from self monitoring. Migration complete!'
})}
</p>
</EuiCallOut>
)
};
}

View file

@ -1,14 +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 { i18n } from '@kbn/i18n';
export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitle', {
defaultMessage: `Migration status`
});
export const statusTitleNewUser = i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitleNewUser', {
defaultMessage: `Monitoring status`
});

View file

@ -8,19 +8,16 @@ import React, { Fragment } from 'react';
import {
EuiSpacer,
EuiCodeBlock,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../../common/constants';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle } from './common_elasticsearch_instructions';
import { getDisableStatusStep } from '../common_instructions';
export function getElasticsearchInstructionsForDisablingInternalCollection(product, meta) {
const disableInternalCollectionStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollectionTitle', {
defaultMessage: 'Disable internal collection of Elasticsearch monitoring metrics'
defaultMessage: 'Disable self monitoring of Elasticsearch monitoring metrics'
}),
children: (
<Fragment>
@ -28,7 +25,7 @@ export function getElasticsearchInstructionsForDisablingInternalCollection(produ
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollectionDescription"
defaultMessage="Disable internal collection of Elasticsearch monitoring metrics.
defaultMessage="Disable self monitoring of Elasticsearch monitoring metrics.
Set {monospace} to false on each server in the production cluster."
values={{
monospace: (
@ -55,81 +52,7 @@ export function getElasticsearchInstructionsForDisablingInternalCollection(produ
)
};
let migrationStatusStep = null;
if (!product || !product.isFullyMigrated) {
let lastInternallyCollectedMessage = '';
// It is possible that, during the migration steps, products are not reporting
// monitoring data for a period of time outside the window of our server-side check
// and this is most likely temporary so we want to be defensive and not error out
// and hopefully wait for the next check and this state will be self-corrected.
if (product) {
const lastInternallyCollectedTimestamp = product.lastInternallyCollectedTimestamp || product.lastTimestamp;
const secondsSinceLastInternalCollectionLabel =
formatTimestampToDuration(lastInternallyCollectedTimestamp, CALCULATE_DURATION_SINCE);
lastInternallyCollectedMessage = (<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.partiallyMigratedStatusDescription"
defaultMessage="Last internal collection occurred {secondsSinceLastInternalCollectionLabel} ago."
values={{
secondsSinceLastInternalCollectionLabel,
}}
/>);
}
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.partiallyMigratedStatusTitle',
{
defaultMessage: `We still see data coming from internal collection of Elasticsearch.`
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.partiallyMigratedStatusDescription"
defaultMessage="Note that it can take up to {secondsAgo} seconds to detect, but
we will continuously check in the background."
values={{
secondsAgo: meta.secondsAgo,
}}
/>
</p>
<p>
{lastInternallyCollectedMessage}
</p>
</EuiCallOut>
)
};
}
else {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.fullyMigratedStatusDescription"
defaultMessage="We are not seeing any documents from internal collection. Migration complete!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getDisableStatusStep(product, meta);
return [
disableInternalCollectionStep,

View file

@ -9,49 +9,18 @@ import {
EuiSpacer,
EuiCodeBlock,
EuiLink,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle, statusTitleNewUser } from './common_elasticsearch_instructions';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getSecurityStep, getMigrationStatusStep } from '../common_instructions';
export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta, {
esMonitoringUrl,
}) {
const securitySetup = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
color="warning"
iconType="help"
title={(
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.metricbeatSecuritySetup"
defaultMessage="If security features are enabled, there may be more setup required.{link}"
values={{
link: (
<Fragment>
{` `}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`}
target="_blank"
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.metricbeatSecuritySetupLinkText"
defaultMessage="View more information."
/>
</EuiLink>
</Fragment>
)
}}
/>
</EuiText>
)}
/>
</Fragment>
const securitySetup = getSecurityStep(
`${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`
);
const installMetricbeatStep = {
@ -67,7 +36,7 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.installMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow these instructions."
/>
</EuiLink>
</p>
@ -82,6 +51,14 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
}),
children: (
<Fragment>
<EuiText>
<p>
{i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.enableMetricbeatModuleInstallDirectory', {
defaultMessage: 'From the installation directory, run:'
})}
</p>
</EuiText>
<EuiSpacer size="s"/>
<EuiCodeBlock
isCopyable
language="bash"
@ -93,9 +70,8 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.enableMetricbeatModuleDescription"
defaultMessage="By default the module will collect Elasticsearch monitoring metrics from {url}.
If the local Elasticsearch server has a different address,
you must specify it via the hosts setting in the {module} file."
defaultMessage="By default the module collects Elasticsearch metrics from {url}.
If the local server has a different address, add it to the hosts setting in {module}."
values={{
module: (
<Monospace>modules.d/elasticsearch-xpack.yml</Monospace>
@ -114,14 +90,14 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
const configureMetricbeatStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.configureMetricbeatTitle', {
defaultMessage: 'Configure Metricbeat to send to the monitoring cluster'
defaultMessage: 'Configure Metricbeat to send data to the monitoring cluster'
}),
children: (
<Fragment>
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.configureMetricbeatDescription"
defaultMessage="Make these changes in your {file}."
defaultMessage="Modify {file} to set the connection information."
values={{
file: (
<Monospace>metricbeat.yml</Monospace>
@ -134,7 +110,7 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
isCopyable
>
{`output.elasticsearch:
hosts: ["${esMonitoringUrl}"] ## Monitoring cluster
hosts: [${esMonitoringUrl}] ## Monitoring cluster
# Optional protocol and basic auth credentials.
#protocol: "https"
@ -161,7 +137,7 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.startMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow these instructions."
/>
</EuiLink>
</p>
@ -169,48 +145,7 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta
)
};
let migrationStatusStep = null;
if (product.isInternalCollector || product.isNetNewUser) {
migrationStatusStep = {
title: product.isNetNewUser ? statusTitleNewUser : statusTitle,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.isInternalCollectorStatusTitle', {
defaultMessage: `We have not detected any monitoring data coming from Metricbeat for this Elasticsearch node.
We will continuously check in the background.`,
})}
/>
)
};
}
else if (product.isPartiallyMigrated || product.isFullyMigrated) {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.elasticsearchInstructions.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.elasticsearchInstructions.fullyMigratedStatusDescription"
defaultMessage="We are now seeing monitoring data shipping from Metricbeat!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getMigrationStatusStep(product);
return [
installMetricbeatStep,

View file

@ -21,15 +21,20 @@ import {
getBeatsInstructionsForDisablingInternalCollection,
} from './beats';
import {
getApmInstructionsForEnablingMetricbeat,
getApmInstructionsForDisablingInternalCollection,
getApmInstructionsForEnablingMetricbeat,
} from './apm';
import {
INSTRUCTION_STEP_ENABLE_METRICBEAT,
INSTRUCTION_STEP_DISABLE_INTERNAL
} from '../constants';
import { ELASTICSEARCH_CUSTOM_ID, APM_CUSTOM_ID } from '../../../../common/constants';
import { KIBANA_SYSTEM_ID, LOGSTASH_SYSTEM_ID, BEATS_SYSTEM_ID } from '../../../../../telemetry/common/constants';
import {
ELASTICSEARCH_SYSTEM_ID,
APM_SYSTEM_ID,
KIBANA_SYSTEM_ID,
LOGSTASH_SYSTEM_ID,
BEATS_SYSTEM_ID
} from '../../../../common/constants';
export function getInstructionSteps(productName, product, step, meta, opts) {
switch (productName) {
@ -40,7 +45,7 @@ export function getInstructionSteps(productName, product, step, meta, opts) {
if (step === INSTRUCTION_STEP_DISABLE_INTERNAL) {
return getKibanaInstructionsForDisablingInternalCollection(product, meta, opts);
}
case ELASTICSEARCH_CUSTOM_ID:
case ELASTICSEARCH_SYSTEM_ID:
if (step === INSTRUCTION_STEP_ENABLE_METRICBEAT) {
return getElasticsearchInstructionsForEnablingMetricbeat(product, meta, opts);
}
@ -61,7 +66,7 @@ export function getInstructionSteps(productName, product, step, meta, opts) {
if (step === INSTRUCTION_STEP_DISABLE_INTERNAL) {
return getBeatsInstructionsForDisablingInternalCollection(product, meta, opts);
}
case APM_CUSTOM_ID:
case APM_SYSTEM_ID:
if (step === INSTRUCTION_STEP_ENABLE_METRICBEAT) {
return getApmInstructionsForEnablingMetricbeat(product, meta, opts);
}

View file

@ -1,14 +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 { i18n } from '@kbn/i18n';
export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitle', {
defaultMessage: `Migration status`
});
export const statusTitleNewUser = i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitleNewUser', {
defaultMessage: `Monitoring status`
});

View file

@ -8,24 +8,14 @@ import React, { Fragment } from 'react';
import {
EuiSpacer,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../../common/constants';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle } from './common_kibana_instructions';
import { getDisableStatusStep } from '../common_instructions';
export function getKibanaInstructionsForDisablingInternalCollection(product, meta, {
checkForMigrationStatus,
checkingMigrationStatus,
hasCheckedStatus,
autoCheckIntervalInMs,
}) {
export function getKibanaInstructionsForDisablingInternalCollection(product, meta) {
let restartWarning = null;
if (product.isPrimary) {
restartWarning = (
@ -35,7 +25,7 @@ export function getKibanaInstructionsForDisablingInternalCollection(product, met
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.restartWarningTitle',
{
defaultMessage: 'Warning'
defaultMessage: 'This step requires you to restart the Kibana server'
}
)}
color="warning"
@ -45,8 +35,7 @@ export function getKibanaInstructionsForDisablingInternalCollection(product, met
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.restartNote"
defaultMessage="This step requires you to restart the Kibana server.
Expect to see errors until the server is running again."
defaultMessage="Expect errors until the server is running again."
/>
</p>
</EuiText>
@ -57,7 +46,7 @@ export function getKibanaInstructionsForDisablingInternalCollection(product, met
const disableInternalCollectionStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.title', {
defaultMessage: 'Disable internal collection of Kibana monitoring metrics'
defaultMessage: 'Disable self monitoring of Kibana monitoring metrics'
}),
children: (
<Fragment>
@ -65,7 +54,7 @@ export function getKibanaInstructionsForDisablingInternalCollection(product, met
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.description"
defaultMessage="Add the following setting in the Kibana configuration file ({file}):"
defaultMessage="Add this setting to {file}."
values={{
file: (
<Monospace>kibana.yml</Monospace>
@ -86,7 +75,7 @@ export function getKibanaInstructionsForDisablingInternalCollection(product, met
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.note"
defaultMessage="Leave the {config} set to its default value ({defaultValue})."
defaultMessage="For {config}, leave the default value of ({defaultValue})."
values={{
config: (
<Monospace>xpack.monitoring.enabled</Monospace>
@ -103,130 +92,7 @@ export function getKibanaInstructionsForDisablingInternalCollection(product, met
)
};
let migrationStatusStep = null;
if (!product || !product.isFullyMigrated) {
let status = null;
if (hasCheckedStatus) {
let lastInternallyCollectedMessage = '';
// It is possible that, during the migration steps, products are not reporting
// monitoring data for a period of time outside the window of our server-side check
// and this is most likely temporary so we want to be defensive and not error out
// and hopefully wait for the next check and this state will be self-corrected.
if (product) {
const lastInternallyCollectedTimestamp = product.lastInternallyCollectedTimestamp || product.lastTimestamp;
const secondsSinceLastInternalCollectionLabel =
formatTimestampToDuration(lastInternallyCollectedTimestamp, CALCULATE_DURATION_SINCE);
lastInternallyCollectedMessage = (<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.partiallyMigratedStatusDescription"
defaultMessage="Last internal collection occurred {secondsSinceLastInternalCollectionLabel} ago."
values={{
secondsSinceLastInternalCollectionLabel,
}}
/>);
}
status = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.partiallyMigratedStatusTitle',
{
defaultMessage: `We still see data coming from internal collection of Kibana.`
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.partiallyMigratedStatusDescription"
defaultMessage="Note that it can take up to {secondsAgo} seconds to detect, but
we will continuously check every {timePeriod} seconds in the background."
values={{
secondsAgo: meta.secondsAgo,
timePeriod: autoCheckIntervalInMs / 1000,
}}
/>
</p>
<p>
{lastInternallyCollectedMessage}
</p>
</EuiCallOut>
</Fragment>
);
}
let buttonLabel;
if (checkingMigrationStatus) {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.checkingStatusButtonLabel',
{
defaultMessage: 'Checking...'
}
);
} else {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.checkStatusButtonLabel',
{
defaultMessage: 'Check'
}
);
}
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<Fragment>
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiText>
<p>
{i18n.translate(
'xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.statusDescription',
{
defaultMessage: 'Check that no documents are coming from internal collection.'
}
)}
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={checkForMigrationStatus} isDisabled={checkingMigrationStatus}>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{status}
</Fragment>
)
};
}
else {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.fullyMigratedStatusDescription"
defaultMessage="We are not seeing any documents from internal collection. Migration complete!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getDisableStatusStep(product, meta);
return [
disableInternalCollectionStep,

View file

@ -9,50 +9,20 @@ import {
EuiSpacer,
EuiCodeBlock,
EuiLink,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle, statusTitleNewUser } from './common_kibana_instructions';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getMigrationStatusStep, getSecurityStep } from '../common_instructions';
export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, {
esMonitoringUrl,
}) {
const securitySetup = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
color="warning"
iconType="help"
title={(
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.metricbeatSecuritySetup"
defaultMessage="If security features are enabled, there may be more setup required.{link}"
values={{
link: (
<Fragment>
{` `}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/kibana/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`}
target="_blank"
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.metricbeatSecuritySetupLinkText"
defaultMessage="View more information."
/>
</EuiLink>
</Fragment>
)
}}
/>
</EuiText>
)}
/>
</Fragment>
const securitySetup = getSecurityStep(
`${ELASTIC_WEBSITE_URL}guide/en/kibana/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`
);
const installMetricbeatStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.installMetricbeatTitle', {
defaultMessage: 'Install Metricbeat on the same server as Kibana'
@ -66,7 +36,7 @@ export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.installMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -130,7 +100,7 @@ export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, {
isCopyable
>
{`output.elasticsearch:
hosts: ["${esMonitoringUrl}"] ## Monitoring cluster
hosts: [${esMonitoringUrl}] ## Monitoring cluster
# Optional protocol and basic auth credentials.
#protocol: "https"
@ -157,7 +127,7 @@ export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.startMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -165,48 +135,7 @@ export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, {
)
};
let migrationStatusStep = null;
if (product.isInternalCollector || product.isNetNewUser) {
migrationStatusStep = {
title: product.isNetNewUser ? statusTitleNewUser : statusTitle,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.isInternalCollectorStatusTitle', {
defaultMessage: `We have not detected any monitoring data coming from Metricbeat for this Kibana instance.
We will continuously check in the background.`,
})}
/>
)
};
}
else if (product.isPartiallyMigrated || product.isFullyMigrated) {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.kibanaInstructions.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.kibanaInstructions.fullyMigratedStatusDescription"
defaultMessage="We are now seeing monitoring data shipping from Metricbeat!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getMigrationStatusStep(product);
return [
installMetricbeatStep,

View file

@ -1,10 +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 { i18n } from '@kbn/i18n';
export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.logstashInstructions.statusTitle', {
defaultMessage: `Migration status`
});

View file

@ -8,27 +8,16 @@ import React, { Fragment } from 'react';
import {
EuiSpacer,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { formatTimestampToDuration } from '../../../../../common';
import { CALCULATE_DURATION_SINCE } from '../../../../../common/constants';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle } from './common_logstash_instructions';
import { getDisableStatusStep } from '../common_instructions';
export function getLogstashInstructionsForDisablingInternalCollection(product, meta, {
checkForMigrationStatus,
checkingMigrationStatus,
hasCheckedStatus,
autoCheckIntervalInMs,
}) {
export function getLogstashInstructionsForDisablingInternalCollection(product, meta) {
const disableInternalCollectionStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.title', {
defaultMessage: 'Disable internal collection of Logstash monitoring metrics'
defaultMessage: 'Disable self monitoring of Logstash monitoring metrics'
}),
children: (
<Fragment>
@ -65,130 +54,7 @@ export function getLogstashInstructionsForDisablingInternalCollection(product, m
)
};
let migrationStatusStep = null;
if (!product || !product.isFullyMigrated) {
let status = null;
if (hasCheckedStatus) {
let lastInternallyCollectedMessage = '';
// It is possible that, during the migration steps, products are not reporting
// monitoring data for a period of time outside the window of our server-side check
// and this is most likely temporary so we want to be defensive and not error out
// and hopefully wait for the next check and this state will be self-corrected.
if (product) {
const lastInternallyCollectedTimestamp = product.lastInternallyCollectedTimestamp || product.lastTimestamp;
const secondsSinceLastInternalCollectionLabel =
formatTimestampToDuration(lastInternallyCollectedTimestamp, CALCULATE_DURATION_SINCE);
lastInternallyCollectedMessage = (<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.partiallyMigratedStatusDescription"
defaultMessage="Last internal collection occurred {secondsSinceLastInternalCollectionLabel} ago."
values={{
secondsSinceLastInternalCollectionLabel,
}}
/>);
}
status = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.logstashInstructions.partiallyMigratedStatusTitle',
{
defaultMessage: `We still see data coming from internal collection of Logstash.`
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.partiallyMigratedStatusDescription"
defaultMessage="Note that it can take up to {secondsAgo} seconds to detect, but
we will continuously check every {timePeriod} seconds in the background."
values={{
secondsAgo: meta.secondsAgo,
timePeriod: autoCheckIntervalInMs / 1000,
}}
/>
</p>
<p>
{lastInternallyCollectedMessage}
</p>
</EuiCallOut>
</Fragment>
);
}
let buttonLabel;
if (checkingMigrationStatus) {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.checkingStatusButtonLabel',
{
defaultMessage: 'Checking...'
}
);
} else {
buttonLabel = i18n.translate(
'xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.checkStatusButtonLabel',
{
defaultMessage: 'Check'
}
);
}
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<Fragment>
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiText>
<p>
{i18n.translate(
'xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.statusDescription',
{
defaultMessage: 'Check that no documents are coming from internal collection.'
}
)}
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={checkForMigrationStatus} isDisabled={checkingMigrationStatus}>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{status}
</Fragment>
)
};
}
else {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.fullyMigratedStatusDescription"
defaultMessage="We are not seeing any documents from internal collection. Migration complete!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getDisableStatusStep(product, meta);
return [
disableInternalCollectionStep,

View file

@ -9,50 +9,20 @@ import {
EuiSpacer,
EuiCodeBlock,
EuiLink,
EuiCallOut,
EuiText
} from '@elastic/eui';
import { Monospace } from '../components/monospace';
import { FormattedMessage } from '@kbn/i18n/react';
import { statusTitle } from './common_logstash_instructions';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getMigrationStatusStep, getSecurityStep } from '../common_instructions';
export function getLogstashInstructionsForEnablingMetricbeat(product, _meta, {
esMonitoringUrl,
}) {
const securitySetup = (
<Fragment>
<EuiSpacer size="m"/>
<EuiCallOut
color="warning"
iconType="help"
title={(
<EuiText>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.metricbeatSecuritySetup"
defaultMessage="If security features are enabled, there may be more setup required.{link}"
values={{
link: (
<Fragment>
{` `}
<EuiLink
href={`${ELASTIC_WEBSITE_URL}guide/en/logstash/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`}
target="_blank"
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.metricbeatSecuritySetupLinkText"
defaultMessage="View more information."
/>
</EuiLink>
</Fragment>
)
}}
/>
</EuiText>
)}
/>
</Fragment>
const securitySetup = getSecurityStep(
`${ELASTIC_WEBSITE_URL}guide/en/logstash/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html`
);
const installMetricbeatStep = {
title: i18n.translate('xpack.monitoring.metricbeatMigration.logstashInstructions.installMetricbeatTitle', {
defaultMessage: 'Install Metricbeat on the same server as Logstash'
@ -66,7 +36,7 @@ export function getLogstashInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.installMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -130,7 +100,7 @@ export function getLogstashInstructionsForEnablingMetricbeat(product, _meta, {
isCopyable
>
{`output.elasticsearch:
hosts: ["${esMonitoringUrl}"] ## Monitoring cluster
hosts: [${esMonitoringUrl}] ## Monitoring cluster
# Optional protocol and basic auth credentials.
#protocol: "https"
@ -157,7 +127,7 @@ export function getLogstashInstructionsForEnablingMetricbeat(product, _meta, {
>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.startMetricbeatLinkText"
defaultMessage="Follow the instructions here"
defaultMessage="Follow the instructions here."
/>
</EuiLink>
</p>
@ -165,48 +135,7 @@ export function getLogstashInstructionsForEnablingMetricbeat(product, _meta, {
)
};
let migrationStatusStep = null;
if (product.isInternalCollector || product.isNetNewUser) {
migrationStatusStep = {
title: statusTitle,
status: 'incomplete',
children: (
<EuiCallOut
size="s"
color="warning"
title={i18n.translate('xpack.monitoring.metricbeatMigration.logstashInstructions.isInternalCollectorStatusTitle', {
defaultMessage: `We have not detected any monitoring data coming from Metricbeat for this Logstash node.
We will continuously check n the background.`,
})}
/>
)
};
}
else if (product.isPartiallyMigrated || product.isFullyMigrated) {
migrationStatusStep = {
title: statusTitle,
status: 'complete',
children: (
<EuiCallOut
size="s"
color="success"
title={i18n.translate(
'xpack.monitoring.metricbeatMigration.logstashInstructions.fullyMigratedStatusTitle',
{
defaultMessage: 'Congratulations!'
}
)}
>
<p>
<FormattedMessage
id="xpack.monitoring.metricbeatMigration.logstashInstructions.fullyMigratedStatusDescription"
defaultMessage="We are now seeing monitoring data shipping from Metricbeat!"
/>
</p>
</EuiCallOut>
)
};
}
const migrationStatusStep = getMigrationStatusStep(product);
return [
installMetricbeatStep,

View file

@ -22,43 +22,69 @@ exports[`NoData should show a default message if reason is unknown 1`] = `
<div
class="euiSpacer euiSpacer--m"
/>
<h2
class="euiTitle euiTitle--large"
>
No monitoring data found
</h2>
<hr
class="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge"
/>
<div
class="euiText euiText--medium"
>
<p>
There is a
<span
class="euiCodeBlock euiCodeBlock--fontSmall euiCodeBlock--paddingLarge euiCodeBlock--inline"
>
<code
class="euiCodeBlock__code"
>
food
</code>
</span>
setting that has
<span
class="euiCodeBlock euiCodeBlock--fontSmall euiCodeBlock--paddingLarge euiCodeBlock--inline"
>
<code
class="euiCodeBlock__code"
>
xpack.monitoring.foo.bar
</code>
</span>
set to
<span
class="euiCodeBlock euiCodeBlock--fontSmall euiCodeBlock--paddingLarge euiCodeBlock--inline"
>
<code
class="euiCodeBlock__code"
>
taco
</code>
</span>
.
Have you set up monitoring yet? If so, make sure that the selected time period in the upper right includes monitoring data.
</p>
</div>
<div
class="euiSpacer euiSpacer--l"
/>
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceAround euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<button
class="euiButton euiButton--primary euiButton--fill"
data-test-subj="enableCollectionInterval"
type="button"
>
<span
class="euiButton__content"
>
<span
class="euiButton__text"
>
Set up monitoring with Metricbeat
</span>
</span>
</button>
</div>
</div>
<hr
class="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge"
/>
<button
class="euiButtonEmpty euiButtonEmpty--primary"
data-test-subj="useInternalCollection"
type="button"
>
<span
class="euiButtonEmpty__content"
>
<span
class="euiButtonEmpty__text"
>
<span
class="euiTextColor euiTextColor--subdued"
>
Or, set up with self monitoring
</span>
</span>
</span>
</button>
</div>
</div>
</div>
@ -89,38 +115,66 @@ exports[`NoData should show text next to the spinner while checking a setting 1`
<h2
class="euiTitle euiTitle--large"
>
We're looking for your monitoring data
No monitoring data found
</h2>
<span
class="euiTextColor euiTextColor--subdued"
>
<div
class="euiText euiText--medium"
>
<p>
Monitoring provides insight to your hardware performance and load.
</p>
</div>
</span>
<hr
class="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge"
/>
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
class="euiText euiText--medium"
>
<p>
Have you set up monitoring yet? If so, make sure that the selected time period in the upper right includes monitoring data.
</p>
</div>
<div
class="euiSpacer euiSpacer--l"
/>
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceAround euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
class="euiLoadingSpinner euiLoadingSpinner--medium"
/>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
checking something to test...
<button
class="euiButton euiButton--primary euiButton--fill"
data-test-subj="enableCollectionInterval"
type="button"
>
<span
class="euiButton__content"
>
<span
class="euiButton__text"
>
Set up monitoring with Metricbeat
</span>
</span>
</button>
</div>
</div>
<hr
class="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge"
/>
<button
class="euiButtonEmpty euiButtonEmpty--primary"
data-test-subj="useInternalCollection"
type="button"
>
<span
class="euiButtonEmpty__content"
>
<span
class="euiButtonEmpty__text"
>
<span
class="euiTextColor euiTextColor--subdued"
>
Or, set up with self monitoring
</span>
</span>
</span>
</button>
</div>
</div>
</div>

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import {
EuiSpacer,
@ -12,7 +12,17 @@ import {
EuiPage,
EuiPageBody,
EuiPageContent,
EuiHorizontalRule,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiText,
EuiTitle,
EuiTextColor,
EuiButtonEmpty
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { toggleSetupMode } from '../../lib/setup_mode';
import { CheckingSettings } from './checking_settings';
import { ReasonFound, WeTried } from './reasons';
import { CheckerErrors } from './checker_errors';
@ -32,6 +42,42 @@ function NoDataMessage(props) {
}
export function NoData(props) {
const [isLoading, setIsLoading] = useState(false);
const [useInternalCollection, setUseInternalCollection] = useState(false);
async function startSetup() {
setIsLoading(true);
await toggleSetupMode(true);
props.changePath('/elasticsearch/nodes');
}
if (useInternalCollection) {
return (
<EuiPage>
<EuiPageBody restrictWidth={600}>
<EuiPageContent
verticalPosition="center"
horizontalPosition="center"
className="eui-textCenter"
>
<EuiIcon type="monitoringApp" size="xxl" />
<EuiSpacer size="m" />
<NoDataMessage {...props} />
<CheckerErrors errors={props.errors} />
<EuiHorizontalRule size="half" />
<EuiButtonEmpty isDisabled={props.isCollectionEnabledUpdated} onClick={() => setUseInternalCollection(false)}>
<EuiTextColor color="default">
<FormattedMessage
id="xpack.monitoring.noData.setupMetricbeatInstead"
defaultMessage="Or, set up with Metricbeat (recommended)"
/>
</EuiTextColor>
</EuiButtonEmpty>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
);
}
return (
<EuiPage>
@ -43,8 +89,54 @@ export function NoData(props) {
>
<EuiIcon type="monitoringApp" size="xxl" />
<EuiSpacer size="m" />
<NoDataMessage {...props} />
<CheckerErrors errors={props.errors} />
<EuiTitle size="l">
<h2>
<FormattedMessage
id="xpack.monitoring.noData.noMonitoringDetected"
defaultMessage="No monitoring data found"
/>
</h2>
</EuiTitle>
<EuiHorizontalRule size="half" />
<EuiText>
<p>
<FormattedMessage
id="xpack.monitoring.noData.noMonitoringDataFound"
defaultMessage="Have you set up monitoring yet? If so, make sure that the selected time period in
the upper right includes monitoring data."
/>
</p>
</EuiText>
<EuiSpacer />
<EuiFlexGroup
alignItems="center"
justifyContent="spaceAround"
gutterSize="s"
>
<EuiFlexItem grow={false}>
<EuiButton
fill={true}
onClick={startSetup}
type="button"
data-test-subj="enableCollectionInterval"
isLoading={isLoading}
>
<FormattedMessage
id="xpack.monitoring.noData.collectionInterval.turnOnMonitoringButtonLabel"
defaultMessage="Set up monitoring with Metricbeat"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiHorizontalRule size="half" />
<EuiButtonEmpty onClick={() => setUseInternalCollection(true)} data-test-subj="useInternalCollection">
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.monitoring.noData.setupInternalInstead"
defaultMessage="Or, set up with self monitoring"
/>
</EuiTextColor>
</EuiButtonEmpty>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
@ -52,6 +144,7 @@ export function NoData(props) {
}
NoData.propTypes = {
changePath: PropTypes.func,
isLoading: PropTypes.bool.isRequired,
reason: PropTypes.object,
checkMessage: PropTypes.string

View file

@ -3,10 +3,28 @@
* 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 { getSetupModeState, initSetupModeState, updateSetupModeData, disableElasticsearchInternalCollection } from '../../lib/setup_mode';
import React, { Fragment } from 'react';
import {
getSetupModeState,
initSetupModeState,
updateSetupModeData,
disableElasticsearchInternalCollection,
toggleSetupMode,
setSetupModeMenuItem
} from '../../lib/setup_mode';
import { Flyout } from '../metricbeat_migration/flyout';
import {
EuiBottomBar,
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiTextColor,
EuiIcon,
EuiSpacer
} from '@elastic/eui';
import { findNewUuid } from './lib/find_new_uuid';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
export class SetupModeRenderer extends React.Component {
state = {
@ -44,6 +62,7 @@ export class SetupModeRenderer extends React.Component {
this.setState(newState);
});
setSetupModeMenuItem();
}
reset() {
@ -97,6 +116,50 @@ export class SetupModeRenderer extends React.Component {
);
}
getBottomBar(setupModeState) {
if (!setupModeState.enabled) {
return null;
}
return (
<Fragment>
<EuiSpacer size="xxl"/>
<EuiBottomBar>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={false}>
<EuiTextColor color="ghost">
<FormattedMessage
id="xpack.monitoring.setupMode.description"
defaultMessage="You are in setup mode. The ({flagIcon}) icon indicates configuration options."
values={{
flagIcon: (
<EuiIcon type="flag"/>
)
}}
/>
</EuiTextColor>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButton color="danger" fill size="s" onClick={() => toggleSetupMode(false)}>
{i18n.translate('xpack.monitoring.setupMode.exit', {
defaultMessage: `Exit setup mode`
})}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
</Fragment>
);
}
async shortcutToFinishMigration() {
await disableElasticsearchInternalCollection();
await updateSetupModeData();
@ -130,6 +193,7 @@ export class SetupModeRenderer extends React.Component {
closeFlyout: () => this.setState({ isFlyoutOpen: false }),
},
flyoutComponent: this.getFlyout(data, meta),
bottomBarComponent: this.getBottomBar(setupModeState)
});
}
}

View file

@ -0,0 +1,124 @@
/*
* 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, { Fragment } from 'react';
import {
EuiTextColor,
EuiIcon,
EuiBadge
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ELASTICSEARCH_SYSTEM_ID } from '../../../common/constants';
const clickToMonitorWithMetricbeat = i18n.translate('xpack.monitoring.setupMode.clickToMonitorWithMetricbeat', {
defaultMessage: 'Monitor with Metricbeat'
});
const clickToDisableInternalCollection = i18n.translate('xpack.monitoring.setupMode.clickToDisableInternalCollection', {
defaultMessage: 'Disable self monitoring'
});
const monitoredWithMetricbeat = i18n.translate('xpack.monitoring.setupMode.usingMetricbeatCollection', {
defaultMessage: 'Monitored with Metricbeat'
});
const unknown = i18n.translate('xpack.monitoring.setupMode.unknown', {
defaultMessage: 'N/A'
});
export function SetupModeBadge({ setupMode, productName, status, instance, clusterUuid }) {
let customAction = null;
let customText = null;
const setupModeData = setupMode.data || {};
const setupModeMeta = setupMode.meta || {};
// Migrating from partially to fully for Elasticsearch involves changing a cluster
// setting which impacts all nodes in the cluster so the action text needs to reflect that
const allPartiallyMigrated = setupModeData.totalUniquePartiallyMigratedCount === setupModeData.totalUniqueInstanceCount;
if (status.isPartiallyMigrated && productName === ELASTICSEARCH_SYSTEM_ID) {
if (allPartiallyMigrated) {
customText = clickToDisableInternalCollection;
if (setupModeMeta.liveClusterUuid === clusterUuid) {
customAction = setupMode.shortcutToFinishMigration;
}
}
else {
return (
<Fragment>
<EuiIcon type="flag"/>
&nbsp;
<EuiTextColor color="warning" size="xs">
{i18n.translate('xpack.monitoring.setupMode.monitorAllNodes', {
defaultMessage: 'Some nodes use only self monitoring'
})}
</EuiTextColor>
</Fragment>
);
}
}
const badgeProps = {};
if (status.isInternalCollector || status.isPartiallyMigrated || status.isNetNewUser) {
badgeProps.onClick = customAction ? customAction : () => setupMode.openFlyout(instance);
}
let statusText = null;
if (status.isInternalCollector) {
if (badgeProps.onClick) {
badgeProps.onClickAriaLabel = customText || clickToMonitorWithMetricbeat;
}
statusText = (
<EuiBadge color="danger" iconType="flag" {...badgeProps}>
{customText || clickToMonitorWithMetricbeat}
</EuiBadge>
);
}
else if (status.isPartiallyMigrated) {
if (badgeProps.onClick) {
badgeProps.onClickAriaLabel = customText || clickToDisableInternalCollection;
}
statusText = (
<EuiBadge color="warning" iconType="flag" {...badgeProps}>
{customText || clickToDisableInternalCollection}
</EuiBadge>
);
}
else if (status.isFullyMigrated) {
if (badgeProps.onClick) {
badgeProps.onClickAriaLabel = customText || monitoredWithMetricbeat;
}
statusText = (
<EuiBadge color="primary" iconType="flag" {...badgeProps}>
{customText || monitoredWithMetricbeat}
</EuiBadge>
);
}
else if (status.isNetNewUser) {
if (badgeProps.onClick) {
badgeProps.onClickAriaLabel = customText || clickToMonitorWithMetricbeat;
}
statusText = (
<EuiBadge color="danger" iconType="flag" {...badgeProps}>
{customText || clickToMonitorWithMetricbeat}
</EuiBadge>
);
}
else {
if (badgeProps.onClick) {
badgeProps.onClickAriaLabel = customText || unknown;
}
statusText = (
<EuiBadge color="danger" iconType="flag" {...badgeProps}>
{customText || unknown}
</EuiBadge>
);
}
return statusText;
}

View file

@ -0,0 +1,56 @@
/*
* 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 { capitalize } from 'lodash';
import { i18n } from '@kbn/i18n';
import {
APM_SYSTEM_ID,
LOGSTASH_SYSTEM_ID,
ELASTICSEARCH_SYSTEM_ID,
KIBANA_SYSTEM_ID,
BEATS_SYSTEM_ID
} from '../../../common/constants';
const NODE_IDENTIFIER_SINGULAR = i18n.translate('xpack.monitoring.setupMode.node', {
defaultMessage: `node`,
});
const NODE_IDENTIFIER_PLURAL = i18n.translate('xpack.monitoring.setupMode.nodes', {
defaultMessage: `nodes`,
});
const INSTANCE_IDENTIFIER_SINGULAR = i18n.translate('xpack.monitoring.setupMode.instance', {
defaultMessage: `instance`,
});
const INSTANCE_IDENTIFIER_PLURAL = i18n.translate('xpack.monitoring.setupMode.instances', {
defaultMessage: `instances`,
});
const SERVER_IDENTIFIER_SINGULAR = i18n.translate('xpack.monitoring.setupMode.server', {
defaultMessage: `server`,
});
const SERVER_IDENTIFIER_PLURAL = i18n.translate('xpack.monitoring.setupMode.servers', {
defaultMessage: `servers`,
});
export function formatProductName(productName) {
if (productName === APM_SYSTEM_ID) {
return productName.toUpperCase();
}
return capitalize(productName);
}
const PRODUCTS_THAT_USE_NODES = [LOGSTASH_SYSTEM_ID, ELASTICSEARCH_SYSTEM_ID];
const PRODUCTS_THAT_USE_INSTANCES = [KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID];
export function getIdentifier(productName, usePlural = false) {
if (PRODUCTS_THAT_USE_INSTANCES.includes(productName)) {
return usePlural ? INSTANCE_IDENTIFIER_PLURAL : INSTANCE_IDENTIFIER_SINGULAR;
}
if (PRODUCTS_THAT_USE_NODES.includes(productName)) {
return usePlural ? NODE_IDENTIFIER_PLURAL : NODE_IDENTIFIER_SINGULAR;
}
if (productName === APM_SYSTEM_ID) {
return usePlural ? SERVER_IDENTIFIER_PLURAL : SERVER_IDENTIFIER_SINGULAR;
}
return productName;
}

View file

@ -0,0 +1,174 @@
/*
* 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, { Fragment } from 'react';
import { get } from 'lodash';
import {
EuiCallOut,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { formatProductName, getIdentifier } from './formatting';
const MIGRATE_TO_MB_LABEL = i18n.translate('xpack.monitoring.setupMode.migrateToMetricbeat', {
defaultMessage: 'Monitor with Metricbeat',
});
export function ListingCallOut({ setupModeData, productName, customRenderer = null }) {
if (customRenderer) {
const { shouldRender, componentToRender } = customRenderer();
if (shouldRender) {
return componentToRender;
}
}
const mightExist = get(setupModeData, 'detected.mightExist');
const hasInstances = setupModeData.totalUniqueInstanceCount > 0;
if (!hasInstances) {
if (mightExist) {
return (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.setupMode.detectedNodeTitle', {
defaultMessage: '{product} {identifier} detected',
values: {
product: formatProductName(productName),
identifier: getIdentifier(productName)
}
})}
color="warning"
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.setupMode.detectedNodeDescription', {
defaultMessage: `Click 'Set up monitoring' below to start monitoring this {identifier}.`,
values: {
identifier: getIdentifier(productName)
}
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
return (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.setupMode.noMonitoringDataFound', {
defaultMessage: 'No {product} {identifier} detected',
values: {
product: formatProductName(productName),
identifier: getIdentifier(productName, true)
}
})}
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.setupMode.netNewUserDescription', {
defaultMessage: `Click 'Set up monitoring' to start monitoring with Metricbeat.`,
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
if (setupModeData.totalUniqueFullyMigratedCount === setupModeData.totalUniqueInstanceCount) {
return (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.setupMode.metricbeatAllNodes', {
defaultMessage: 'Metricbeat is monitoring all {identifier}.',
values: {
identifier: getIdentifier(productName, true)
}
})}
color="success"
iconType="flag"
/>
<EuiSpacer size="m"/>
</Fragment>
);
}
if (setupModeData.totalUniquePartiallyMigratedCount === setupModeData.totalUniqueInstanceCount) {
return (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.monitoring.setupMode.disableInternalCollectionTitle', {
defaultMessage: 'Disable self monitoring',
})}
color="warning"
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.setupMode.disableInternalCollectionDescription', {
defaultMessage: `Metricbeat is now monitoring your {product} {identifier}.
Disable self monitoring to finish the migration.`,
values: {
product: formatProductName(productName),
identifier: getIdentifier(productName, true)
}
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
if (setupModeData.totalUniqueInstanceCount > 0) {
if (setupModeData.totalUniqueFullyMigratedCount === 0 && setupModeData.totalUniquePartiallyMigratedCount === 0) {
return (
<Fragment>
<EuiCallOut
title={MIGRATE_TO_MB_LABEL}
color="danger"
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.setupMode.migrateToMetricbeatDescription', {
defaultMessage: `These {product} {identifier} are self monitored.
Click 'Monitor with Metricbeat' to migrate.`,
values: {
product: formatProductName(productName),
identifier: getIdentifier(productName, true)
}
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
return (
<Fragment>
<EuiCallOut
title={MIGRATE_TO_MB_LABEL}
color="danger"
iconType="flag"
>
<p>
{i18n.translate('xpack.monitoring.setupMode.migrateSomeToMetricbeatDescription', {
defaultMessage: `Some {product} {identifier} are monitored through self monitoring. Migrate to monitor with Metricbeat.`,
values: {
product: formatProductName(productName),
identifier: getIdentifier(productName, true)
}
})}
</p>
</EuiCallOut>
<EuiSpacer size="m"/>
</Fragment>
);
}
return null;
}

View file

@ -0,0 +1,141 @@
/*
* 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 { get } from 'lodash';
import {
EuiBadge,
EuiFlexItem,
EuiToolTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { getIdentifier } from './formatting';
export function SetupModeTooltip({ setupModeData, badgeClickAction, productName }) {
if (!setupModeData) {
return null;
}
const {
totalUniqueInstanceCount,
totalUniqueFullyMigratedCount,
totalUniquePartiallyMigratedCount
} = setupModeData;
const allMonitoredByMetricbeat = totalUniqueInstanceCount > 0 &&
(totalUniqueFullyMigratedCount === totalUniqueInstanceCount || totalUniquePartiallyMigratedCount === totalUniqueInstanceCount);
const internalCollectionOn = totalUniquePartiallyMigratedCount > 0;
const mightExist = get(setupModeData, 'detected.mightExist') || get(setupModeData, 'detected.doesExist');
let tooltip = null;
if (totalUniqueInstanceCount === 0) {
if (mightExist) {
const detectedText = i18n.translate('xpack.monitoring.setupMode.tooltip.detected', {
defaultMessage: 'No monitoring'
});
tooltip = (
<EuiToolTip
position="top"
content={i18n.translate('xpack.monitoring.setupMode.tooltip.mightExist', {
defaultMessage: `We detected usage of this product. Click to start monitoring.`,
})}
>
<EuiBadge color="warning" iconType="flag" onClick={badgeClickAction} onClickAriaLabel={detectedText}>
{detectedText}
</EuiBadge>
</EuiToolTip>
);
}
else {
const noMonitoringText = i18n.translate('xpack.monitoring.setupMode.tooltip.noUsage', {
defaultMessage: 'No usage'
});
tooltip = (
<EuiToolTip
position="top"
content={i18n.translate('xpack.monitoring.setupMode.tooltip.noUsageDetected', {
defaultMessage: `We did not detect any usage. Click to view {identifier}.`,
values: {
identifier: getIdentifier(productName, true)
}
})}
>
<EuiBadge color="hollow" iconType="flag" onClick={badgeClickAction} onClickAriaLabel={noMonitoringText}>
{noMonitoringText}
</EuiBadge>
</EuiToolTip>
);
}
}
else if (!allMonitoredByMetricbeat) {
const internalCollection = i18n.translate('xpack.monitoring.euiTable.isInternalCollectorLabel', {
defaultMessage: 'Self monitoring'
});
tooltip = (
<EuiToolTip
position="top"
content={i18n.translate('xpack.monitoring.setupMode.tooltip.oneInternal', {
defaultMessage: `At least one {identifier} isnt monitored using Metricbeat. Click to view status.`,
values: {
identifier: getIdentifier(productName)
}
})}
>
<EuiBadge color="danger" iconType="flag" onClick={badgeClickAction} onClickAriaLabel={internalCollection}>
{internalCollection}
</EuiBadge>
</EuiToolTip>
);
}
else if (internalCollectionOn) {
const internalAndMB = i18n.translate('xpack.monitoring.euiTable.isPartiallyMigratedLabel', {
defaultMessage: 'Self monitoring is on'
});
tooltip = (
<EuiToolTip
position="top"
content={i18n.translate('xpack.monitoring.setupMode.tooltip.disableInternal', {
defaultMessage: `Metricbeat is monitoring all {identifierPlural}. Click to view {identifierPlural} and disable self monitoring.`,
values: {
identifierPlural: getIdentifier(productName, true)
}
})}
>
<EuiBadge color="warning" iconType="flag" onClick={badgeClickAction} onClickAriaLabel={internalAndMB}>
{internalAndMB}
</EuiBadge>
</EuiToolTip>
);
}
else {
const metricbeatCollection = i18n.translate('xpack.monitoring.euiTable.isFullyMigratedLabel', {
defaultMessage: 'Metricbeat monitoring'
});
tooltip = (
<EuiToolTip
position="top"
content={i18n.translate('xpack.monitoring.setupMode.tooltip.allSet', {
defaultMessage: `Metricbeat is monitoring all {identifierPlural}.`,
values: {
identifierPlural: getIdentifier(productName, true)
}
})}
>
<EuiBadge color="secondary" iconType="flag" onClick={badgeClickAction} onClickAriaLabel={metricbeatCollection}>
{metricbeatCollection}
</EuiBadge>
</EuiToolTip>
);
}
return (
<EuiFlexItem grow={false}>
{tooltip}
</EuiFlexItem>
);
}

View file

@ -5,17 +5,13 @@
*/
import React, { Fragment } from 'react';
import { get } from 'lodash';
import {
EuiInMemoryTable,
EuiBadge,
EuiButtonEmpty,
EuiHealth,
EuiButton,
EuiSpacer
} from '@elastic/eui';
import { ELASTICSEARCH_CUSTOM_ID } from '../../../common/constants';
import { i18n } from '@kbn/i18n';
import { getIdentifier } from '../setup_mode/formatting';
export class EuiMonitoringTable extends React.PureComponent {
render() {
@ -24,9 +20,7 @@ export class EuiMonitoringTable extends React.PureComponent {
search = {},
columns: _columns,
setupMode,
uuidField,
nameField,
setupNewButtonLabel,
productName,
...props
} = this.props;
@ -51,150 +45,16 @@ export class EuiMonitoringTable extends React.PureComponent {
let footerContent = null;
if (setupMode && setupMode.enabled) {
columns.push({
name: i18n.translate('xpack.monitoring.euiTable.setupStatusTitle', {
defaultMessage: 'Setup Status'
}),
sortable: product => {
const list = get(setupMode, 'data.byUuid', {});
const status = list[get(product, uuidField)] || {};
if (status.isInternalCollector) {
return 4;
}
if (status.isPartiallyMigrated) {
return 3;
}
if (status.isFullyMigrated) {
return 2;
}
if (status.isNetNewUser) {
return 1;
}
return 0;
},
render: (product) => {
const list = get(setupMode, 'data.byUuid', {});
const status = list[get(product, uuidField)] || {};
let statusBadge = null;
if (status.isInternalCollector) {
statusBadge = (
<EuiHealth color="danger">
{i18n.translate('xpack.monitoring.euiTable.isInternalCollectorLabel', {
defaultMessage: 'Internal collection'
})}
</EuiHealth>
);
}
else if (status.isPartiallyMigrated) {
statusBadge = (
<EuiHealth color="warning">
{i18n.translate('xpack.monitoring.euiTable.isPartiallyMigratedLabel', {
defaultMessage: 'Internal collection and Metricbeat collection'
})}
</EuiHealth>
);
}
else if (status.isFullyMigrated) {
statusBadge = (
<EuiBadge color="primary">
{i18n.translate('xpack.monitoring.euiTable.isFullyMigratedLabel', {
defaultMessage: 'Metricbeat collection'
})}
</EuiBadge>
);
}
else if (status.isNetNewUser) {
statusBadge = (
<EuiHealth color="danger">
{i18n.translate('xpack.monitoring.euiTable.isNetNewUserLabel', {
defaultMessage: 'No monitoring detected'
})}
</EuiHealth>
);
}
else {
statusBadge = i18n.translate('xpack.monitoring.euiTable.migrationStatusUnknown', {
defaultMessage: 'N/A'
});
}
return statusBadge;
}
});
columns.push({
name: i18n.translate('xpack.monitoring.euiTable.setupActionTitle', {
defaultMessage: 'Setup Action'
}),
sortable: product => {
const list = get(setupMode, 'data.byUuid', {});
const status = list[get(product, uuidField)] || {};
if (status.isInternalCollector || status.isNetNewUser) {
return 1;
}
if (status.isPartiallyMigrated) {
if (setupMode.productName === ELASTICSEARCH_CUSTOM_ID) {
// See comment for same conditional in render function
return 0;
}
return 1;
}
return 0;
},
render: (product) => {
const uuid = get(product, uuidField);
const list = get(setupMode, 'data.byUuid', {});
const status = list[uuid] || {};
const instance = {
uuid: get(product, uuidField),
name: get(product, nameField),
};
// Migrating from partially to fully for Elasticsearch involves changing a cluster
// setting which impacts all nodes in the cluster, which we have a separate callout
// for. Since it does not make sense to do this on a per node basis, show nothing here
if (status.isPartiallyMigrated && setupMode.productName === ELASTICSEARCH_CUSTOM_ID) {
return null;
}
if (status.isInternalCollector || status.isPartiallyMigrated) {
return (
<EuiButtonEmpty flush="left" size="s" color="primary" onClick={() => setupMode.openFlyout(instance)}>
{i18n.translate('xpack.monitoring.euiTable.migrateButtonLabel', {
defaultMessage: 'Migrate'
})}
</EuiButtonEmpty>
);
}
if (status.isNetNewUser) {
return (
<EuiButtonEmpty flush="left" size="s" color="primary" onClick={() => setupMode.openFlyout(instance)}>
{i18n.translate('xpack.monitoring.euiTable.setupButtonLabel', {
defaultMessage: 'Setup'
})}
</EuiButtonEmpty>
);
}
return null;
}
});
footerContent = (
<Fragment>
<EuiSpacer size="m"/>
<EuiButton onClick={() => setupMode.openFlyout({}, true)}>
{setupNewButtonLabel}
<EuiButton iconType="flag" onClick={() => setupMode.openFlyout({}, true)}>
{i18n.translate('xpack.monitoring.euiTable.setupNewButtonLabel', {
defaultMessage: 'Set up monitoring for new {identifier}',
values: {
identifier: getIdentifier(productName)
}
})}
</EuiButton>
</Fragment>
);

View file

@ -18,7 +18,7 @@ import template from './index.html';
import { timefilter } from 'ui/timefilter';
import { shortenPipelineHash } from '../../../common/formatting';
import 'ui/directives/kbn_href';
import { getSetupModeState } from '../../lib/setup_mode';
import { getSetupModeState, initSetupModeState } from '../../lib/setup_mode';
const setOptions = (controller) => {
if (!controller.pipelineVersions || !controller.pipelineVersions.length || !controller.pipelineDropdownElement) {
@ -56,6 +56,7 @@ const setOptions = (controller) => {
, controller.pipelineDropdownElement);
};
/*
* Manage data and provide helper methods for the "main" directive's template
*/
@ -97,7 +98,7 @@ export class MonitoringMainController {
} else {
this.inOverview = this.name === 'overview';
this.inAlerts = this.name === 'alerts';
this.inListing = this.name === 'listing' || this.name === 'no-data';
this.inListing = this.name === 'listing';// || this.name === 'no-data';
}
if (!this.inListing) {
@ -155,6 +156,10 @@ export class MonitoringMainController {
if (data.totalUniqueInstanceCount === 0) {
return true;
}
if (data.totalUniqueInternallyCollectedCount === 0
&& data.totalUniqueFullyMigratedCount === 0 && data.totalUniquePartiallyMigratedCount === 0) {
return true;
}
return false;
}
}
@ -169,6 +174,9 @@ uiModule.directive('monitoringMain', (breadcrumbs, license, kbnUrl, $injector) =
controllerAs: 'monitoringMain',
bindToController: true,
link(scope, _element, attributes, controller) {
initSetupModeState(scope, $injector, () => {
controller.setup(getSetupObj());
});
if (!scope.cluster) {
const $route = $injector.get('$route');
const globalState = $injector.get('globalState');

View file

@ -6,7 +6,7 @@
import _ from 'lodash';
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
import { getSetupModeState } from './setup_mode';
import { isInSetupMode } from './setup_mode';
import { getClusterFromClusters } from './get_cluster_from_clusters';
export function routeInitProvider(Private, monitoringClusters, globalState, license, kbnUrl) {
@ -26,8 +26,8 @@ export function routeInitProvider(Private, monitoringClusters, globalState, lice
const clusterUuid = fetchAllClusters ? null : globalState.cluster_uuid;
return monitoringClusters(clusterUuid, undefined, codePaths)
// Set the clusters collection and current cluster in globalState
.then((clusters) => {
const inSetupMode = getSetupModeState().enabled;
.then(async (clusters) => {
const inSetupMode = await isInSetupMode();
const cluster = getClusterFromClusters(clusters, globalState);
if (!cluster && !inSetupMode) {
return kbnUrl.redirect('/no-data');

View file

@ -5,7 +5,12 @@
*/
import { ajaxErrorHandlersProvider } from './ajax_error_handler';
import { get } from 'lodash';
import { get, contains } from 'lodash';
import chrome from 'ui/chrome';
function isOnPage(hash) {
return contains(window.location.hash, hash);
}
const angularState = {
injector: null,
@ -111,70 +116,63 @@ export const disableElasticsearchInternalCollection = async () => {
};
export const toggleSetupMode = inSetupMode => {
return new Promise(async (resolve, reject) => {
try {
checkAngularState();
} catch (err) {
return reject(err);
}
const globalState = angularState.injector.get('globalState');
setupModeState.enabled = inSetupMode;
globalState.inSetupMode = inSetupMode;
globalState.save();
setSetupModeMenuItem(); // eslint-disable-line no-use-before-define
notifySetupModeDataChange();
if (inSetupMode) {
await updateSetupModeData();
}
resolve();
});
};
const setSetupModeMenuItem = () => {
// Disabling this for this initial release. This will be added back in
// in a subsequent PR
// checkAngularState();
// const globalState = angularState.injector.get('globalState');
// const navItems = globalState.inSetupMode
// ? [
// {
// key: 'exit',
// label: 'Exit Setup Mode',
// description: 'Exit setup mode',
// run: () => toggleSetupMode(false),
// testId: 'exitSetupMode'
// },
// {
// key: 'refresh',
// label: 'Refresh Setup Data',
// description: 'Refresh data used for setup mode',
// run: () => updateSetupModeData(),
// testId: 'refreshSetupModeData'
// }
// ]
// : [{
// key: 'enter',
// label: 'Enter Setup Mode',
// description: 'Enter setup mode',
// run: () => toggleSetupMode(true),
// testId: 'enterSetupMode'
// }];
// angularState.scope.topNavMenu = [...navItems];
};
export const initSetupModeState = ($scope, $injector, callback) => {
angularState.scope = $scope;
angularState.injector = $injector;
setSetupModeMenuItem();
callback && setupModeState.callbacks.push(callback);
checkAngularState();
const globalState = angularState.injector.get('globalState');
if (globalState.inSetupMode) {
toggleSetupMode(true);
setupModeState.enabled = inSetupMode;
globalState.inSetupMode = inSetupMode;
globalState.save();
setSetupModeMenuItem(); // eslint-disable-line no-use-before-define
notifySetupModeDataChange();
if (inSetupMode) {
// Intentionally do not await this so we don't block UI operations
updateSetupModeData();
}
};
export const setSetupModeMenuItem = () => {
checkAngularState();
if (isOnPage('no-data')) {
return;
}
const globalState = angularState.injector.get('globalState');
const navItems = globalState.inSetupMode
? []
: [{
id: 'enter',
label: 'Enter Setup Mode',
description: 'Enter setup',
run: () => toggleSetupMode(true),
testId: 'enterSetupMode'
}];
angularState.scope.topNavMenu = [...navItems];
// LOL angular
if (!angularState.scope.$$phase) {
angularState.scope.$apply();
}
};
export const initSetupModeState = async ($scope, $injector, callback) => {
angularState.scope = $scope;
angularState.injector = $injector;
callback && setupModeState.callbacks.push(callback);
const globalState = $injector.get('globalState');
if (globalState.inSetupMode) {
await toggleSetupMode(true);
}
};
export const isInSetupMode = async () => {
if (setupModeState.enabled) {
return true;
}
const $injector = angularState.injector || await chrome.dangerouslyGetActiveInjector();
const globalState = $injector.get('globalState');
return globalState.inSetupMode;
};

View file

@ -120,12 +120,11 @@ function getApmBreadcrumbs(mainInstance) {
export function breadcrumbsProvider() {
return function createBreadcrumbs(clusterName, mainInstance) {
let breadcrumbs = [ createCrumb('#/home',
i18n.translate(
'xpack.monitoring.breadcrumbs.clustersLabel', { defaultMessage: 'Clusters' }
),
'breadcrumbClusters')
];
const homeCrumb = i18n.translate(
'xpack.monitoring.breadcrumbs.clustersLabel', { defaultMessage: 'Clusters' }
);
let breadcrumbs = [ createCrumb('#/home', homeCrumb, 'breadcrumbClusters')];
if (!mainInstance.inOverview && clusterName) {
breadcrumbs.push(createCrumb('#/overview', clusterName));

View file

@ -14,7 +14,7 @@ import { ApmServerInstances } from '../../../components/apm/instances';
import { MonitoringViewBaseEuiTableController } from '../..';
import { I18nContext } from 'ui/i18n';
import { SetupModeRenderer } from '../../../components/renderers';
import { APM_CUSTOM_ID, CODE_PATH_APM } from '../../../../common/constants';
import { APM_SYSTEM_ID, CODE_PATH_APM } from '../../../../common/constants';
uiRoutes.when('/apm/instances', {
template,
@ -67,8 +67,8 @@ uiRoutes.when('/apm/instances', {
<SetupModeRenderer
scope={this.scope}
injector={this.injector}
productName={APM_CUSTOM_ID}
render={({ setupMode, flyoutComponent }) => (
productName={APM_SYSTEM_ID}
render={({ setupMode, flyoutComponent, bottomBarComponent }) => (
<Fragment>
{flyoutComponent}
<ApmServerInstances
@ -80,6 +80,7 @@ uiRoutes.when('/apm/instances', {
data,
}}
/>
{bottomBarComponent}
</Fragment>
)}
/>

View file

@ -15,8 +15,7 @@ import React, { Fragment } from 'react';
import { I18nContext } from 'ui/i18n';
import { Listing } from '../../../components/beats/listing/listing';
import { SetupModeRenderer } from '../../../components/renderers';
import { BEATS_SYSTEM_ID } from '../../../../../telemetry/common/constants';
import { CODE_PATH_BEATS } from '../../../../common/constants';
import { CODE_PATH_BEATS, BEATS_SYSTEM_ID } from '../../../../common/constants';
uiRoutes.when('/beats/beats', {
template,
@ -63,7 +62,7 @@ uiRoutes.when('/beats/beats', {
scope={this.scope}
injector={this.injector}
productName={BEATS_SYSTEM_ID}
render={({ setupMode, flyoutComponent }) => (
render={({ setupMode, flyoutComponent, bottomBarComponent }) => (
<Fragment>
{flyoutComponent}
<Listing
@ -78,6 +77,7 @@ uiRoutes.when('/beats/beats', {
scope: this.scope,
}}
/>
{bottomBarComponent}
</Fragment>
)}
/>

View file

@ -58,7 +58,7 @@ uiRoutes.when('/overview', {
<SetupModeRenderer
scope={$scope}
injector={$injector}
render={({ setupMode, flyoutComponent }) => (
render={({ setupMode, flyoutComponent, bottomBarComponent }) => (
<Fragment>
{flyoutComponent}
<Overview
@ -67,6 +67,7 @@ uiRoutes.when('/overview', {
changeUrl={changeUrl}
showLicenseExpiration={showLicenseExpiration}
/>
{bottomBarComponent}
</Fragment>
)}
/>

View file

@ -16,7 +16,7 @@ import { ElasticsearchNodes } from '../../../components';
import { I18nContext } from 'ui/i18n';
import { ajaxErrorHandlersProvider } from '../../../lib/ajax_error_handler';
import { SetupModeRenderer } from '../../../components/renderers';
import { ELASTICSEARCH_CUSTOM_ID, CODE_PATH_ELASTICSEARCH } from '../../../../common/constants';
import { ELASTICSEARCH_SYSTEM_ID, CODE_PATH_ELASTICSEARCH } from '../../../../common/constants';
uiRoutes.when('/elasticsearch/nodes', {
template,
@ -83,8 +83,8 @@ uiRoutes.when('/elasticsearch/nodes', {
<SetupModeRenderer
scope={$scope}
injector={$injector}
productName={ELASTICSEARCH_CUSTOM_ID}
render={({ setupMode, flyoutComponent }) => (
productName={ELASTICSEARCH_SYSTEM_ID}
render={({ setupMode, flyoutComponent, bottomBarComponent }) => (
<Fragment>
{flyoutComponent}
<ElasticsearchNodes
@ -97,6 +97,7 @@ uiRoutes.when('/elasticsearch/nodes', {
pagination={this.pagination}
onTableChange={this.onTableChange}
/>
{bottomBarComponent}
</Fragment>
)}
/>

View file

@ -13,8 +13,7 @@ import template from './index.html';
import { KibanaInstances } from 'plugins/monitoring/components/kibana/instances';
import { SetupModeRenderer } from '../../../components/renderers';
import { I18nContext } from 'ui/i18n';
import { KIBANA_SYSTEM_ID } from '../../../../../telemetry/common/constants';
import { CODE_PATH_KIBANA } from '../../../../common/constants';
import { KIBANA_SYSTEM_ID, CODE_PATH_KIBANA } from '../../../../common/constants';
uiRoutes.when('/kibana/instances', {
template,
@ -47,7 +46,7 @@ uiRoutes.when('/kibana/instances', {
scope={$scope}
injector={$injector}
productName={KIBANA_SYSTEM_ID}
render={({ setupMode, flyoutComponent }) => (
render={({ setupMode, flyoutComponent, bottomBarComponent }) => (
<Fragment>
{flyoutComponent}
<KibanaInstances
@ -62,6 +61,7 @@ uiRoutes.when('/kibana/instances', {
kbnUrl,
}}
/>
{bottomBarComponent}
</Fragment>
)}
/>

View file

@ -10,7 +10,6 @@ import { PageLoading } from 'plugins/monitoring/components';
import uiRoutes from 'ui/routes';
import { I18nContext } from 'ui/i18n';
import template from './index.html';
import { toggleSetupMode, getSetupModeState, initSetupModeState } from '../../lib/setup_mode';
import { CODE_PATH_LICENSE } from '../../../common/constants';
const REACT_DOM_ID = 'monitoringLoadingReactApp';
@ -23,17 +22,6 @@ uiRoutes
const monitoringClusters = $injector.get('monitoringClusters');
const kbnUrl = $injector.get('kbnUrl');
initSetupModeState($scope, $injector);
const setupMode = getSetupModeState();
// For phase 3, this is not an valid route unless
// setup mode is currently enabled. For phase 4,
// we will remove this check.
if (!setupMode.enabled) {
kbnUrl.changePath('/no-data');
return;
}
$scope.$on('$destroy', () => {
unmountComponentAtNode(document.getElementById(REACT_DOM_ID));
});
@ -48,12 +36,8 @@ uiRoutes
kbnUrl.changePath('/home');
return;
}
initSetupModeState($scope, $injector);
return toggleSetupMode(true)
.then(() => {
kbnUrl.changePath('/elasticsearch/nodes');
$scope.$apply();
});
kbnUrl.changePath('/no-data');
return;
});
}

View file

@ -12,8 +12,7 @@ import template from './index.html';
import { I18nContext } from 'ui/i18n';
import { Listing } from '../../../components/logstash/listing';
import { SetupModeRenderer } from '../../../components/renderers';
import { LOGSTASH_SYSTEM_ID } from '../../../../../telemetry/common/constants';
import { CODE_PATH_LOGSTASH } from '../../../../common/constants';
import { CODE_PATH_LOGSTASH, LOGSTASH_SYSTEM_ID } from '../../../../common/constants';
uiRoutes.when('/logstash/nodes', {
template,
@ -46,7 +45,7 @@ uiRoutes.when('/logstash/nodes', {
scope={$scope}
injector={$injector}
productName={LOGSTASH_SYSTEM_ID}
render={({ setupMode, flyoutComponent }) => (
render={({ setupMode, flyoutComponent, bottomBarComponent }) => (
<Fragment>
{flyoutComponent}
<Listing
@ -58,6 +57,7 @@ uiRoutes.when('/logstash/nodes', {
onTableChange={this.onTableChange}
angular={{ kbnUrl, scope: $scope }}
/>
{bottomBarComponent}
</Fragment>
)}
/>

View file

@ -78,6 +78,8 @@ export class NoDataController extends MonitoringViewBaseController {
}
this.render(enabler);
}, true);
this.changePath = path => kbnUrl.changePath(path);
}
getDefaultModel() {
@ -94,9 +96,10 @@ export class NoDataController extends MonitoringViewBaseController {
render(enabler) {
const props = this;
this.renderReact(
<I18nContext>
<NoData {...props} enabler={enabler} />
<NoData {...props} enabler={enabler} changePath={this.changePath} />
</I18nContext>
);
}

View file

@ -9,7 +9,8 @@ import sinon from 'sinon';
import { getCollectionStatus } from '../';
import { getIndexPatterns } from '../../../cluster/get_index_patterns';
const mockReq = (searchResult = {}, msearchResult = { responses: [] }) => {
const liveClusterUuid = 'a12';
const mockReq = (searchResult = {}) => {
return {
server: {
config() {
@ -18,12 +19,28 @@ const mockReq = (searchResult = {}, msearchResult = { responses: [] }) => {
.withArgs('server.uuid').returns('kibana-1234')
};
},
usage: {
collectorSet: {
getCollectorByType: () => ({
isReady: () => false
})
}
},
plugins: {
elasticsearch: {
getCluster() {
return {
callWithRequest(_req, type) {
return Promise.resolve(type === 'search' ? searchResult : msearchResult);
callWithRequest(_req, type, params) {
if (type === 'transport.request' && (params && params.path === '/_cluster/state/cluster_uuid')) {
return Promise.resolve({ cluster_uuid: liveClusterUuid });
}
if (type === 'transport.request' && (params && params.path === '/_nodes')) {
return Promise.resolve({ nodes: {} });
}
if (type === 'cat.indices') {
return Promise.resolve([1]);
}
return Promise.resolve(searchResult);
}
};
}
@ -192,7 +209,7 @@ describe('getCollectionStatus', () => {
]
});
const result = await getCollectionStatus(req, getIndexPatterns(req.server));
const result = await getCollectionStatus(req, getIndexPatterns(req.server), liveClusterUuid);
expect(result.kibana.detected.doesExist).to.be(true);
expect(result.elasticsearch.detected.doesExist).to.be(true);

View file

@ -5,8 +5,14 @@
*/
import { get, uniq } from 'lodash';
import { METRICBEAT_INDEX_NAME_UNIQUE_TOKEN, ELASTICSEARCH_CUSTOM_ID, APM_CUSTOM_ID } from '../../../../common/constants';
import { KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID, LOGSTASH_SYSTEM_ID } from '../../../../../telemetry/common/constants';
import {
METRICBEAT_INDEX_NAME_UNIQUE_TOKEN,
ELASTICSEARCH_SYSTEM_ID,
APM_SYSTEM_ID,
KIBANA_SYSTEM_ID,
BEATS_SYSTEM_ID,
LOGSTASH_SYSTEM_ID
} from '../../../../common/constants';
import { getLivesNodes } from '../../elasticsearch/nodes/get_nodes/get_live_nodes';
import { KIBANA_STATS_TYPE } from '../../../../../../../../src/legacy/server/status/constants';
@ -139,18 +145,18 @@ const getRecentMonitoringDocuments = async (req, indexPatterns, clusterUuid, nod
return await callWithRequest(req, 'search', params);
};
async function detectProducts(req) {
async function detectProducts(req, isLiveCluster) {
const result = {
[KIBANA_SYSTEM_ID]: {
doesExist: true,
},
[ELASTICSEARCH_CUSTOM_ID]: {
[ELASTICSEARCH_SYSTEM_ID]: {
doesExist: true,
},
[BEATS_SYSTEM_ID]: {
mightExist: false,
},
[APM_CUSTOM_ID]: {
[APM_SYSTEM_ID]: {
mightExist: false,
},
[LOGSTASH_SYSTEM_ID]: {
@ -174,18 +180,20 @@ async function detectProducts(req) {
]
},
{
id: APM_CUSTOM_ID,
id: APM_SYSTEM_ID,
indices: [
'apm-*'
]
}
];
const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('data');
for (const { id, indices } of detectionSearch) {
const response = await callWithRequest(req, 'cat.indices', { index: indices, format: 'json' });
if (response.length) {
result[id].mightExist = true;
if (isLiveCluster) {
const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('data');
for (const { id, indices } of detectionSearch) {
const response = await callWithRequest(req, 'cat.indices', { index: indices, format: 'json' });
if (response.length) {
result[id].mightExist = true;
}
}
}
@ -194,12 +202,12 @@ async function detectProducts(req) {
function getUuidBucketName(productName) {
switch (productName) {
case ELASTICSEARCH_CUSTOM_ID:
case ELASTICSEARCH_SYSTEM_ID:
return 'es_uuids';
case KIBANA_SYSTEM_ID:
return 'kibana_uuids';
case BEATS_SYSTEM_ID:
case APM_CUSTOM_ID:
case APM_SYSTEM_ID:
return 'beats_uuids';
case LOGSTASH_SYSTEM_ID:
return 'logstash_uuids';
@ -232,7 +240,7 @@ function shouldSkipBucket(product, bucket) {
if (product.name === BEATS_SYSTEM_ID && isBeatFromAPM(bucket)) {
return true;
}
if (product.name === APM_CUSTOM_ID && !isBeatFromAPM(bucket)) {
if (product.name === APM_SYSTEM_ID && !isBeatFromAPM(bucket)) {
return true;
}
return false;
@ -271,7 +279,7 @@ async function getLiveElasticsearchCollectionEnabled(req) {
});
const sources = ['persistent', 'transient', 'defaults'];
for (const source of sources) {
const collectionSettings = get(response[source], 'xpack.monitoring.collection');
const collectionSettings = get(response[source], 'xpack.monitoring.elasticsearch.collection');
if (collectionSettings && collectionSettings.enabled === 'true') {
return true;
}
@ -308,13 +316,15 @@ async function getLiveElasticsearchCollectionEnabled(req) {
export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeUuid, skipLiveData) => {
const config = req.server.config();
const kibanaUuid = config.get('server.uuid');
const liveClusterUuid = skipLiveData ? null : await getLiveElasticsearchClusterUuid(req);
const isLiveCluster = !clusterUuid || liveClusterUuid === clusterUuid;
const PRODUCTS = [
{ name: KIBANA_SYSTEM_ID },
{ name: BEATS_SYSTEM_ID },
{ name: LOGSTASH_SYSTEM_ID },
{ name: APM_CUSTOM_ID, token: '-beats-' },
{ name: ELASTICSEARCH_CUSTOM_ID, token: '-es-' },
{ name: APM_SYSTEM_ID, token: '-beats-' },
{ name: ELASTICSEARCH_SYSTEM_ID, token: '-es-' },
];
const [
@ -322,12 +332,12 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
detectedProducts
] = await Promise.all([
await getRecentMonitoringDocuments(req, indexPatterns, clusterUuid, nodeUuid),
await detectProducts(req)
await detectProducts(req, isLiveCluster)
]);
const liveClusterUuid = skipLiveData ? null : await getLiveElasticsearchClusterUuid(req);
const liveEsNodes = skipLiveData || (clusterUuid && liveClusterUuid !== clusterUuid) ? [] : await getLivesNodes(req);
const liveKibanaInstance = skipLiveData || (clusterUuid && liveClusterUuid !== clusterUuid) ? {} : await getLiveKibanaInstance(req);
const liveEsNodes = skipLiveData || !isLiveCluster ? [] : await getLivesNodes(req);
const liveKibanaInstance = skipLiveData || !isLiveCluster ? {} : await getLiveKibanaInstance(req);
const indicesBuckets = get(recentDocuments, 'aggregations.indices.buckets', []);
const liveClusterInternalCollectionEnabled = await getLiveElasticsearchCollectionEnabled(req);
@ -338,6 +348,7 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
const productStatus = {
totalUniqueInstanceCount: 0,
totalUniqueInternallyCollectedCount: 0,
totalUniqueFullyMigratedCount: 0,
totalUniquePartiallyMigratedCount: 0,
detected: null,
@ -348,28 +359,6 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
const internalCollectorsUuidsMap = {};
const partiallyMigratedUuidsMap = {};
if (product.name === ELASTICSEARCH_CUSTOM_ID && liveEsNodes.length) {
productStatus.byUuid = liveEsNodes.reduce((accum, esNode) => ({
...accum,
[esNode.id]: {
node: esNode,
isNetNewUser: true
},
}), {});
}
if (product.name === KIBANA_SYSTEM_ID && liveKibanaInstance) {
const kibanaLiveUuid = get(liveKibanaInstance, 'kibana.uuid');
if (kibanaLiveUuid) {
productStatus.byUuid = {
[kibanaLiveUuid]: {
instance: liveKibanaInstance,
isNetNewUser: true
}
};
}
}
// If there is no data, then they are a net new user
if (!indexBuckets || indexBuckets.length === 0) {
productStatus.totalUniqueInstanceCount = 0;
@ -400,6 +389,7 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
}
}
productStatus.totalUniqueInstanceCount = Object.keys(map).length;
productStatus.totalUniqueInternallyCollectedCount = Object.keys(internalCollectorsUuidsMap).length;
productStatus.totalUniquePartiallyMigratedCount = Object.keys(partiallyMigratedUuidsMap).length;
productStatus.totalUniqueFullyMigratedCount = Object.keys(fullyMigratedUuidsMap).length;
productStatus.byUuid = {
@ -435,7 +425,7 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
}
// If there are multiple buckets, they are partially upgraded assuming a single mb index exists
else {
const considerAllInstancesMigrated = product.name === ELASTICSEARCH_CUSTOM_ID &&
const considerAllInstancesMigrated = product.name === ELASTICSEARCH_SYSTEM_ID &&
clusterUuid === liveClusterUuid && !liveClusterInternalCollectionEnabled;
const internalTimestamps = [];
for (const indexBucket of indexBuckets) {
@ -479,6 +469,7 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
...Object.keys(fullyMigratedUuidsMap),
...Object.keys(partiallyMigratedUuidsMap)
]).length;
productStatus.totalUniqueInternallyCollectedCount = Object.keys(internalCollectorsUuidsMap).length;
productStatus.totalUniquePartiallyMigratedCount = Object.keys(partiallyMigratedUuidsMap).length;
productStatus.totalUniqueFullyMigratedCount = Object.keys(fullyMigratedUuidsMap).length;
productStatus.byUuid = {
@ -518,6 +509,35 @@ export const getCollectionStatus = async (req, indexPatterns, clusterUuid, nodeU
productStatus.detected = detectedProducts[product.name];
}
if (product.name === ELASTICSEARCH_SYSTEM_ID && liveEsNodes.length) {
productStatus.byUuid = liveEsNodes.reduce((byUuid, esNode) => {
if (!byUuid[esNode.id]) {
productStatus.totalUniqueInstanceCount++;
return {
...byUuid,
[esNode.id]: {
node: esNode,
isNetNewUser: true
},
};
}
return byUuid;
}, productStatus.byUuid);
}
if (product.name === KIBANA_SYSTEM_ID && liveKibanaInstance) {
const kibanaLiveUuid = get(liveKibanaInstance, 'kibana.uuid');
if (kibanaLiveUuid && !productStatus.byUuid[kibanaLiveUuid]) {
productStatus.totalUniqueInstanceCount++;
productStatus.byUuid = {
[kibanaLiveUuid]: {
instance: liveKibanaInstance,
isNetNewUser: true
}
};
}
}
return {
...products,
[product.name]: productStatus,

View file

@ -8171,9 +8171,6 @@
"xpack.monitoring.elasticsearch.nodes.diskFreeSpaceColumnTitle": "ディスクの空き容量",
"xpack.monitoring.elasticsearch.nodes.jvmMemoryColumnTitle": "{javaVirtualMachine} メモリー",
"xpack.monitoring.elasticsearch.nodes.loadAverageColumnTitle": "平均負荷",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionDescription": "ご使用の Elasticsearch サーバーはすべて Metricbeat により監視されています。\n 但し、移行を完了させるには内部収集を無効にする必要があります。",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionMigrationButtonLabel": "無効にして移行を完了させる",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionTitle": "内部収集を無効にして移行を完了させる",
"xpack.monitoring.elasticsearch.nodes.monitoringTablePlaceholder": "ノードをフィルタリング…",
"xpack.monitoring.elasticsearch.nodes.nameColumnTitle": "名前",
"xpack.monitoring.elasticsearch.nodes.routeTitle": "Elasticsearch - ノード",
@ -8241,10 +8238,6 @@
"xpack.monitoring.euiTable.isFullyMigratedLabel": "Metricbeat 収集",
"xpack.monitoring.euiTable.isInternalCollectorLabel": "内部収集",
"xpack.monitoring.euiTable.isPartiallyMigratedLabel": "内部収集と Metricbeat 収集",
"xpack.monitoring.euiTable.migrateButtonLabel": "移行",
"xpack.monitoring.euiTable.migrationStatusUnknown": "N/A",
"xpack.monitoring.euiTable.setupActionTitle": "セットアップアクション",
"xpack.monitoring.euiTable.setupStatusTitle": "セットアップステータス",
"xpack.monitoring.feature.reserved.description": "ユーザーアクセスを許可するには、monitoring_user ロールも割り当てる必要があります。",
"xpack.monitoring.featureRegistry.monitoringFeatureName": "スタック監視",
"xpack.monitoring.formatNumbers.notAvailableLabel": "N/A",
@ -8366,58 +8359,32 @@
"xpack.monitoring.logstashNavigation.pipelineVersionDescription": "バージョンは {relativeLastSeen} 時点でアクティブ、初回検知 {relativeFirstSeen}",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.configureMetricbeatDescription": "{file} にこれらの変更を加えます。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.configureMetricbeatTitle": "Metricbeat を構成して監視クラスターに送ります",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.fullyMigratedStatusDescription": "内部収集からのドキュメントがありません。移行完了!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "最後の内部収集は {secondsSinceLastInternalCollectionLabel} 前に行われました。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollectionDescription": "Elasticsearch 監視メトリックの内部収集を無効にします。本番クラスターの各サーバーの {monospace} を false に設定します。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollectionTitle": "Elasticsearch 監視メトリックの内部収集を無効にする",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.enableMetricbeatModuleDescription": "モジュールはデフォルトで {url} から Elasticsearch 監視メトリックを収集します。ローカル Elasticsearch サーバーのアドレスが異なる場合は、{module} ファイルのホスト設定で指定する必要があります。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.enableMetricbeatModuleTitle": "Metricbeat の Elasticsearch X-Pack モジュールの有効化と構成",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.fullyMigratedStatusDescription": "Metricbeat から監視データが送信され始めました!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.installMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.installMetricbeatTitle": "Metricbeat を Elasticsearch と同じサーバーにインストール",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.metricbeatSecuritySetup": "セキュリティ機能が有効な場合、追加セットアップが必要な可能性があります。{link}",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.metricbeatSecuritySetupLinkText": "詳細をご覧ください。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.partiallyMigratedStatusTitle": "現在も Elasticsearch の内部収集からデータが送信されています。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.startMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.startMetricbeatTitle": "Metricbeat を起動します",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitle": "移行ステータス",
"xpack.monitoring.metricbeatMigration.flyout.closeButtonLabel": "閉じる",
"xpack.monitoring.metricbeatMigration.flyout.doneButtonLabel": "完了",
"xpack.monitoring.metricbeatMigration.flyout.elasticsearchNode": "ノード",
"xpack.monitoring.metricbeatMigration.flyout.elasticsearchNodesTitle": "Elasticsearch ノード",
"xpack.monitoring.metricbeatMigration.flyout.flyoutTitle": "{instanceName} {instanceType} の Metricbeat への移行",
"xpack.monitoring.metricbeatMigration.flyout.kibanaInstance": "インスタンス",
"xpack.monitoring.metricbeatMigration.flyout.nextButtonLabel": "次へ",
"xpack.monitoring.metricbeatMigration.flyout.step1.monitoringUrlHelpText": "これは通常単一のインスタンスですが、複数ある場合は、すべてのインスタンス URL をコンマ区切りで入力します。\n Metricbeat インスタンスの実行には、Elasticsearch サーバーとの通信が必要です。",
"xpack.monitoring.metricbeatMigration.flyout.step1.monitoringUrlLabel": "監視クラスター URL",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.configureMetricbeatDescription": "{file} にこれらの変更を加えます。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.configureMetricbeatTitle": "Metricbeat を構成して監視クラスターに送ります",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.checkingStatusButtonLabel": "確認中...",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.checkStatusButtonLabel": "確認",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.description": "Kibana 構成ファイル ({file}) に次の設定を追加します:",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.fullyMigratedStatusDescription": "内部収集からのドキュメントがありません。移行完了!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.note": "{config} をデフォルト値のままにします ({defaultValue})。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "最後の内部収集は {secondsSinceLastInternalCollectionLabel} 前に行われました。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.restartNote": "このステップには Kibana サーバーの再起動が必要です。サーバーの再起動が完了するまでエラーが表示されます。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.restartWarningTitle": "警告",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.statusDescription": "内部収集からのドキュメントがないことを確認してください。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.title": "Kibana 監視メトリックの内部収集を無効にする",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.enableMetricbeatModuleDescription": "モジュールはデフォルトで http://localhost:5601 から Kibana 監視メトリックを収集します。ローカル Kibana インスタンスのアドレスが異なる場合は、{file} ファイルの {hosts} 設定で指定する必要があります。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.enableMetricbeatModuleTitle": "Metricbeat の Kibana X-Pack もウールの有効化と構成",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.fullyMigratedStatusDescription": "Metricbeat から監視データが送信され始めました!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.installMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.installMetricbeatTitle": "Metricbeat を Kibana と同じサーバーにインストール",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.metricbeatSecuritySetup": "セキュリティ機能が有効な場合、追加セットアップが必要な可能性があります。{link}",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.metricbeatSecuritySetupLinkText": "詳細をご覧ください。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.partiallyMigratedStatusDescription": "検出には最長 {secondsAgo} 秒かかる場合がありますが、引き続きバックグラウンドで {timePeriod} 秒ごとに確認します。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.partiallyMigratedStatusTitle": "現在も Kibana の内部収集からデータが送信されています。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.startMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.startMetricbeatTitle": "Metricbeat を起動します",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitle": "移行ステータス",
"xpack.monitoring.metrics.apm.outputAckedEventsRate.ackedDescription": "アウトプットにより処理されたイベントです (再試行を含む)",
"xpack.monitoring.metrics.apm.outputAckedEventsRate.ackedLabel": "承認済み",
"xpack.monitoring.metrics.apm.outputAckedEventsRateTitle": "アウトプット承認イベントレート",
@ -8957,131 +8924,52 @@
"xpack.monitoring.summaryStatus.statusIconLabel": "ステータス: {status}",
"xpack.monitoring.summaryStatus.statusIconTitle": "ステータス: {statusIcon}",
"xpack.monitoring.uiExportsDescription": "Elastic Stack の監視です",
"xpack.monitoring.apm.instances.metricbeatMigration.detectedInstanceDescription": "インデックスによると、APM サーバーがあると思われます。下の「監視をセットアップ」をクリックして\n この APM サーバーの監視を開始してください。",
"xpack.monitoring.apm.instances.metricbeatMigration.detectedInstanceTitle": "APM サーバーが検出されました",
"xpack.monitoring.apm.metricbeatMigration.setupNewButtonLabel": "新規 APM サーバーの監視をセットアップ",
"xpack.monitoring.beats.instances.metricbeatMigration.detectedInstanceDescription": "インデックスによると、Beats インスタンスがあると思われます。下の「監視をセットアップ」をクリックして\n このインスタンスの監視を開始してください。",
"xpack.monitoring.beats.instances.metricbeatMigration.detectedInstanceTitle": "Beats インスタンスが検出されました",
"xpack.monitoring.beats.metricbeatMigration.setupNewButtonLabel": "新規 Beats インスタンスの監視をセットアップ",
"xpack.monitoring.chart.timeSeries.zoomOut": "ズームアウト",
"xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip.disableInternal": "すべてのサーバーが Metricbeat によって監視されていますが、内部収集を\n オフにする必要があります。フラッグアイコンをクリックして、サーバーリストページにアクセスし、内部収集を無効にしてください。",
"xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip.oneInternal": "Metricbeat により監視されていないサーバーが少なくとも 1 つあります。フラッグ\n アイコンをクリックして、サーバーリストページにアクセスし、各サーバーの詳細なステータスを確認してください。",
"xpack.monitoring.cluster.overview.beatsPanel.setupModeNodesTooltip.disableInternal": "すべてのインスタンスが Metricbeat によって監視されていますが、内部収集を\n オフにする必要があります。フラッグアイコンをクリックして、インスタンスリストページにアクセスし、内部収集を無効にしてください。",
"xpack.monitoring.cluster.overview.beatsPanel.setupModeNodesTooltip.oneInternal": "Metricbeat により監視されていないインスタンスが少なくとも 1 つあります。フラッグ\n アイコンをクリックして、インスタンスリストページにアクセスし、各インスタンスの詳細なステータスを確認してください。",
"xpack.monitoring.cluster.overview.elasticsearchPanel.setupModeNodesTooltip.disableInternal": "すべてのノードが Metricbeat によって監視されていますが、内部収集を上のメニューバーの\n フラッグアイコンをクリックして、ノードリストページにアクセスし、内部収集を無効にしてください。",
"xpack.monitoring.cluster.overview.elasticsearchPanel.setupModeNodesTooltip.oneInternal": "Metricbeat により監視されていないノードが少なくとも 1 つあります。フラッグアイコンをクリックして、ノード\n リストページにアクセスし、各ノードの詳細なステータスを確認してください。",
"xpack.monitoring.cluster.overview.kibanaPanel.setupModeNodesTooltip.disableInternal": "すべてのインスタンスが Metricbeat によって監視されていますが、内部収集を\n オフにする必要があります。フラッグアイコンをクリックして、インスタンスリストページにアクセスし、内部収集を無効にしてください。",
"xpack.monitoring.cluster.overview.kibanaPanel.setupModeNodesTooltip.oneInternal": "Metricbeat により監視されていないインスタンスが少なくとも 1 つあります。フラッグ\n アイコンをクリックして、インスタンスリストページにアクセスし、各インスタンスの詳細なステータスを確認してください。",
"xpack.monitoring.cluster.overview.logstashPanel.setupModeNodesTooltip.disableInternal": "すべてのノードが Metricbeat によって監視されていますが、内部収集を\n オフにする必要があります。フラッグアイコンをクリックして、ノードリストページにアクセスし、内部収集を無効にしてください。",
"xpack.monitoring.cluster.overview.logstashPanel.setupModeNodesTooltip.oneInternal": "Metricbeat により監視されていないノードが少なくとも 1 つあります。フラッグ\n アイコンをクリックして、ノードリストページにアクセスし、各ノードの詳細なステータスを確認してください。",
"xpack.monitoring.elasticsearch.metricbeatMigration.setupNewButtonLabel": "新規 Elasticsearch ノードの監視をセットアップ",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserDescription": "監視データは検出されませんでしたが、次の Elasticsearch ノードが検出されました。\n 検出された各ノードとセットアップボタンが下に表示されます。このボタンをクリックすると、\n 各ノードの監視を有効にするプロセスをご案内します。",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserTitle": "監視データが検出されませんでした",
"xpack.monitoring.errors.monitoringLicenseErrorDescription": "クラスター = 「{clusterId}」のライセンス情報が見つかりませんでした。クラスターのマスターノードサーバーログにエラーや警告がないか確認してください。",
"xpack.monitoring.errors.monitoringLicenseErrorTitle": "監視ライセンスエラー",
"xpack.monitoring.euiTable.isNetNewUserLabel": "監視が検出されませんでした",
"xpack.monitoring.euiTable.setupButtonLabel": "セットアップ",
"xpack.monitoring.kibana.metricbeatMigration.setupNewButtonLabel": "新規 Kibana インスタンスの監視をセットアップ",
"xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserDescription": "監視データは検出されませんでしたが、次の Kibana インスタンスが検出されました。\n 検出されたインスタンスとセットアップボタンが下に表示されます。このボタンをクリックすると、\n このインスタンスの監視を有効にするプロセスをご案内します。",
"xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserTitle": "監視データが検出されませんでした",
"xpack.monitoring.logs.reason.defaultMessage": "ログデータが見つからず、理由を診断することができません。{link}",
"xpack.monitoring.logs.reason.defaultMessageLink": "正しくセットアップされていることを確認してください。",
"xpack.monitoring.logs.reason.defaultTitle": "ログデータが見つかりませんでした",
"xpack.monitoring.logstash.metricbeatMigration.setupNewButtonLabel": "新規 Logstash サーバーの監視をセットアップ",
"xpack.monitoring.logstash.nodes.metribeatMigration.netNewUserDescription": "インデックスによると、Logstash ノードがあると思われます。下の「監視をセットアップ」をクリックして\n このノードの監視を開始してください。",
"xpack.monitoring.logstash.nodes.metribeatMigration.netNewUserTitle": "監視データが検出されませんでした",
"xpack.monitoring.metricbeatMigration.apmInstructions.configureMetricbeatDescription": "{file} にこれらの変更を加えます。",
"xpack.monitoring.metricbeatMigration.apmInstructions.configureMetricbeatTitle": "Metricbeat を構成して監視クラスターに送ります",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.checkingStatusButtonLabel": "確認中...",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.checkStatusButtonLabel": "確認",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.description": "APM サーバーの構成ファイル ({file}) に次の設定を追加します:",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.fullyMigratedStatusDescription": "内部収集からのドキュメントがありません。移行完了!",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.note": "この変更後、APM サーバーの再起動が必要です。",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "最後の内部収集は {secondsSinceLastInternalCollectionLabel} 前に行われました。",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.statusDescription": "内部収集からのドキュメントがないことを確認してください。",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.title": "APM サーバーの監視メトリックの内部収集を無効にする",
"xpack.monitoring.metricbeatMigration.apmInstructions.enableMetricbeatModuleDescription": "モジュールはデフォルトで http://localhost:5066 から APM サーバーの監視メトリックを収集します。ローカル APM サーバーのアドレスが異なる場合は、{file} ファイルの {hosts} 設定で指定する必要があります。",
"xpack.monitoring.metricbeatMigration.apmInstructions.enableMetricbeatModuleTitle": "Metricbeat の Beat X-Pack モジュールの有効化と構成",
"xpack.monitoring.metricbeatMigration.apmInstructions.fullyMigratedStatusDescription": "Metricbeat から監視データが送信され始めました!",
"xpack.monitoring.metricbeatMigration.apmInstructions.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.apmInstructions.installMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.apmInstructions.installMetricbeatTitle": "Metricbeat を APM サーバーと同じサーバーにインストール",
"xpack.monitoring.metricbeatMigration.apmInstructions.isInternalCollectorStatusTitle": "この APM サーバーの Metricbeat からの監視データが検出されていません。\n 引き続きバックグラウンドで確認を続けます。",
"xpack.monitoring.metricbeatMigration.apmInstructions.metricbeatSecuritySetup": "セキュリティ機能が有効な場合、追加セットアップが必要な可能性があります。{link}",
"xpack.monitoring.metricbeatMigration.apmInstructions.metricbeatSecuritySetupLinkText": "詳細をご覧ください。",
"xpack.monitoring.metricbeatMigration.apmInstructions.partiallyMigratedStatusDescription": "検出には最長 {secondsAgo} 秒かかる場合がありますが、引き続きバックグラウンドで {timePeriod} 秒ごとに確認します。",
"xpack.monitoring.metricbeatMigration.apmInstructions.partiallyMigratedStatusTitle": "現在も APM サーバーの内部収集からデータが送信されています。",
"xpack.monitoring.metricbeatMigration.apmInstructions.startMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.apmInstructions.startMetricbeatTitle": "Metricbeat を起動します",
"xpack.monitoring.metricbeatMigration.apmInstructions.statusTitle": "移行ステータス",
"xpack.monitoring.metricbeatMigration.beatsInstructions.configureMetricbeatDescription": "{file} にこれらの変更を加えます。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.configureMetricbeatTitle": "Metricbeat を構成して監視クラスターに送ります",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.checkingStatusButtonLabel": "確認中...",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.checkStatusButtonLabel": "確認",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.description": "{beatType} の構成ファイル ({file}) に次の設定を追加します:",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.fullyMigratedStatusDescription": "内部収集からのドキュメントがありません。移行完了!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.note": "この変更後、{beatType} の再起動が必要です。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "最後の内部収集は {secondsSinceLastInternalCollectionLabel} 前に行われました。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.statusDescription": "内部収集からのドキュメントがないことを確認してください。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.title": "{beatType} の監視メトリックの内部収集を無効にする",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleDescription": "モジュールはデフォルトで http://localhost:5066 から {beatType} 監視メトリックを収集します。監視されている {beatType} インスタンスのアドレスが異なる場合は、{file} ファイルの {hosts} 設定で指定する必要があります。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleHttpEnabledDirections": "Metricbeat が実行中の {beatType} からメトリックを収集するには、{link} 必要があります。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleHttpEnabledDirectionsLinkText": "監視されている {beatType} の HTTP エンドポイントを有効にする",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleTitle": "Metricbeat の Beat X-Pack モジュールの有効化と構成",
"xpack.monitoring.metricbeatMigration.beatsInstructions.fullyMigratedStatusDescription": "Metricbeat から監視データが送信され始めました!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.installMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.beatsInstructions.installMetricbeatTitle": "Metricbeat を {beatType} と同じサーバーにインストール",
"xpack.monitoring.metricbeatMigration.beatsInstructions.isInternalCollectorStatusTitle": "この Beat の Metricbeat からの監視データが検出されていません。\n 引き続きバックグラウンドで確認を続けます。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.metricbeatSecuritySetup": "セキュリティ機能が有効な場合、追加セットアップが必要な可能性があります。{link}",
"xpack.monitoring.metricbeatMigration.beatsInstructions.metricbeatSecuritySetupLinkText": "詳細をご覧ください。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.partiallyMigratedStatusDescription": "検出には最長 {secondsAgo} 秒かかる場合がありますが、引き続きバックグラウンドで {timePeriod} 秒ごとに確認します。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.partiallyMigratedStatusTitle": "現在も Beat の内部収集からデータが送信されています。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.startMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.beatsInstructions.startMetricbeatTitle": "Metricbeat を起動します",
"xpack.monitoring.metricbeatMigration.beatsInstructions.statusTitle": "移行ステータス",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitleNewUser": "監視ステータス",
"xpack.monitoring.metricbeatMigration.flyout.flyoutTitleNewUser": "Metricbeat で {instanceName} {instanceType} を監視",
"xpack.monitoring.metricbeatMigration.flyout.instance": "インスタンス",
"xpack.monitoring.metricbeatMigration.flyout.noClusterUuidCheckboxLabel": "はい、\n この {productName} {typeText} スタンドアロンクラスターを調べる必要があることを理解しています。",
"xpack.monitoring.metricbeatMigration.flyout.noClusterUuidDescription": "この {productName} {typeText} は Elasticsearch クラスターに接続されていないため、完全に移行された時点で、この {productName} {typeText} はこのクラスターではなくスタンドアロンクラスターに表示されます。 {link}",
"xpack.monitoring.metricbeatMigration.flyout.noClusterUuidTitle": "クラスターが検出されてませんでした",
"xpack.monitoring.metricbeatMigration.flyout.node": "ノード",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitleNewUser": "監視ステータス",
"xpack.monitoring.metricbeatMigration.logstashInstructions.configureMetricbeatDescription": "{file} にこれらの変更を加えます。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.configureMetricbeatTitle": "Metricbeat を構成して監視クラスターに送ります",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.checkingStatusButtonLabel": "確認中...",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.checkStatusButtonLabel": "確認",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.description": "Logstash 構成ファイル ({file}) に次の設定を追加します:",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.fullyMigratedStatusDescription": "内部収集からのドキュメントがありません。移行完了!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.note": "この変更後、Logstash の再起動が必要です。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "最後の内部収集は {secondsSinceLastInternalCollectionLabel} 前に行われました。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.statusDescription": "内部収集からのドキュメントがないことを確認してください。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.title": "Logstash 監視メトリックの内部収集を無効にする",
"xpack.monitoring.metricbeatMigration.logstashInstructions.enableMetricbeatModuleDescription": "モジュールはデフォルトで http://localhost:9600 から Logstash 監視メトリックを収集します。ローカル Logstash インスタンスのアドレスが異なる場合は、{file} ファイルの {hosts} 設定で指定する必要があります。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.enableMetricbeatModuleTitle": "Metricbeat の Logstash X-Pack もウールの有効化と構成",
"xpack.monitoring.metricbeatMigration.logstashInstructions.fullyMigratedStatusDescription": "Metricbeat から監視データが送信され始めました!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.fullyMigratedStatusTitle": "お疲れさまでした!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.installMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.logstashInstructions.installMetricbeatTitle": "Metricbeat を Logstash と同じサーバーにインストール",
"xpack.monitoring.metricbeatMigration.logstashInstructions.isInternalCollectorStatusTitle": "この Metricbeat ノードの Metricbeat からの監視データが検出されていません。\n 引き続きバックグラウンドで確認を続けます。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.metricbeatSecuritySetup": "セキュリティ機能が有効な場合、追加セットアップが必要な可能性があります。{link}",
"xpack.monitoring.metricbeatMigration.logstashInstructions.metricbeatSecuritySetupLinkText": "詳細をご覧ください。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.partiallyMigratedStatusDescription": "検出には最長 {secondsAgo} 秒かかる場合がありますが、引き続きバックグラウンドで {timePeriod} 秒ごとに確認します。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.partiallyMigratedStatusTitle": "現在も Logstash の内部収集からデータが送信されています。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.startMetricbeatLinkText": "こちらの手順に従ってください",
"xpack.monitoring.metricbeatMigration.logstashInstructions.startMetricbeatTitle": "Metricbeat を起動します",
"xpack.monitoring.metricbeatMigration.logstashInstructions.statusTitle": "移行ステータス",
"xpack.monitoring.noData.blurbs.cloudDeploymentDescription": "次の場所に戻ってください: ",
"xpack.monitoring.noData.blurbs.cloudDeploymentDescriptionMore": "Elastic Cloud での監視の詳細は、 ",
"xpack.monitoring.noData.blurbs.cloudDeploymentTitle": "監視データはこちらに表示されません。",
"xpack.monitoring.noData.explanations.exportersCloudDescription": "Elastic Cloud では、監視データが専用の監視クラスターに格納されます。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.isInternalCollectorStatusTitle": "この Elasticsearch ノードの Metricbeat からの監視データが検出されていません。\n 引き続きバックグラウンドで確認を続けます。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.partiallyMigratedStatusDescription": "検出には最長 {secondsAgo} 秒かかる場合がありますが、引き続きバックグラウンドで確認します。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.isInternalCollectorStatusTitle": "この Kibana インスタンスの Metricbeat からの監視データが検出されていません。\n 引き続きバックグラウンドで確認を続けます。",
"xpack.remoteClusters.addAction.clusterNameAlreadyExistsErrorMessage": "「{clusterName}」という名前のクラスターが既に存在します。",
"xpack.remoteClusters.addAction.errorTitle": "クラスターの追加中にエラーが発生",
"xpack.remoteClusters.addAction.failedDefaultErrorMessage": "{statusCode} エラーでリクエスト失敗: {message}",

View file

@ -8173,9 +8173,6 @@
"xpack.monitoring.elasticsearch.nodes.diskFreeSpaceColumnTitle": "磁盘可用空间",
"xpack.monitoring.elasticsearch.nodes.jvmMemoryColumnTitle": "{javaVirtualMachine} 内存",
"xpack.monitoring.elasticsearch.nodes.loadAverageColumnTitle": "负载平均值",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionDescription": "系统将使用 Metricbeat 监测所有 Elasticsearch 服务器,\n 但您需要禁用内部收集以完成迁移。",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionMigrationButtonLabel": "禁用并完成迁移",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.disableInternalCollectionTitle": "禁用内部收集以完成迁移",
"xpack.monitoring.elasticsearch.nodes.monitoringTablePlaceholder": "筛选节点……",
"xpack.monitoring.elasticsearch.nodes.nameColumnTitle": "名称",
"xpack.monitoring.elasticsearch.nodes.routeTitle": "Elasticsearch - 节点",
@ -8243,10 +8240,6 @@
"xpack.monitoring.euiTable.isFullyMigratedLabel": "Metricbeat 收集",
"xpack.monitoring.euiTable.isInternalCollectorLabel": "内部收集",
"xpack.monitoring.euiTable.isPartiallyMigratedLabel": "内部收集和 Metricbeat 收集",
"xpack.monitoring.euiTable.migrateButtonLabel": "迁移",
"xpack.monitoring.euiTable.migrationStatusUnknown": "不适用",
"xpack.monitoring.euiTable.setupActionTitle": "设置操作",
"xpack.monitoring.euiTable.setupStatusTitle": "设置状态",
"xpack.monitoring.feature.reserved.description": "要向用户授予访问权限,还应分配 monitoring_user 角色。",
"xpack.monitoring.featureRegistry.monitoringFeatureName": "堆栈监测",
"xpack.monitoring.formatNumbers.notAvailableLabel": "不适用",
@ -8368,58 +8361,32 @@
"xpack.monitoring.logstashNavigation.pipelineVersionDescription": "活动版本 {relativeLastSeen} 和首次看到 {relativeFirstSeen}",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.configureMetricbeatDescription": "在 {file} 文件中进行这些更改。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.configureMetricbeatTitle": "配置 Metricbeat 以发送至监测集群",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.fullyMigratedStatusDescription": "我们未看到任何来自内部收集的文档。迁移完成!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "上次内部收集发生于 {secondsSinceLastInternalCollectionLabel}前。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollectionDescription": "禁用 Elasticsearch 监测指标的内部收集。在生产集群中的每个服务器上将 {monospace} 设置为 false。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.disableInternalCollectionTitle": "禁用 Elasticsearch 监测指标的内部收集",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.enableMetricbeatModuleDescription": "默认情况下,该模块将从 {url} 收集 Elasticsearch 监测指标。如果本地 Elasticsearch 服务器有不同的地址,则必须通过 {module} 文件中的 hosts 设置来进行指定。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.enableMetricbeatModuleTitle": "在 Metricbeat 中启用并配置 Elasticsearch x-pack 模块",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.fullyMigratedStatusDescription": "我们现在看到来自 Metricbeat 的监测数据传送!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.installMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.installMetricbeatTitle": "在安装 Elasticsearch 的同一台服务器上安装 Metricbeat",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.metricbeatSecuritySetup": "如果已启用安全功能,则可能需要更多的设置。{link}",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.metricbeatSecuritySetupLinkText": "查看更多信息。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.partiallyMigratedStatusTitle": "我们仍看到数据来自 Elasticsearch 的内部收集。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.startMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.startMetricbeatTitle": "启动 Metricbeat",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitle": "迁移状态",
"xpack.monitoring.metricbeatMigration.flyout.closeButtonLabel": "关闭",
"xpack.monitoring.metricbeatMigration.flyout.doneButtonLabel": "完成",
"xpack.monitoring.metricbeatMigration.flyout.elasticsearchNode": "节点",
"xpack.monitoring.metricbeatMigration.flyout.elasticsearchNodesTitle": "Elasticsearch 节点",
"xpack.monitoring.metricbeatMigration.flyout.flyoutTitle": "将 {instanceName} {instanceType} 迁移到 Metricbeat",
"xpack.monitoring.metricbeatMigration.flyout.kibanaInstance": "实例",
"xpack.monitoring.metricbeatMigration.flyout.nextButtonLabel": "下一个",
"xpack.monitoring.metricbeatMigration.flyout.step1.monitoringUrlHelpText": "这通常是单个实例,但如果您有多个,请输入所有实例 url以逗号分隔。\n 切记运行的 Metricbeat 实例需要能够与这些 Elasticsearch 实例通信。",
"xpack.monitoring.metricbeatMigration.flyout.step1.monitoringUrlLabel": "监测集群 URL",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.configureMetricbeatDescription": "在 {file} 文件中进行这些更改。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.configureMetricbeatTitle": "配置 Metricbeat 以发送至监测集群",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.checkingStatusButtonLabel": "正在检查......",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.checkStatusButtonLabel": "检查",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.description": "在 Kibana 配置文件 ({file}) 中添加以下设置:",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.fullyMigratedStatusDescription": "我们未看到任何来自内部收集的文档。迁移完成!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.note": "将 {config} 设置为其默认值 ({defaultValue})。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "上次内部收集发生于 {secondsSinceLastInternalCollectionLabel}前。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.restartNote": "此步骤需要您重新启动 Kibana 服务器。在服务器再次运行之前应会看到错误。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.restartWarningTitle": "警告",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.statusDescription": "确认没有文档来自内部收集。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.disableInternalCollection.title": "禁用 Kibana 监测指标的内部收集",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.enableMetricbeatModuleDescription": "该模块将默认从 http://localhost:5601 收集 Kibana 监测指标。如果本地 Kibana 实例有不同的地址,则必须通过 {file} 文件中的 {hosts} 设置进行指定。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.enableMetricbeatModuleTitle": "在 Metricbeat 中启用并配置 Kibana x-pack 模块",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.fullyMigratedStatusDescription": "我们现在看到来自 Metricbeat 的监测数据传送!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.installMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.installMetricbeatTitle": "在安装 Kibana 的同一台服务器上安装 Metricbeat",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.metricbeatSecuritySetup": "如果已启用安全功能,则可能需要更多的设置。{link}",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.metricbeatSecuritySetupLinkText": "查看更多信息。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.partiallyMigratedStatusDescription": "请注意,检测最多花费 {secondsAgo} 秒,但我们在后台每 {timePeriod} 秒检查一次。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.partiallyMigratedStatusTitle": "我们仍看到数据来自 Kibana 的内部收集。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.startMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.startMetricbeatTitle": "启动 Metricbeat",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitle": "迁移状态",
"xpack.monitoring.metrics.apm.outputAckedEventsRate.ackedDescription": "输出处理的事件(包括重试)",
"xpack.monitoring.metrics.apm.outputAckedEventsRate.ackedLabel": "已确认",
"xpack.monitoring.metrics.apm.outputAckedEventsRateTitle": "输出已确认事件速率",
@ -8959,131 +8926,52 @@
"xpack.monitoring.summaryStatus.statusIconLabel": "状态:{status}",
"xpack.monitoring.summaryStatus.statusIconTitle": "状态:{statusIcon}",
"xpack.monitoring.uiExportsDescription": "Elastic Stack 的 Monitoring 组件",
"xpack.monitoring.apm.instances.metricbeatMigration.detectedInstanceDescription": "基于您的索引,我们认为您可能有 APM Server。单击下面的“设置监测”\n 按钮以开始监测此 APM Server。",
"xpack.monitoring.apm.instances.metricbeatMigration.detectedInstanceTitle": "检测到 APM Server",
"xpack.monitoring.apm.metricbeatMigration.setupNewButtonLabel": "为新的 APM Server 设置监测",
"xpack.monitoring.beats.instances.metricbeatMigration.detectedInstanceDescription": "基于您的索引,我们认为您可能有 Beats 实例。单击下面的“设置监测”\n 按钮以开始监测此实例。",
"xpack.monitoring.beats.instances.metricbeatMigration.detectedInstanceTitle": "检测到 Beats 实例",
"xpack.monitoring.beats.metricbeatMigration.setupNewButtonLabel": "为新的 Beats 实例设置监测",
"xpack.monitoring.chart.timeSeries.zoomOut": "缩小",
"xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip.disableInternal": "正在使用 Metricbeat 监测所有服务器,但内部收集仍需要\n 关闭。单击旗帜图标可访问服务器列表页面以及禁用内部收集。",
"xpack.monitoring.cluster.overview.apmPanel.setupModeNodesTooltip.oneInternal": "至少有一个服务器未使用 Metricbeat 进行监测。单击旗帜\n 图标可访问服务器列表页面以及详细了解每个服务器的状态。",
"xpack.monitoring.cluster.overview.beatsPanel.setupModeNodesTooltip.disableInternal": "正在使用 Metricbeat 监测所有实例,但内部收集仍需要\n 关闭。单击旗帜图标可访问实例列表页面以及禁用内部收集。",
"xpack.monitoring.cluster.overview.beatsPanel.setupModeNodesTooltip.oneInternal": "至少有一个实例未使用 Metricbeat 进行监测。单击旗帜\n 图标可访问实例列表页面以及详细了解每个实例的状态。",
"xpack.monitoring.cluster.overview.elasticsearchPanel.setupModeNodesTooltip.disableInternal": "正在使用 Metricbeat 监测所有节点,但内部收集仍需要关闭。单击\n 旗帜图标可访问节点列表页面以及禁用内部收集。",
"xpack.monitoring.cluster.overview.elasticsearchPanel.setupModeNodesTooltip.oneInternal": "至少有一个节点未使用 Metricbeat 进行监测。单击旗帜图标可访问节点\n 列表页面以及详细了解每个节点的状态。",
"xpack.monitoring.cluster.overview.kibanaPanel.setupModeNodesTooltip.disableInternal": "正在使用 Metricbeat 监测所有实例,但内部收集仍需要\n 关闭。单击旗帜图标可访问实例列表页面以及禁用内部收集。",
"xpack.monitoring.cluster.overview.kibanaPanel.setupModeNodesTooltip.oneInternal": "至少有一个实例未使用 Metricbeat 进行监测。单击旗帜\n 图标可访问实例列表页面以及详细了解每个实例的状态。",
"xpack.monitoring.cluster.overview.logstashPanel.setupModeNodesTooltip.disableInternal": "正在使用 Metricbeat 监测所有节点,但内部收集仍需要\n 关闭。单击旗帜图标可访问节点列表页面以及禁用内部收集。",
"xpack.monitoring.cluster.overview.logstashPanel.setupModeNodesTooltip.oneInternal": "至少有一个节点未使用 Metricbeat 进行监测。单击旗帜\n 图标可访问节点列表页面以及详细了解每个节点的状态。",
"xpack.monitoring.elasticsearch.metricbeatMigration.setupNewButtonLabel": "为新的 Elasticsearch 节点设置监测",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserDescription": "我们未检测到任何监测数据,但我们却检测到以下 Elasticsearch 节点。\n 检测到的每个节点与相应的“设置”按钮在下面一起列出。单击此按钮,系统将指导您完成\n 为每个节点启用监测的过程。",
"xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserTitle": "未检测到任何监测数据",
"xpack.monitoring.errors.monitoringLicenseErrorDescription": "无法找到集群“{clusterId}”的许可信息。请在集群的主节点服务器日志中查看相关错误或警告。",
"xpack.monitoring.errors.monitoringLicenseErrorTitle": "监测许可错误",
"xpack.monitoring.euiTable.isNetNewUserLabel": "未检测到监测",
"xpack.monitoring.euiTable.setupButtonLabel": "设置",
"xpack.monitoring.kibana.metricbeatMigration.setupNewButtonLabel": "为新的 Kibana 实例设置监测",
"xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserDescription": "我们未检测到任何监测数据,但我们却检测到以下 Kibana 实例。\n 该检测到的实例与相应的“设置”按钮在下面一起列出。单击此按钮,系统将指导您完成\n 为此实例启用监测的过程。",
"xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserTitle": "未检测到任何监测数据",
"xpack.monitoring.logs.reason.defaultMessage": "我们未找到任何日志数据,我们无法诊断原因。{link}",
"xpack.monitoring.logs.reason.defaultMessageLink": "请确认您的设置正确。",
"xpack.monitoring.logs.reason.defaultTitle": "未找到任何日志数据",
"xpack.monitoring.logstash.metricbeatMigration.setupNewButtonLabel": "为新的 Logstash 节点设置监测",
"xpack.monitoring.logstash.nodes.metribeatMigration.netNewUserDescription": "基于您的索引,我们认为您可能有 Logstash 节点。单击下面的“设置监测”\n 按钮以开始监测此节点。",
"xpack.monitoring.logstash.nodes.metribeatMigration.netNewUserTitle": "未检测到任何监测数据",
"xpack.monitoring.metricbeatMigration.apmInstructions.configureMetricbeatDescription": "在 {file} 文件中进行这些更改。",
"xpack.monitoring.metricbeatMigration.apmInstructions.configureMetricbeatTitle": "配置 Metricbeat 以发送至监测集群",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.checkingStatusButtonLabel": "正在检查......",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.checkStatusButtonLabel": "检查",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.description": "在 APM Server 的配置文件 ({file}) 中添加以下设置:",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.fullyMigratedStatusDescription": "我们未看到任何来自内部收集的文档。迁移完成!",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.note": "进行此更改后,需要重新启动 APM Server。",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "上次内部收集发生于 {secondsSinceLastInternalCollectionLabel}前。",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.statusDescription": "确认没有文档来自内部收集。",
"xpack.monitoring.metricbeatMigration.apmInstructions.disableInternalCollection.title": "禁用 APM Server 监测指标的内部收集",
"xpack.monitoring.metricbeatMigration.apmInstructions.enableMetricbeatModuleDescription": "该模块将默认从 http://localhost:5066 收集 APM Server 监测指标。如果本地 APM Server 有不同的地址,则必须通过 {file} 文件中的 {hosts} 设置进行指定。",
"xpack.monitoring.metricbeatMigration.apmInstructions.enableMetricbeatModuleTitle": "在 Metricbeat 中启用并配置 Beat x-pack 模块",
"xpack.monitoring.metricbeatMigration.apmInstructions.fullyMigratedStatusDescription": "我们现在看到来自 Metricbeat 的监测数据传送!",
"xpack.monitoring.metricbeatMigration.apmInstructions.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.apmInstructions.installMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.apmInstructions.installMetricbeatTitle": "在安装 APM Server 的同一台服务器上安装 Metricbeat",
"xpack.monitoring.metricbeatMigration.apmInstructions.isInternalCollectorStatusTitle": "我们未检测到任何监测数据来自此 APM Server 的 Metricbeat。\n 我们将持续在后台检查。",
"xpack.monitoring.metricbeatMigration.apmInstructions.metricbeatSecuritySetup": "如果已启用安全功能,则可能需要更多的设置。{link}",
"xpack.monitoring.metricbeatMigration.apmInstructions.metricbeatSecuritySetupLinkText": "查看更多信息。",
"xpack.monitoring.metricbeatMigration.apmInstructions.partiallyMigratedStatusDescription": "请注意,检测最多花费 {secondsAgo} 秒,但我们在后台每 {timePeriod} 秒检查一次。",
"xpack.monitoring.metricbeatMigration.apmInstructions.partiallyMigratedStatusTitle": "我们仍看到数据来自此 APM Server 的内部收集。",
"xpack.monitoring.metricbeatMigration.apmInstructions.startMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.apmInstructions.startMetricbeatTitle": "启动 Metricbeat",
"xpack.monitoring.metricbeatMigration.apmInstructions.statusTitle": "迁移状态",
"xpack.monitoring.metricbeatMigration.beatsInstructions.configureMetricbeatDescription": "在 {file} 文件中进行这些更改。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.configureMetricbeatTitle": "配置 Metricbeat 以发送至监测集群",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.checkingStatusButtonLabel": "正在检查......",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.checkStatusButtonLabel": "检查",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.description": "在 {beatType} 的配置文件 ({file}) 中添加以下设置:",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.fullyMigratedStatusDescription": "我们未看到任何来自内部收集的文档。迁移完成!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.note": "进行此更改后,您需要重新启动 {beatType}。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "上次内部收集发生于 {secondsSinceLastInternalCollectionLabel}前。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.statusDescription": "确认没有文档来自内部收集。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.disableInternalCollection.title": "禁用 {beatType} 监测指标的内部收集",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleDescription": "该模块将默认从 http://localhost:5066 收集 {beatType} 监测指标。如果正在监测的 {beatType} 实例有不同的地址,则必须通过 {file} 文件中的 {hosts} 设置进行指定。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleHttpEnabledDirections": "要使 Metricbeat 从正在运行的 {beatType} 收集指标,需要{link}。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleHttpEnabledDirectionsLinkText": "为正在监测的 {beatType} 实例启用 HTTP 终端节点",
"xpack.monitoring.metricbeatMigration.beatsInstructions.enableMetricbeatModuleTitle": "在 Metricbeat 中启用并配置 Beat x-pack 模块",
"xpack.monitoring.metricbeatMigration.beatsInstructions.fullyMigratedStatusDescription": "我们现在看到来自 Metricbeat 的监测数据传送!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.beatsInstructions.installMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.beatsInstructions.installMetricbeatTitle": "在安装此 {beatType} 的同一台服务器上安装 Metricbeat",
"xpack.monitoring.metricbeatMigration.beatsInstructions.isInternalCollectorStatusTitle": "我们未检测到任何监测数据来自此 Beat 的 Metricbeat。\n 我们将持续在后台检查。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.metricbeatSecuritySetup": "如果已启用安全功能,则可能需要更多的设置。{link}",
"xpack.monitoring.metricbeatMigration.beatsInstructions.metricbeatSecuritySetupLinkText": "查看更多信息。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.partiallyMigratedStatusDescription": "请注意,检测最多花费 {secondsAgo} 秒,但我们在后台每 {timePeriod} 秒检查一次。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.partiallyMigratedStatusTitle": "我们仍看到数据来自此 Beat 的内部收集。",
"xpack.monitoring.metricbeatMigration.beatsInstructions.startMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.beatsInstructions.startMetricbeatTitle": "启动 Metricbeat",
"xpack.monitoring.metricbeatMigration.beatsInstructions.statusTitle": "迁移状态",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitleNewUser": "监测状态",
"xpack.monitoring.metricbeatMigration.flyout.flyoutTitleNewUser": "使用 Metricbeat 监测 {instanceName} {instanceType}",
"xpack.monitoring.metricbeatMigration.flyout.instance": "实例",
"xpack.monitoring.metricbeatMigration.flyout.noClusterUuidCheckboxLabel": "是的,我明白我将需要在独立集群中寻找\n 此 {productName} {typeText}。",
"xpack.monitoring.metricbeatMigration.flyout.noClusterUuidDescription": "此 {productName} {typeText} 未连接到 Elasticsearch 集群,因此完全迁移后,此 {productName} {typeText} 将显示在独立集群中,而非此集群中。{link}",
"xpack.monitoring.metricbeatMigration.flyout.noClusterUuidTitle": "未检测到集群",
"xpack.monitoring.metricbeatMigration.flyout.node": "节点",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitleNewUser": "监测状态",
"xpack.monitoring.metricbeatMigration.logstashInstructions.configureMetricbeatDescription": "在 {file} 文件中进行这些更改。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.configureMetricbeatTitle": "配置 Metricbeat 以发送至监测集群",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.checkingStatusButtonLabel": "正在检查......",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.checkStatusButtonLabel": "检查",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.description": "在 Logstash 配置文件 ({file}) 中添加以下设置:",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.fullyMigratedStatusDescription": "我们未看到任何来自内部收集的文档。迁移完成!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.note": "进行此更改后,您需要重新启动 Logstash。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.partiallyMigratedStatusDescription": "上次内部收集发生于 {secondsSinceLastInternalCollectionLabel}前。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.statusDescription": "确认没有文档来自内部收集。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.disableInternalCollection.title": "禁用 Logstash 监测指标的内部收集",
"xpack.monitoring.metricbeatMigration.logstashInstructions.enableMetricbeatModuleDescription": "该模块将默认从 http://localhost:9600 收集 Logstash 监测指标。如果本地 Logstash 实例有不同的地址,则必须通过 {file} 文件中的 {hosts} 设置进行指定。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.enableMetricbeatModuleTitle": "在 Metricbeat 中启用并配置 Logstash x-pack 模块",
"xpack.monitoring.metricbeatMigration.logstashInstructions.fullyMigratedStatusDescription": "我们现在看到来自 Metricbeat 的监测数据传送!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.fullyMigratedStatusTitle": "恭喜您!",
"xpack.monitoring.metricbeatMigration.logstashInstructions.installMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.logstashInstructions.installMetricbeatTitle": "在安装 Logstash 的同一台服务器上安装 Metricbeat",
"xpack.monitoring.metricbeatMigration.logstashInstructions.isInternalCollectorStatusTitle": "我们未检测到任何监测数据来自此 Logstash 节点的 Metricbeat。\n 我们将持续在后台检查。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.metricbeatSecuritySetup": "如果已启用安全功能,则可能需要更多的设置。{link}",
"xpack.monitoring.metricbeatMigration.logstashInstructions.metricbeatSecuritySetupLinkText": "查看更多信息。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.partiallyMigratedStatusDescription": "请注意,检测最多花费 {secondsAgo} 秒,但我们在后台每 {timePeriod} 秒检查一次。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.partiallyMigratedStatusTitle": "我们仍看到数据来自 Logstash 的内部收集。",
"xpack.monitoring.metricbeatMigration.logstashInstructions.startMetricbeatLinkText": "按照此处的说明执行操作",
"xpack.monitoring.metricbeatMigration.logstashInstructions.startMetricbeatTitle": "启动 Metricbeat",
"xpack.monitoring.metricbeatMigration.logstashInstructions.statusTitle": "迁移状态",
"xpack.monitoring.noData.blurbs.cloudDeploymentDescription": "请返回到您的 ",
"xpack.monitoring.noData.blurbs.cloudDeploymentDescriptionMore": "有关在 Elastic Cloud 中监测的详情,请参阅 ",
"xpack.monitoring.noData.blurbs.cloudDeploymentTitle": "此处没有您的监测数据。",
"xpack.monitoring.noData.explanations.exportersCloudDescription": "在 Elastic Cloud 中,您的监测数据将存储在专用监测集群中。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.isInternalCollectorStatusTitle": "我们未检测到任何监测数据来自此 Elasticsearch 节点的 Metricbeat。\n 我们将持续在后台检查。",
"xpack.monitoring.metricbeatMigration.elasticsearchInstructions.partiallyMigratedStatusDescription": "请注意,检测最多花费 {secondsAgo} 秒,但我们将在后台持续检查。",
"xpack.monitoring.metricbeatMigration.kibanaInstructions.isInternalCollectorStatusTitle": "我们未检测到任何监测数据来自此 Kibana 实例的 Metricbeat。\n 我们将持续在后台检查。",
"xpack.remoteClusters.addAction.clusterNameAlreadyExistsErrorMessage": "名为 “{clusterName}” 的集群已存在。",
"xpack.remoteClusters.addAction.errorTitle": "添加集群时出错",
"xpack.remoteClusters.addAction.failedDefaultErrorMessage": "请求失败,显示 {statusCode} 错误。{message}",

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},
@ -12,6 +13,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -21,6 +23,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -30,6 +33,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": true
},
@ -39,6 +43,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 1,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"5b2de169-2785-441b-ae8c-186a1936b17d": {
@ -17,6 +18,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": true
},
@ -26,6 +28,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -35,6 +38,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -44,6 +48,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 1,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"agI8JhXhShasvuDgq0VxRg": {

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},
@ -12,6 +13,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": true
},
@ -21,6 +23,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -30,6 +33,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -39,6 +43,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},
@ -12,6 +13,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -21,6 +23,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": true
},
@ -30,6 +33,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -39,6 +43,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},
@ -12,6 +13,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -21,6 +23,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": true
},
@ -30,6 +33,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -39,6 +43,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"doesExist": true
},

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 1,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"5b2de169-2785-441b-ae8c-186a1936b17d": {
@ -17,6 +18,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"8eba4902-df80-43b0-b6c2-ed8ca290984e": {
@ -32,6 +34,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"4134a00e-89e4-4896-a3d4-c3a9aa03a594": {
@ -46,6 +49,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -55,6 +59,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 1,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"agI8JhXhShasvuDgq0VxRg": {

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 1,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"5b2de169-2785-441b-ae8c-186a1936b17d": {
@ -17,6 +18,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"8eba4902-df80-43b0-b6c2-ed8ca290984e": {
@ -32,6 +34,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"4134a00e-89e4-4896-a3d4-c3a9aa03a594": {
@ -46,6 +49,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -55,6 +59,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 1,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"agI8JhXhShasvuDgq0VxRg": {

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 1,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"5b2de169-2785-441b-ae8c-186a1936b17d": {
@ -17,6 +18,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"8eba4902-df80-43b0-b6c2-ed8ca290984e": {
@ -32,6 +34,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"4134a00e-89e4-4896-a3d4-c3a9aa03a594": {
@ -46,6 +49,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -55,6 +59,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 1,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"agI8JhXhShasvuDgq0VxRg": {

View file

@ -3,6 +3,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 1,
"totalUniqueInternallyCollectedCount": 0,
"detected": null,
"byUuid": {
"5b2de169-2785-441b-ae8c-186a1936b17d": {
@ -17,6 +18,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"8eba4902-df80-43b0-b6c2-ed8ca290984e": {
@ -32,6 +34,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"4134a00e-89e4-4896-a3d4-c3a9aa03a594": {
@ -46,6 +49,7 @@
"totalUniqueInstanceCount": 0,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 0,
"detected": {
"mightExist": false
},
@ -55,6 +59,7 @@
"totalUniqueInstanceCount": 1,
"totalUniqueFullyMigratedCount": 0,
"totalUniquePartiallyMigratedCount": 0,
"totalUniqueInternallyCollectedCount": 1,
"detected": null,
"byUuid": {
"agI8JhXhShasvuDgq0VxRg": {

View file

@ -45,8 +45,8 @@ export default function ({ getService, getPageObjects }) {
dataSize: 'Total\n8.8 MB',
dataSizePrimaries: 'Primaries\n4.4 MB',
documentCount: 'Documents\n628',
totalShards: 'Total Shards\n10',
unassignedShards: 'Unassigned Shards\n0',
totalShards: 'Total shards\n10',
unassignedShards: 'Unassigned shards\n0',
health: 'Health: green',
});
});
@ -58,8 +58,8 @@ export default function ({ getService, getPageObjects }) {
dataSize: 'Total\n4.8 KB',
dataSizePrimaries: 'Primaries\n4.8 KB',
documentCount: 'Documents\n1',
totalShards: 'Total Shards\n1',
unassignedShards: 'Unassigned Shards\n0',
totalShards: 'Total shards\n1',
unassignedShards: 'Unassigned shards\n0',
health: 'Health: green',
});
});
@ -71,8 +71,8 @@ export default function ({ getService, getPageObjects }) {
dataSize: 'Total\n1.2 MB',
dataSizePrimaries: 'Primaries\n657.6 KB',
documentCount: 'Documents\n10',
totalShards: 'Total Shards\n10',
unassignedShards: 'Unassigned Shards\n1',
totalShards: 'Total shards\n10',
unassignedShards: 'Unassigned shards\n1',
health: 'Health: yellow',
});
});

View file

@ -35,8 +35,8 @@ export default function ({ getService, getPageObjects }) {
nodesCount: 'Nodes\n1',
indicesCount: 'Indices\n19',
memory: 'Memory\n267.7 MB / 676.8 MB',
totalShards: 'Total Shards\n46',
unassignedShards: 'Unassigned Shards\n23',
totalShards: 'Total shards\n46',
unassignedShards: 'Unassigned shards\n23',
documentCount: 'Documents\n4,535',
dataSize: 'Data\n8.6 MB',
health: 'Health: red',

View file

@ -39,8 +39,8 @@ export default function ({ getService, getPageObjects }) {
nodesCount: 'Nodes\n2',
indicesCount: 'Indices\n20',
memory: 'Memory\n696.6 MB / 1.3 GB',
totalShards: 'Total Shards\n79',
unassignedShards: 'Unassigned Shards\n7',
totalShards: 'Total shards\n79',
unassignedShards: 'Unassigned shards\n7',
documentCount: 'Documents\n25,758',
dataSize: 'Data\n100.0 MB',
health: 'Health: yellow',
@ -214,8 +214,8 @@ export default function ({ getService, getPageObjects }) {
nodesCount: 'Nodes\n3',
indicesCount: 'Indices\n20',
memory: 'Memory\n575.3 MB / 2.0 GB',
totalShards: 'Total Shards\n80',
unassignedShards: 'Unassigned Shards\n5',
totalShards: 'Total shards\n80',
unassignedShards: 'Unassigned shards\n5',
documentCount: 'Documents\n25,927',
dataSize: 'Data\n101.6 MB',
health: 'Health: yellow',

View file

@ -35,8 +35,8 @@ export default function ({ getService, getPageObjects }) {
nodesCount: 'Nodes\n3',
indicesCount: 'Indices\n20',
memory: 'Memory\n575.3 MB / 2.0 GB',
totalShards: 'Total Shards\n80',
unassignedShards: 'Unassigned Shards\n5',
totalShards: 'Total shards\n80',
unassignedShards: 'Unassigned shards\n5',
documentCount: 'Documents\n25,927',
dataSize: 'Data\n101.6 MB',
health: 'Health: yellow',

View file

@ -10,6 +10,7 @@ export function MonitoringNoDataProvider({ getService }) {
return new class NoData {
async enableMonitoring() {
await testSubjects.click('useInternalCollection');
await testSubjects.click('enableCollectionEnabled');
}