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 d4bc3e3529610..e705802676900 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 +179,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 +192,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 +232,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/routes/api/v1/cluster/clusters.ts b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.ts
index 1e5883360d09b..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,11 +5,8 @@
* 2.0.
*/
-import {
- postClustersRequestPayloadRT,
- postClustersResponsePayloadRT,
-} from '../../../../../common/http_api/cluster';
-import { getClustersFromRequest } from '../../../../lib/cluster/get_clusters_from_request';
+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';
import { handleError } from '../../../../lib/errors';
@@ -37,10 +34,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);
}