kibana/x-pack/plugins/monitoring/server/telemetry_collection/get_all_stats.ts

120 lines
4.3 KiB
TypeScript

/*
* 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 { set } from '@elastic/safer-lodash-set';
import { get, merge } from 'lodash';
import { StatsGetter } from 'src/plugins/telemetry_collection_manager/server';
import { LOGSTASH_SYSTEM_ID, KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID } from '../../common/constants';
import { getElasticsearchStats, ESClusterStats } from './get_es_stats';
import { getKibanaStats, KibanaStats } from './get_kibana_stats';
import { getBeatsStats } from './get_beats_stats';
import { getHighLevelStats } from './get_high_level_stats';
type PromiseReturnType<T extends (...args: any[]) => any> = ReturnType<T> extends Promise<infer R>
? R
: T;
export interface CustomContext {
maxBucketSize: number;
}
/**
* Get statistics for all products joined by Elasticsearch cluster.
* Returns the array of clusters joined with the Kibana and Logstash instances.
*
*/
export const getAllStats: StatsGetter<CustomContext> = async (
clustersDetails,
{ callCluster, start, end },
{ maxBucketSize }
) => {
const clusterUuids = clustersDetails.map((clusterDetails) => clusterDetails.clusterUuid);
const [esClusters, kibana, logstash, beats] = await Promise.all([
getElasticsearchStats(callCluster, clusterUuids, maxBucketSize), // cluster_stats, stack_stats.xpack, cluster_name/uuid, license, version
getKibanaStats(callCluster, clusterUuids, start, end, maxBucketSize), // stack_stats.kibana
getHighLevelStats(callCluster, clusterUuids, start, end, LOGSTASH_SYSTEM_ID, maxBucketSize), // stack_stats.logstash
getBeatsStats(callCluster, clusterUuids, start, end), // stack_stats.beats
]);
return handleAllStats(esClusters, { kibana, logstash, beats });
};
/**
* Combine the statistics from the stack to create "cluster" stats that associate all products together based on the cluster
* that is attached.
*
* @param {Array} clusters The Elasticsearch clusters
* @param {Object} kibana The Kibana instances keyed by Cluster UUID
* @param {Object} logstash The Logstash nodes keyed by Cluster UUID
*
* Returns the clusters joined with the Kibana and Logstash instances under each cluster's {@code stack_stats}.
*/
export function handleAllStats(
clusters: ESClusterStats[],
{
kibana,
logstash,
beats,
}: {
kibana: KibanaStats;
logstash: PromiseReturnType<typeof getHighLevelStats>;
beats: PromiseReturnType<typeof getBeatsStats>;
}
) {
return clusters.map((cluster) => {
const stats = {
...cluster,
stack_stats: {
...cluster.stack_stats,
// if they are using Kibana or Logstash, then add it to the cluster details under cluster.stack_stats
...getStackStats(cluster.cluster_uuid, kibana, KIBANA_SYSTEM_ID),
...getStackStats(cluster.cluster_uuid, logstash, LOGSTASH_SYSTEM_ID),
...getStackStats(cluster.cluster_uuid, beats, BEATS_SYSTEM_ID),
},
};
mergeXPackStats(stats, kibana, 'graph_workspace', 'graph'); // copy graph_workspace info out of kibana, merge it into stack_stats.xpack.graph
return stats;
});
}
export function getStackStats<T extends { [clusterUuid: string]: K }, K>(
clusterUuid: string,
allProductStats: T,
product: string
) {
const productStats = allProductStats[clusterUuid];
// Don't add it if they're not using (or configured to report stats) this product for this cluster
return productStats ? { [product]: productStats } : {};
}
export function mergeXPackStats<T extends { [clusterUuid: string]: unknown }>(
cluster: ESClusterStats & { stack_stats?: { xpack?: { [product: string]: unknown } } },
allProductStats: T,
path: string,
product: string
) {
const productStats = get(allProductStats, cluster.cluster_uuid + '.' + path);
if (productStats || productStats === 0) {
if (!cluster.stack_stats) {
cluster.stack_stats = {};
}
if (!cluster.stack_stats.xpack) {
cluster.stack_stats.xpack = {};
}
const mergeStats = {};
set(mergeStats, path, productStats);
// merge existing data with new stats
cluster.stack_stats.xpack[product] = cluster.stack_stats.xpack[product] || {};
merge(cluster.stack_stats.xpack[product], mergeStats);
}
}