From e02f7f4542f6cf1c1f06da9e3fed7b2ace5179d8 Mon Sep 17 00:00:00 2001 From: klacabane Date: Wed, 7 Dec 2022 13:43:15 +0100 Subject: [PATCH 1/2] remove cluster_stats dependency --- .../components/cluster/listing/listing.js | 49 +++-- .../components/cluster/overview/index.js | 20 +- .../cluster/find_monitored_clusters_query.ts | 189 ++++++++++++++++++ .../lib/cluster/get_clusters_from_request.ts | 168 +++++++++++----- .../server/lib/cluster/get_index_patterns.ts | 1 + .../server/routes/api/v1/cluster/clusters.ts | 9 +- 6 files changed, 352 insertions(+), 84 deletions(-) create mode 100644 x-pack/plugins/monitoring/server/lib/cluster/find_monitored_clusters_query.ts diff --git a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js index 77a73e51ea794..6170126d16608 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js +++ b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js @@ -128,7 +128,7 @@ const getColumns = ( name: i18n.translate('xpack.monitoring.cluster.listing.nodesColumnTitle', { defaultMessage: 'Nodes', }), - field: 'elasticsearch.cluster_stats.nodes.count.total', + field: 'elasticsearch.count', 'data-test-subj': 'nodesCount', sortable: true, render: (total, cluster) => ( @@ -138,44 +138,55 @@ const getColumns = ( ), }, { - name: i18n.translate('xpack.monitoring.cluster.listing.indicesColumnTitle', { - defaultMessage: 'Indices', + name: i18n.translate('xpack.monitoring.cluster.listing.logstashColumnTitle', { + defaultMessage: 'Logstash', }), - field: 'elasticsearch.cluster_stats.indices.count', - 'data-test-subj': 'indicesCount', + field: 'logstash.count', + 'data-test-subj': 'logstashCount', sortable: true, render: (count, cluster) => ( {numeral(count).format('0,0')} ), }, { - name: i18n.translate('xpack.monitoring.cluster.listing.dataColumnTitle', { - defaultMessage: 'Data', + name: i18n.translate('xpack.monitoring.cluster.listing.kibanaColumnTitle', { + defaultMessage: 'Kibana', }), - field: 'elasticsearch.cluster_stats.indices.store.size_in_bytes', - 'data-test-subj': 'dataSize', + field: 'kibana.count', + 'data-test-subj': 'kibanaCount', sortable: true, - render: (size, cluster) => ( - {numeral(size).format('0,0[.]0 b')} + render: (count, cluster) => ( + {numeral(count).format('0,0')} ), }, { - name: i18n.translate('xpack.monitoring.cluster.listing.logstashColumnTitle', { - defaultMessage: 'Logstash', + name: i18n.translate('xpack.monitoring.cluster.listing.beatsColumnTitle', { + defaultMessage: 'Apm', }), - field: 'logstash.node_count', - 'data-test-subj': 'logstashCount', + field: 'apm.count', + 'data-test-subj': 'apmCount', sortable: true, render: (count, cluster) => ( {numeral(count).format('0,0')} ), }, { - name: i18n.translate('xpack.monitoring.cluster.listing.kibanaColumnTitle', { - defaultMessage: 'Kibana', + name: i18n.translate('xpack.monitoring.cluster.listing.beatsColumnTitle', { + defaultMessage: 'Beats', }), - field: 'kibana.count', - 'data-test-subj': 'kibanaCount', + field: 'beats.count', + 'data-test-subj': 'beatsCount', + sortable: true, + render: (count, cluster) => ( + {numeral(count).format('0,0')} + ), + }, + { + name: i18n.translate('xpack.monitoring.cluster.listing.beatsColumnTitle', { + defaultMessage: 'Enterprise search', + }), + field: 'enterprisesearch.count', + 'data-test-subj': 'enterprisesearchCount', sortable: true, render: (count, cluster) => ( {numeral(count).format('0,0')} diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/index.js b/x-pack/plugins/monitoring/public/components/cluster/overview/index.js index 05d5cb22c4c1b..b4634d9b3c783 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/index.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/index.js @@ -32,15 +32,17 @@ export function Overview(props) { {!isFromStandaloneCluster ? ( - + {props.cluster.elasticsearch.cluster_stats.nodes.count.total > 0 ? ( + + ) : null} ((acc, ruleTypeName) => { + acc[ruleTypeName] = alertStatus[ruleTypeName].map((rule: any) => ({ + ...rule, + states: rule.states.filter( + (state: any) => state.state.cluster.clusterUuid === clusterUuid + ), + })); + return acc; + }, {}), + alertsMeta: { + enabled: true, + }, + }; + } catch (err) { + req.logger.warn( + `Unable to fetch alert status because '${err.message}'. Alerts may not properly show up in the UI.` + ); + return { + list: {}, + alertsMeta: { + enabled: true, + }, + }; + } +} + +/** + * returns lightweight informations of the clusters monitored + */ +export async function findMonitoredClusters(req: LegacyRequest) { + const indexPattern = [ + '.monitoring-*', + 'metrics-elasticsearch.stack_monitoring.*', + 'metrics-kibana.stack_monitoring.*', + 'metrics-logstash.stack_monitoring.*', + 'metrics-beats.stack_monitoring.*', + ].join(','); + + const params = { + index: indexPattern, + size: 0, + ignore_unavailable: true, + body: findMonitoredClustersQuery({ + start: req.payload.timeRange.min, + end: req.payload.timeRange.max, + }), + }; + + const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); + const result = await callWithRequest(req, 'search', params); + + if (!result.aggregations) { + return []; + } + + const { buckets } = result.aggregations.cluster_uuid; + const clusterUuids = buckets.map((bucket: any) => bucket.key); + + const rulesClient = req.getRulesClient(); + const alertStatus = await fetchStatus(rulesClient, undefined, clusterUuids); + + return result.aggregations.cluster_uuid.buckets.map((bucket: any) => { + const { + key: cluster_uuid, + elasticsearch, + kibana, + beats, + logstash, + apm, + enterprisesearch, + } = bucket; + + const alerts = getAlertState(req, alertStatus, cluster_uuid); + return { + isSupported: true, + cluster_uuid, + cluster_name: + elasticsearch.latest_doc.hits.hits[0]?._source.elasticsearch.cluster?.name ?? cluster_uuid, + license: + elasticsearch.latest_doc.hits.hits[0]?._source.elasticsearch.cluster?.stats?.license ?? {}, + alerts, + elasticsearch: { + count: + elasticsearch.latest_doc.hits.hits[0]?._source.elasticsearch.cluster?.stats?.nodes + .count ?? 0, + }, + kibana: { count: kibana.instance_count.value }, + apm: { count: apm.instance_count.value }, + beats: { count: beats.instance_count.value }, + logstash: { count: logstash.instance_count.value }, + enterprisesearch: { count: enterprisesearch.instance_count.value }, + }; + }); +} + /** * Get all clusters or the cluster associated with {@code clusterUuid} when it is defined. */ @@ -71,6 +181,9 @@ export async function getClustersFromRequest( } else { // get clusters with stats and cluster state clusters = await getClustersStats(req, clusterUuid, CCS_REMOTE_PATTERN); + if (!clusters.length) { + clusters.push({ cluster_uuid: clusterUuid!, license: {}, isSupported: true }); + } } if (!clusterUuid && !isStandaloneCluster) { @@ -81,19 +194,6 @@ export async function getClustersFromRequest( // TODO: this handling logic should be two different functions if (clusterUuid) { - // if is defined, get specific cluster (no need for license checking) - if (!clusters || clusters.length === 0) { - throw notFound( - i18n.translate('xpack.monitoring.requestedClusters.uuidNotFoundErrorMessage', { - defaultMessage: - 'Unable to find the cluster in the selected time range. UUID: {clusterUuid}', - values: { - clusterUuid, - }, - }) - ); - } - const cluster = clusters[0]; // add ml jobs and alerts data @@ -134,43 +234,11 @@ export async function getClustersFromRequest( ); for (const cluster of clusters) { - if (!rulesClient) { - cluster.alerts = { - list: {}, - alertsMeta: { - enabled: false, - }, - }; - } else { - try { - cluster.alerts = { - list: Object.keys(alertStatus).reduce((acc, ruleTypeName) => { - acc[ruleTypeName] = alertStatus[ruleTypeName].map((rule) => ({ - ...rule, - states: rule.states.filter( - (state) => - state.state.cluster.clusterUuid === - get(cluster, 'elasticsearch.cluster.id', cluster.cluster_uuid) - ), - })); - return acc; - }, {}), - alertsMeta: { - enabled: true, - }, - }; - } catch (err) { - req.logger.warn( - `Unable to fetch alert status because '${err.message}'. Alerts may not properly show up in the UI.` - ); - cluster.alerts = { - list: {}, - alertsMeta: { - enabled: true, - }, - }; - } - } + cluster.alerts = getAlertState( + req, + alertStatus, + get(cluster, 'elasticsearch.cluster.id', cluster.cluster_uuid) + ); } } } diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_index_patterns.ts b/x-pack/plugins/monitoring/server/lib/cluster/get_index_patterns.ts index 03313f21fbfa2..8d31cea037864 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_index_patterns.ts +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_index_patterns.ts @@ -126,6 +126,7 @@ const getDataset = (moduleType: INDEX_PATTERN_TYPES) => (dataset: string) => export const getElasticsearchDataset = getDataset('elasticsearch'); export const getKibanaDataset = getDataset('kibana'); export const getLogstashDataset = getDataset('logstash'); +export const getBeatDataset = getDataset('beats'); function buildDatasetPattern( moduleType?: INDEX_PATTERN_TYPES, diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts index 1e5883360d09b..bcb9a1a069997 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts @@ -7,9 +7,8 @@ import { postClustersRequestPayloadRT, - postClustersResponsePayloadRT, } from '../../../../../common/http_api/cluster'; -import { getClustersFromRequest } from '../../../../lib/cluster/get_clusters_from_request'; +import { findMonitoredClusters } from '../../../../lib/cluster/get_clusters_from_request'; import { createValidationFunction } from '../../../../lib/create_route_validation_function'; import { verifyMonitoringAuth } from '../../../../lib/elasticsearch/verify_monitoring_auth'; import { handleError } from '../../../../lib/errors'; @@ -37,10 +36,8 @@ export function clustersRoute(server: MonitoringCore) { try { await verifyMonitoringAuth(req); - const clusters = await getClustersFromRequest(req, { - codePaths: req.payload.codePaths, - }); - return postClustersResponsePayloadRT.encode(clusters); + const clusters = await findMonitoredClusters(req); + return clusters; } catch (err) { throw handleError(err, req); } From 1d31605e8be2d37b3d7877a3a41c4bc5c86b5507 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 7 Dec 2022 13:59:35 +0000 Subject: [PATCH 2/2] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../lib/cluster/find_monitored_clusters_query.ts | 13 +++++++++---- .../server/lib/cluster/get_clusters_from_request.ts | 2 -- .../server/routes/api/v1/cluster/clusters.ts | 4 +--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/monitoring/server/lib/cluster/find_monitored_clusters_query.ts b/x-pack/plugins/monitoring/server/lib/cluster/find_monitored_clusters_query.ts index 186126686a99e..6668316ed1e4c 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/find_monitored_clusters_query.ts +++ b/x-pack/plugins/monitoring/server/lib/cluster/find_monitored_clusters_query.ts @@ -1,3 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../../common/constants'; import { getBeatDataset, @@ -166,9 +173,7 @@ export function findMonitoredClustersQuery(options: { start?: number; end?: numb }, { bool: { - should: [ - { term: { 'metricset.name': 'stats' } }, - ], + should: [{ term: { 'metricset.name': 'stats' } }], }, }, ], @@ -181,7 +186,7 @@ export function findMonitoredClustersQuery(options: { start?: number; end?: numb }, }, }, - } + }, }, }, }, diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts index 086ee27019c4c..0dcbc1557921f 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts @@ -5,10 +5,8 @@ * 2.0. */ -import { notFound } from '@hapi/boom'; import { get, omit } from 'lodash'; import { set } from '@kbn/safer-lodash-set'; -import { i18n } from '@kbn/i18n'; import { getClustersStats } from './get_clusters_stats'; import { flagSupportedClusters } from './flag_supported_clusters'; import { getMlJobsForCluster } from '../elasticsearch'; diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts index bcb9a1a069997..bc6d366d16046 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts @@ -5,9 +5,7 @@ * 2.0. */ -import { - postClustersRequestPayloadRT, -} from '../../../../../common/http_api/cluster'; +import { postClustersRequestPayloadRT } from '../../../../../common/http_api/cluster'; import { findMonitoredClusters } from '../../../../lib/cluster/get_clusters_from_request'; import { createValidationFunction } from '../../../../lib/create_route_validation_function'; import { verifyMonitoringAuth } from '../../../../lib/elasticsearch/verify_monitoring_auth';