diff --git a/x-pack/plugins/monitoring/common/types/es.ts b/x-pack/plugins/monitoring/common/types/es.ts index 2802dcaea9a79..728cd3d73a34c 100644 --- a/x-pack/plugins/monitoring/common/types/es.ts +++ b/x-pack/plugins/monitoring/common/types/es.ts @@ -278,6 +278,14 @@ export interface ElasticsearchLegacySource { }; ccr_stats?: { leader_index?: string; + follower_index?: string; + shard_id?: number; + read_exceptions?: Array<{ + exception?: { + type?: string; + }; + }>; + time_since_last_read_millis?: number; }; index_recovery?: { shards?: ElasticsearchIndexRecoveryShard[]; diff --git a/x-pack/plugins/monitoring/server/lib/apm/_get_time_of_last_event.ts b/x-pack/plugins/monitoring/server/lib/apm/_get_time_of_last_event.ts index dad34ec3861f9..68f16cf23b474 100644 --- a/x-pack/plugins/monitoring/server/lib/apm/_get_time_of_last_event.ts +++ b/x-pack/plugins/monitoring/server/lib/apm/_get_time_of_last_event.ts @@ -59,5 +59,5 @@ export async function getTimeOfLastEvent({ }; const response = await callWithRequest(req, 'search', params); - return response.hits?.hits.length ? response.hits?.hits[0]._source.timestamp : undefined; + return response.hits?.hits.length ? response.hits?.hits[0]?._source.timestamp : undefined; } diff --git a/x-pack/plugins/monitoring/server/lib/cluster/flag_supported_clusters.ts b/x-pack/plugins/monitoring/server/lib/cluster/flag_supported_clusters.ts index 6b2ebcf281a8f..248d1604ee20b 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/flag_supported_clusters.ts +++ b/x-pack/plugins/monitoring/server/lib/cluster/flag_supported_clusters.ts @@ -44,7 +44,7 @@ async function findSupportedBasicLicenseCluster( }, }, })) as ElasticsearchResponse; - const supportedClusterUuid = kibanaDataResult.hits?.hits[0]._source.cluster_uuid ?? undefined; + const supportedClusterUuid = kibanaDataResult.hits?.hits[0]?._source.cluster_uuid ?? undefined; for (const cluster of clusters) { if (cluster.cluster_uuid === supportedClusterUuid) { cluster.isSupported = true; diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_cluster_license.ts b/x-pack/plugins/monitoring/server/lib/cluster/get_cluster_license.ts index 2b55b2747ee46..9f3106f7c04a3 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_cluster_license.ts +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_cluster_license.ts @@ -33,6 +33,6 @@ export function getClusterLicense(req: LegacyRequest, esIndexPattern: string, cl const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); return callWithRequest(req, 'search', params).then((response: ElasticsearchResponse) => { - return response.hits?.hits[0]._source.license; + return response.hits?.hits[0]?._source.license; }); } diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/ccr.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/ccr.ts index 0f8099d13d44c..ec7ccd5ddb9af 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/ccr.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/ccr.ts @@ -15,8 +15,9 @@ import { ElasticsearchResponse } from '../../../common/types/es'; import { LegacyRequest } from '../../types'; export function handleResponse(response: ElasticsearchResponse) { - const isEnabled = response.hits?.hits[0]._source.stack_stats?.xpack?.ccr?.enabled ?? false; - const isAvailable = response.hits?.hits[0]._source.stack_stats?.xpack?.ccr?.available ?? false; + const isEnabled = response.hits?.hits[0]?._source.stack_stats?.xpack?.ccr?.enabled ?? undefined; + const isAvailable = + response.hits?.hits[0]?._source.stack_stats?.xpack?.ccr?.available ?? undefined; return isEnabled && isAvailable; } diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.ts index 34ae28cb1ae3c..31a58651ecd3b 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.ts @@ -42,7 +42,7 @@ export function filterOldShardActivity(startMs: number) { */ export function handleLastRecoveries(resp: ElasticsearchResponse, start: number) { if (resp.hits?.hits.length === 1) { - const data = (resp.hits?.hits[0]._source.index_recovery?.shards ?? []).filter( + const data = (resp.hits?.hits[0]?._source.index_recovery?.shards ?? []).filter( filterOldShardActivity(moment.utc(start).valueOf()) ); data.sort((a, b) => b.start_time_in_millis - a.start_time_in_millis); diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.ts index 3d6d1a792e2d6..3257c5ac36084 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.ts @@ -17,7 +17,7 @@ import { LegacyRequest } from '../../../types'; export function handleResponse(shardStats: any, indexUuid: string) { return (response: ElasticsearchResponse) => { - const indexStats = response.hits?.hits[0]._source.index_stats; + const indexStats = response.hits?.hits[0]?._source.index_stats; const primaries = indexStats?.primaries; const total = indexStats?.total; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.ts index 56b99d9fbde92..6d38cc7824ae4 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.ts @@ -29,11 +29,11 @@ export function handleResponse( const hits = resp.hits?.hits ?? []; return hits.map((hit) => { const stats = hit._source.index_stats; - const earliestStats = hit.inner_hits?.earliest?.hits?.hits[0]._source.index_stats; + const earliestStats = hit.inner_hits?.earliest?.hits?.hits[0]?._source.index_stats; const rateOptions = { hitTimestamp: hit._source.timestamp, - earliestHitTimestamp: hit.inner_hits?.earliest?.hits?.hits[0]._source.timestamp, + earliestHitTimestamp: hit.inner_hits?.earliest?.hits?.hits[0]?._source.timestamp, timeWindowMin: min, timeWindowMax: max, }; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.ts index 6c98fa1f51301..bf7471d77b616 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.ts @@ -39,15 +39,15 @@ export function handleResponse( > = nodeStatsHits.map((hit) => hit._source.elasticsearch?.node || hit._source.source_node); // using [0] value because query results are sorted desc per timestamp const node = nodes[0] || getDefaultNodeFromId(nodeUuid); const sourceStats = - response.hits?.hits[0]._source.elasticsearch?.node?.stats || - response.hits?.hits[0]._source.node_stats; + response.hits?.hits[0]?._source.elasticsearch?.node?.stats || + response.hits?.hits[0]?._source.node_stats; const clusterNode = clusterState && clusterState.nodes ? clusterState.nodes[nodeUuid] : undefined; const stats = { resolver: nodeUuid, node_ids: nodes.map((_node) => node.id || node.uuid), attributes: node.attributes, - transport_address: response.hits?.hits[0]._source.service?.address || node.transport_address, + transport_address: response.hits?.hits[0]?._source.service?.address || node.transport_address, name: node.name, type: node.type, }; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_info.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_info.ts index 8ccf04a15ed39..0f166c873dac1 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_info.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_info.ts @@ -50,7 +50,7 @@ export function mapNodesInfo( isOnline, nodeTypeLabel, nodeTypeClass, - shardCount: nodesShardCount.nodes[uuid].shardCount ?? 0, + shardCount: nodesShardCount.nodes[uuid]?.shardCount ?? 0, }, }; }, {}); diff --git a/x-pack/plugins/monitoring/server/lib/kibana/get_kibana_info.ts b/x-pack/plugins/monitoring/server/lib/kibana/get_kibana_info.ts index 28f1ffaf03597..4a0c598eec307 100644 --- a/x-pack/plugins/monitoring/server/lib/kibana/get_kibana_info.ts +++ b/x-pack/plugins/monitoring/server/lib/kibana/get_kibana_info.ts @@ -13,7 +13,7 @@ import { LegacyRequest } from '../../types'; import { ElasticsearchResponse } from '../../../common/types/es'; export function handleResponse(resp: ElasticsearchResponse) { - const source = resp.hits?.hits[0]._source.kibana_stats; + const source = resp.hits?.hits[0]?._source.kibana_stats; const kibana = source?.kibana; return merge(kibana, { availability: calculateAvailability(source?.timestamp), diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.ts b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.ts index 0dc9c251422c0..6f41455ebca6a 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.ts @@ -12,7 +12,7 @@ import { handleError } from '../../../../lib/errors/handle_error'; // @ts-ignore import { prefixIndexPattern } from '../../../../lib/ccs_utils'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../../../../common/constants'; -import { ElasticsearchResponse } from '../../../../../common/types/es'; +import { ElasticsearchResponse, ElasticsearchSource } from '../../../../../common/types/es'; import { LegacyRequest } from '../../../../types'; function getBucketScript(max: string, min: string) { @@ -218,19 +218,25 @@ export function ccrRoute(server: { return { data: [] }; } - const fullStats = response.hits?.hits.reduce((accum, hit) => { - const innerHits = hit.inner_hits?.by_shard.hits?.hits ?? []; - const innerHitsSource = innerHits.map((innerHit) => get(innerHit, '_source.ccr_stats')); - const grouped = groupBy( - innerHitsSource, - (stat) => `${stat.follower_index}:${stat.shard_id}` - ); + const fullStats: { + [key: string]: Array>; + } = + response.hits?.hits.reduce((accum, hit) => { + const innerHits = hit.inner_hits?.by_shard.hits?.hits ?? []; + const innerHitsSource = innerHits.map( + (innerHit) => + innerHit._source.ccr_stats as NonNullable + ); + const grouped = groupBy( + innerHitsSource, + (stat) => `${stat.follower_index}:${stat.shard_id}` + ); - return { - ...accum, - ...grouped, - }; - }, {}); + return { + ...accum, + ...grouped, + }; + }, {}) ?? {}; const buckets = response.aggregations.by_follower_index.buckets; const data = buckets.reduce((accum: any, bucket: any) => { @@ -261,11 +267,11 @@ export function ccrRoute(server: { stat.shards = get(bucket, 'by_shard_id.buckets').reduce( (accum2: any, shardBucket: any) => { - const fullStat = get(fullStats, [`${bucket.key}:${shardBucket.key}`, '[0]'], {}); + const fullStat = fullStats[`${bucket.key}:${shardBucket.key}`][0] ?? {}; const shardStat = { shardId: shardBucket.key, - error: fullStat.read_exceptions.length - ? fullStat.read_exceptions[0].exception.type + error: fullStat.read_exceptions?.length + ? fullStat.read_exceptions[0].exception?.type : null, opsSynced: get(shardBucket, 'ops_synced.value'), syncLagTime: fullStat.time_since_last_read_millis, diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.ts b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.ts index 78e98fb51b5e8..fd834cff29aa3 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.ts @@ -137,15 +137,15 @@ export function ccrShardRoute(server: { route: (p: any) => void; config: () => { getCcrStat(req, esIndexPattern, filters), ]); - const stat = ccrResponse.hits?.hits[0]._source.ccr_stats ?? {}; + const stat = ccrResponse.hits?.hits[0]?._source.ccr_stats ?? {}; const oldestStat = - ccrResponse.hits?.hits[0].inner_hits?.oldest.hits?.hits[0]._source.ccr_stats ?? {}; + ccrResponse.hits?.hits[0].inner_hits?.oldest.hits?.hits[0]?._source.ccr_stats ?? {}; return { metrics, stat, formattedLeader: getFormattedLeaderIndex(stat.leader_index ?? ''), - timestamp: ccrResponse.hits?.hits[0]._source.timestamp, + timestamp: ccrResponse.hits?.hits[0]?._source.timestamp, oldestStat, }; } catch (err) {