Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Monitoring] Convert Elasticsearch-related server files that read from _source to typescript #88212

Merged
merged 8 commits into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 205 additions & 1 deletion x-pack/plugins/monitoring/common/types/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@
* you may not use this file except in compliance with the Elastic License.
*/

export interface ElasticsearchResponse {
hits?: {
hits: ElasticsearchResponseHit[];
total: {
value: number;
};
};
aggregations?: any;
}

export interface ElasticsearchResponseHit {
_index: string;
_source: ElasticsearchSource;
inner_hits?: {
[field: string]: {
hits?: {
hits: ElasticsearchResponseHit[];
total: {
value: number;
};
};
};
};
}

export interface ElasticsearchSourceKibanaStats {
timestamp?: string;
kibana?: {
Expand Down Expand Up @@ -34,9 +59,94 @@ export interface ElasticsearchSourceLogstashPipelineVertex {
};
}

export interface ElasticsearchSource {
export interface ElasticsearchNodeStats {
indices?: {
docs?: {
count?: number;
};
store?: {
size_in_bytes?: number;
size?: {
bytes?: number;
};
};
};
fs?: {
total?: {
available_in_bytes?: number;
total_in_bytes?: number;
};
summary?: {
available?: {
bytes?: number;
};
total?: {
bytes?: number;
};
};
};
jvm?: {
mem?: {
heap_used_percent?: number;
heap?: {
used?: {
pct?: number;
};
};
};
};
}

export interface ElasticsearchLegacySource {
timestamp: string;
cluster_uuid: string;
cluster_stats?: {
nodes?: {
count?: {
total?: number;
};
jvm?: {
max_uptime_in_millis?: number;
mem?: {
heap_used_in_bytes?: number;
heap_max_in_bytes?: number;
};
};
versions?: string[];
};
indices?: {
count?: number;
docs?: {
count?: number;
};
shards?: {
total?: number;
};
store?: {
size_in_bytes?: number;
};
};
};
cluster_state?: {
status?: string;
nodes?: {
[nodeUuid: string]: {};
};
master_node?: boolean;
};
source_node?: {
id?: string;
uuid?: string;
attributes?: {};
transport_address?: string;
name?: string;
type?: string;
};
kibana_stats?: ElasticsearchSourceKibanaStats;
license?: {
status?: string;
type?: string;
};
logstash_state?: {
pipeline?: {
representation?: {
Expand Down Expand Up @@ -108,4 +218,98 @@ export interface ElasticsearchSource {
};
};
};
stack_stats?: {
xpack?: {
ccr?: {
enabled?: boolean;
available?: boolean;
};
};
};
job_stats?: {
job_id?: number;
state?: string;
data_counts?: {
processed_record_count?: number;
};
model_size_stats?: {
model_bytes?: number;
};
forecasts_stats?: {
total?: number;
};
node?: {
id?: number;
name?: string;
};
};
index_stats?: {
index?: string;
primaries?: {
docs?: {
count?: number;
};
store?: {
size_in_bytes?: number;
};
indexing?: {
index_total?: number;
};
};
total?: {
store?: {
size_in_bytes?: number;
};
search?: {
query_total?: number;
};
};
};
node_stats?: ElasticsearchNodeStats;
service?: {
address?: string;
};
shard?: {
index?: string;
shard?: string;
primary?: boolean;
relocating_node?: string;
node?: string;
};
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[];
};
}

export interface ElasticsearchIndexRecoveryShard {
start_time_in_millis: number;
stop_time_in_millis: number;
}

export interface ElasticsearchMetricbeatNode {
stats?: ElasticsearchNodeStats;
}

export interface ElasticsearchMetricbeatSource {
elasticsearch?: {
node?: ElasticsearchLegacySource['source_node'] & ElasticsearchMetricbeatNode;
};
}

export type ElasticsearchSource = ElasticsearchLegacySource & ElasticsearchMetricbeatSource;

export interface ElasticsearchModifiedSource extends ElasticsearchSource {
ccs?: string;
isSupported?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import { createApmQuery } from './create_apm_query';
// @ts-ignore
import { ApmClusterMetric } from '../metrics';
import { LegacyRequest, ElasticsearchResponse } from '../../types';
import { LegacyRequest } from '../../types';
import { ElasticsearchResponse } from '../../../common/types/es';

export async function getTimeOfLastEvent({
req,
Expand Down Expand Up @@ -58,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;
}
3 changes: 2 additions & 1 deletion x-pack/plugins/monitoring/server/lib/apm/get_apm_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { getDiffCalculation } from '../beats/_beats_stats';
// @ts-ignore
import { ApmMetric } from '../metrics';
import { getTimeOfLastEvent } from './_get_time_of_last_event';
import { LegacyRequest, ElasticsearchResponse } from '../../types';
import { LegacyRequest } from '../../types';
import { ElasticsearchResponse } from '../../../common/types/es';

export function handleResponse(response: ElasticsearchResponse, apmUuid: string) {
if (!response.hits || response.hits.hits.length === 0) {
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/monitoring/server/lib/apm/get_apms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { createApmQuery } from './create_apm_query';
import { calculateRate } from '../calculate_rate';
// @ts-ignore
import { getDiffCalculation } from './_apm_stats';
import { LegacyRequest, ElasticsearchResponse, ElasticsearchResponseHit } from '../../types';
import { LegacyRequest } from '../../types';
import { ElasticsearchResponse, ElasticsearchResponseHit } from '../../../common/types/es';

export function handleResponse(response: ElasticsearchResponse, start: number, end: number) {
const initial = { ids: new Set(), beats: [] };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
*/

import { upperFirst } from 'lodash';
import { LegacyRequest, ElasticsearchResponse } from '../../types';
import { LegacyRequest } from '../../types';
import { ElasticsearchResponse } from '../../../common/types/es';
// @ts-ignore
import { checkParam } from '../error_missing_required';
// @ts-ignore
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/monitoring/server/lib/beats/get_beats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { createBeatsQuery } from './create_beats_query';
import { calculateRate } from '../calculate_rate';
// @ts-ignore
import { getDiffCalculation } from './_beats_stats';
import { ElasticsearchResponse, LegacyRequest } from '../../types';
import { LegacyRequest } from '../../types';
import { ElasticsearchResponse } from '../../../common/types/es';

interface Beat {
uuid: string | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { set } from '@elastic/safer-lodash-set';
import { get, find } from 'lodash';
// @ts-ignore
import { checkParam } from '../error_missing_required';
import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../../common/constants';
import { ElasticsearchResponse, ElasticsearchModifiedSource } from '../../../common/types/es';
import { LegacyRequest } from '../../types';

async function findSupportedBasicLicenseCluster(
req,
clusters,
kbnIndexPattern,
kibanaUuid,
serverLog
req: LegacyRequest,
clusters: ElasticsearchModifiedSource[],
kbnIndexPattern: string,
kibanaUuid: string,
serverLog: (message: string) => void
) {
checkParam(kbnIndexPattern, 'kbnIndexPattern in cluster/findSupportedBasicLicenseCluster');

Expand All @@ -25,7 +26,7 @@ async function findSupportedBasicLicenseCluster(
const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
const gte = req.payload.timeRange.min;
const lte = req.payload.timeRange.max;
const kibanaDataResult = await callWithRequest(req, 'search', {
const kibanaDataResult: ElasticsearchResponse = (await callWithRequest(req, 'search', {
index: kbnIndexPattern,
size: 1,
ignoreUnavailable: true,
Expand All @@ -42,11 +43,13 @@ async function findSupportedBasicLicenseCluster(
},
},
},
});
const supportedClusterUuid = get(kibanaDataResult, 'hits.hits[0]._source.cluster_uuid');
const supportedCluster = find(clusters, { cluster_uuid: supportedClusterUuid });
// only this basic cluster is supported
set(supportedCluster, 'isSupported', true);
})) as ElasticsearchResponse;
const supportedClusterUuid = kibanaDataResult.hits?.hits[0]?._source.cluster_uuid ?? undefined;
for (const cluster of clusters) {
if (cluster.cluster_uuid === supportedClusterUuid) {
cluster.isSupported = true;
}
}

serverLog(
`Found basic license admin cluster UUID for Monitoring UI support: ${supportedClusterUuid}.`
Expand All @@ -69,12 +72,12 @@ async function findSupportedBasicLicenseCluster(
* Non-Basic license clusters and any cluster in a single-cluster environment
* are also flagged as supported in this method.
*/
export function flagSupportedClusters(req, kbnIndexPattern) {
export function flagSupportedClusters(req: LegacyRequest, kbnIndexPattern: string) {
checkParam(kbnIndexPattern, 'kbnIndexPattern in cluster/flagSupportedClusters');

const config = req.server.config();
const serverLog = (msg) => req.getLogger('supported-clusters').debug(msg);
const flagAllSupported = (clusters) => {
const serverLog = (message: string) => req.getLogger('supported-clusters').debug(message);
const flagAllSupported = (clusters: ElasticsearchModifiedSource[]) => {
clusters.forEach((cluster) => {
if (cluster.license) {
cluster.isSupported = true;
Expand All @@ -83,7 +86,7 @@ export function flagSupportedClusters(req, kbnIndexPattern) {
return clusters;
};

return async function (clusters) {
return async function (clusters: ElasticsearchModifiedSource[]) {
// Standalone clusters are automatically supported in the UI so ignore those for
// our calculations here
let linkedClusterCount = 0;
Expand All @@ -110,7 +113,7 @@ export function flagSupportedClusters(req, kbnIndexPattern) {

// if all linked are basic licenses
if (linkedClusterCount === basicLicenseCount) {
const kibanaUuid = config.get('server.uuid');
const kibanaUuid = config.get('server.uuid') as string;
return await findSupportedBasicLicenseCluster(
req,
clusters,
Expand Down
Loading