Skip to content

Commit

Permalink
[Monitoring] "Internal Monitoring" deprecation warning (#72020)
Browse files Browse the repository at this point in the history
* Internal Monitoring deprecation

* Fixed type

* Added if cloud logic

* Fixed i18n test

* Addressed code review feedback

* Fixed types

* Changed query

* Added delay to fix a test

* Fixed tests

* Fixed text

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
igoristic and elasticmachine committed Jul 27, 2020
1 parent 02e3fca commit 9aa5e17
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 6 deletions.
123 changes: 123 additions & 0 deletions x-pack/plugins/monitoring/public/lib/internal_monitoring_toasts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiSpacer, EuiLink } from '@elastic/eui';
import { Legacy } from '../legacy_shims';
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
import { isInSetupMode, toggleSetupMode } from './setup_mode';

export interface MonitoringIndicesTypes {
legacyIndices: number;
metricbeatIndices: number;
}

const enterSetupModeLabel = () =>
i18n.translate('xpack.monitoring.internalMonitoringToast.enterSetupMode', {
defaultMessage: 'Enter setup mode',
});

const learnMoreLabel = () =>
i18n.translate('xpack.monitoring.internalMonitoringToast.learnMoreAction', {
defaultMessage: 'Learn more',
});

const showIfLegacyOnlyIndices = () => {
const { ELASTIC_WEBSITE_URL } = Legacy.shims.docLinks;
const toast = Legacy.shims.toastNotifications.addWarning({
title: toMountPoint(
<FormattedMessage
id="xpack.monitoring.internalMonitoringToast.title"
defaultMessage="Internal Monitoring Detected"
/>
),
text: toMountPoint(
<div>
<p>
{i18n.translate('xpack.monitoring.internalMonitoringToast.description', {
defaultMessage: `It appears you are using "Legacy Collection" for Stack Monitoring.
This method of monitoring will no longer be supported in the next major release (8.0.0).
Please follow the steps in setup mode to start monitoring with Metricbeat.`,
})}
</p>
<EuiLink
onClick={() => {
Legacy.shims.toastNotifications.remove(toast);
toggleSetupMode(true);
}}
>
{enterSetupModeLabel()}
</EuiLink>

<EuiSpacer />
<EuiLink
href={`${ELASTIC_WEBSITE_URL}blog/external-collection-for-elastic-stack-monitoring-is-now-available-via-metricbeat`}
external
target="_blank"
>
{learnMoreLabel()}
</EuiLink>
</div>
),
});
};

const showIfLegacyAndMetricbeatIndices = () => {
const { ELASTIC_WEBSITE_URL } = Legacy.shims.docLinks;
const toast = Legacy.shims.toastNotifications.addWarning({
title: toMountPoint(
<FormattedMessage
id="xpack.monitoring.internalAndMetricbeatMonitoringToast.title"
defaultMessage="Partial Legacy Monitoring Detected"
/>
),
text: toMountPoint(
<div>
<p>
{i18n.translate('xpack.monitoring.internalAndMetricbeatMonitoringToast.description', {
defaultMessage: `It appears you are using both Metricbeat and "Legacy Collection" for Stack Monitoring.
In 8.0.0, you must use Metricbeat to collect monitoring data.
Please follow the steps in setup mode to migrate the rest of the monitoring to Metricbeat.`,
})}
</p>
<EuiLink
onClick={() => {
Legacy.shims.toastNotifications.remove(toast);
toggleSetupMode(true);
}}
>
{enterSetupModeLabel()}
</EuiLink>

<EuiSpacer />
<EuiLink
href={`${ELASTIC_WEBSITE_URL}blog/external-collection-for-elastic-stack-monitoring-is-now-available-via-metricbeat`}
external
target="_blank"
>
{learnMoreLabel()}
</EuiLink>
</div>
),
});
};

export const showInternalMonitoringToast = ({
legacyIndices,
metricbeatIndices,
}: MonitoringIndicesTypes) => {
if (isInSetupMode()) {
return;
}

if (legacyIndices && !metricbeatIndices) {
showIfLegacyOnlyIndices();
} else if (legacyIndices && metricbeatIndices) {
showIfLegacyAndMetricbeatIndices();
}
};
34 changes: 28 additions & 6 deletions x-pack/plugins/monitoring/public/services/clusters.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { ajaxErrorHandlersProvider } from '../lib/ajax_error_handler';
import { Legacy } from '../legacy_shims';
import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../common/constants';
import { showInternalMonitoringToast } from '../lib/internal_monitoring_toasts';
import { showSecurityToast } from '../alerts/lib/security_toasts';

function formatClusters(clusters) {
Expand All @@ -21,6 +22,7 @@ function formatCluster(cluster) {
}

let once = false;
let inTransit = false;

export function monitoringClustersProvider($injector) {
return (clusterUuid, ccs, codePaths) => {
Expand Down Expand Up @@ -63,19 +65,39 @@ export function monitoringClustersProvider($injector) {
});
}

if (!once) {
function ensureMetricbeatEnabled() {
if (Legacy.shims.isCloud) {
return Promise.resolve();
}

return $http
.get('../api/monitoring/v1/elasticsearch_settings/check/internal_monitoring')
.then(({ data }) => {
showInternalMonitoringToast({
legacyIndices: data.legacy_indices,
metricbeatIndices: data.mb_indices,
});
})
.catch((err) => {
const Private = $injector.get('Private');
const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider);
return ajaxErrorHandlers(err);
});
}

if (!once && !inTransit) {
inTransit = true;
return getClusters().then((clusters) => {
if (clusters.length) {
return ensureAlertsEnabled()
.then(({ data }) => {
Promise.all([ensureAlertsEnabled(), ensureMetricbeatEnabled()])
.then(([{ data }]) => {
showSecurityToast(data);
once = true;
return clusters;
})
.catch(() => {
// Intentionally swallow the error as this will retry the next page load
return clusters;
});
})
.finally(() => (inTransit = false));
}
return clusters;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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 { RequestHandlerContext } from 'kibana/server';
// @ts-ignore
import { getIndexPatterns } from '../../../../../lib/cluster/get_index_patterns';
// @ts-ignore
import { handleError } from '../../../../../lib/errors';
import { RouteDependencies } from '../../../../../types';

const queryBody = {
size: 0,
aggs: {
types: {
terms: {
field: '_index',
size: 10,
},
},
},
};

const checkLatestMonitoringIsLegacy = async (context: RequestHandlerContext, index: string) => {
const { client: esClient } = context.core.elasticsearch.legacy;
const result = await esClient.callAsCurrentUser('search', {
index,
body: queryBody,
});

const { aggregations } = result;
const counts = {
legacyIndicesCount: 0,
mbIndicesCount: 0,
};

if (!aggregations) {
return counts;
}

const {
types: { buckets },
} = aggregations;
counts.mbIndicesCount = buckets.filter(({ key }: { key: string }) => key.includes('-mb-')).length;

counts.legacyIndicesCount = buckets.length - counts.mbIndicesCount;
return counts;
};

export function internalMonitoringCheckRoute(server: unknown, npRoute: RouteDependencies) {
npRoute.router.get(
{
path: '/api/monitoring/v1/elasticsearch_settings/check/internal_monitoring',
validate: false,
},
async (context, _request, response) => {
try {
const typeCount = {
legacy_indices: 0,
mb_indices: 0,
};

const { esIndexPattern, kbnIndexPattern, lsIndexPattern } = getIndexPatterns(server);
const indexCounts = await Promise.all([
checkLatestMonitoringIsLegacy(context, esIndexPattern),
checkLatestMonitoringIsLegacy(context, kbnIndexPattern),
checkLatestMonitoringIsLegacy(context, lsIndexPattern),
]);

indexCounts.forEach((counts) => {
typeCount.legacy_indices += counts.legacyIndicesCount;
typeCount.mb_indices += counts.mbIndicesCount;
});

return response.ok({
body: typeCount,
});
} catch (err) {
throw handleError(err);
}
}
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

export { internalMonitoringCheckRoute } from './check/internal_monitoring';
export { clusterSettingsCheckRoute } from './check/cluster';
export { nodesSettingsCheckRoute } from './check/nodes';
export { setCollectionEnabledRoute } from './set/collection_enabled';
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/monitoring/server/routes/api/v1/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export {
ccrShardRoute,
} from './elasticsearch';
export {
internalMonitoringCheckRoute,
clusterSettingsCheckRoute,
nodesSettingsCheckRoute,
setCollectionEnabledRoute,
Expand Down
7 changes: 7 additions & 0 deletions x-pack/test/functional/apps/monitoring/time_filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import expect from '@kbn/expect';
import { getLifecycleMethods } from './_get_lifecycle_methods';

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

export default function ({ getService, getPageObjects }) {
const PageObjects = getPageObjects(['header', 'timePicker']);
const testSubjects = getService('testSubjects');
Expand Down Expand Up @@ -35,6 +37,11 @@ export default function ({ getService, getPageObjects }) {
});

it('should send another request when changing the time picker', async () => {
/**
* TODO: The value should either be removed or lowered after:
* https://github.com/elastic/kibana/issues/72997 is resolved
*/
await delay(3000);
await PageObjects.timePicker.setAbsoluteRange(
'Aug 15, 2016 @ 21:00:00.000',
'Aug 16, 2016 @ 00:00:00.000'
Expand Down

0 comments on commit 9aa5e17

Please sign in to comment.