mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[Monitoring] "Internal Monitoring" deprecation warning (#72020)
* 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>
This commit is contained in:
parent
02e3fca772
commit
9aa5e1772d
6 changed files with 245 additions and 6 deletions
|
@ -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();
|
||||||
|
}
|
||||||
|
};
|
|
@ -7,6 +7,7 @@
|
||||||
import { ajaxErrorHandlersProvider } from '../lib/ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from '../lib/ajax_error_handler';
|
||||||
import { Legacy } from '../legacy_shims';
|
import { Legacy } from '../legacy_shims';
|
||||||
import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../common/constants';
|
import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../common/constants';
|
||||||
|
import { showInternalMonitoringToast } from '../lib/internal_monitoring_toasts';
|
||||||
import { showSecurityToast } from '../alerts/lib/security_toasts';
|
import { showSecurityToast } from '../alerts/lib/security_toasts';
|
||||||
|
|
||||||
function formatClusters(clusters) {
|
function formatClusters(clusters) {
|
||||||
|
@ -21,6 +22,7 @@ function formatCluster(cluster) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let once = false;
|
let once = false;
|
||||||
|
let inTransit = false;
|
||||||
|
|
||||||
export function monitoringClustersProvider($injector) {
|
export function monitoringClustersProvider($injector) {
|
||||||
return (clusterUuid, ccs, codePaths) => {
|
return (clusterUuid, ccs, codePaths) => {
|
||||||
|
@ -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) => {
|
return getClusters().then((clusters) => {
|
||||||
if (clusters.length) {
|
if (clusters.length) {
|
||||||
return ensureAlertsEnabled()
|
Promise.all([ensureAlertsEnabled(), ensureMetricbeatEnabled()])
|
||||||
.then(({ data }) => {
|
.then(([{ data }]) => {
|
||||||
showSecurityToast(data);
|
showSecurityToast(data);
|
||||||
once = true;
|
once = true;
|
||||||
return clusters;
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
// Intentionally swallow the error as this will retry the next page load
|
// Intentionally swallow the error as this will retry the next page load
|
||||||
return clusters;
|
})
|
||||||
});
|
.finally(() => (inTransit = false));
|
||||||
}
|
}
|
||||||
return clusters;
|
return clusters;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* 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 { clusterSettingsCheckRoute } from './check/cluster';
|
||||||
export { nodesSettingsCheckRoute } from './check/nodes';
|
export { nodesSettingsCheckRoute } from './check/nodes';
|
||||||
export { setCollectionEnabledRoute } from './set/collection_enabled';
|
export { setCollectionEnabledRoute } from './set/collection_enabled';
|
||||||
|
|
|
@ -20,6 +20,7 @@ export {
|
||||||
ccrShardRoute,
|
ccrShardRoute,
|
||||||
} from './elasticsearch';
|
} from './elasticsearch';
|
||||||
export {
|
export {
|
||||||
|
internalMonitoringCheckRoute,
|
||||||
clusterSettingsCheckRoute,
|
clusterSettingsCheckRoute,
|
||||||
nodesSettingsCheckRoute,
|
nodesSettingsCheckRoute,
|
||||||
setCollectionEnabledRoute,
|
setCollectionEnabledRoute,
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
import expect from '@kbn/expect';
|
import expect from '@kbn/expect';
|
||||||
import { getLifecycleMethods } from './_get_lifecycle_methods';
|
import { getLifecycleMethods } from './_get_lifecycle_methods';
|
||||||
|
|
||||||
|
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
export default function ({ getService, getPageObjects }) {
|
export default function ({ getService, getPageObjects }) {
|
||||||
const PageObjects = getPageObjects(['header', 'timePicker']);
|
const PageObjects = getPageObjects(['header', 'timePicker']);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
|
@ -35,6 +37,11 @@ export default function ({ getService, getPageObjects }) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send another request when changing the time picker', async () => {
|
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(
|
await PageObjects.timePicker.setAbsoluteRange(
|
||||||
'Aug 15, 2016 @ 21:00:00.000',
|
'Aug 15, 2016 @ 21:00:00.000',
|
||||||
'Aug 16, 2016 @ 00:00:00.000'
|
'Aug 16, 2016 @ 00:00:00.000'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue