From 20654388a40c82dd9ae9cccf82c24ff4dffc4749 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 2 Feb 2021 20:23:56 -0500 Subject: [PATCH] [Fleet] Fix performance issue in agent status endpoint (#90066) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet/server/services/agents/crud_so.ts | 40 +++++++++++++------ .../fleet/server/services/agents/status.ts | 24 ++++++++--- .../fleet/server/types/rest_spec/common.ts | 7 +++- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agents/crud_so.ts b/x-pack/plugins/fleet/server/services/agents/crud_so.ts index eb8f389741a6..7111a2413914 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud_so.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud_so.ts @@ -12,18 +12,35 @@ import { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { escapeSearchQueryPhrase, normalizeKuery, findAllSOs } from '../saved_object'; import { savedObjectToAgent } from './saved_objects'; import { appContextService } from '../../services'; +import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server'; const ACTIVE_AGENT_CONDITION = `${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`; const INACTIVE_AGENT_CONDITION = `NOT (${ACTIVE_AGENT_CONDITION})`; -function _joinFilters(filters: string[], operator = 'AND') { - return filters.reduce((acc: string | undefined, filter) => { - if (acc) { - return `${acc} ${operator} (${filter})`; - } +function _joinFilters(filters: Array) { + return filters + .filter((filter) => filter !== undefined) + .reduce((acc: KueryNode | undefined, kuery: string | KueryNode | undefined): + | KueryNode + | undefined => { + if (kuery === undefined) { + return acc; + } + const kueryNode: KueryNode = + typeof kuery === 'string' + ? esKuery.fromKueryExpression(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery)) + : kuery; - return `(${filter})`; - }, undefined); + if (!acc) { + return kueryNode; + } + + return { + type: 'function', + function: 'and', + arguments: [acc, kueryNode], + }; + }, undefined as KueryNode | undefined); } export async function listAgents( @@ -46,19 +63,18 @@ export async function listAgents( showInactive = false, showUpgradeable, } = options; - const filters = []; + const filters: Array = []; if (kuery && kuery !== '') { - filters.push(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery)); + filters.push(kuery); } if (showInactive === false) { filters.push(ACTIVE_AGENT_CONDITION); } - let { saved_objects: agentSOs, total } = await soClient.find({ type: AGENT_SAVED_OBJECT_TYPE, - filter: _joinFilters(filters), + filter: _joinFilters(filters) || '', sortField, sortOrder, page, @@ -94,7 +110,7 @@ export async function listAllAgents( const filters = []; if (kuery && kuery !== '') { - filters.push(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery)); + filters.push(kuery); } if (showInactive === false) { diff --git a/x-pack/plugins/fleet/server/services/agents/status.ts b/x-pack/plugins/fleet/server/services/agents/status.ts index ba8f8fc36385..726d188f723d 100644 --- a/x-pack/plugins/fleet/server/services/agents/status.ts +++ b/x-pack/plugins/fleet/server/services/agents/status.ts @@ -11,6 +11,8 @@ import { AGENT_EVENT_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE } from '../../co import { AgentStatus } from '../../types'; import { AgentStatusKueryHelper } from '../../../common/services'; +import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server'; +import { normalizeKuery } from '../saved_object'; export async function getAgentStatusById( soClient: SavedObjectsClientContract, @@ -26,13 +28,24 @@ export const getAgentStatus = AgentStatusKueryHelper.getAgentStatus; function joinKuerys(...kuerys: Array) { return kuerys .filter((kuery) => kuery !== undefined) - .reduce((acc, kuery) => { - if (acc === '') { - return `(${kuery})`; + .reduce((acc: KueryNode | undefined, kuery: string | undefined): KueryNode | undefined => { + if (kuery === undefined) { + return acc; + } + const normalizedKuery: KueryNode = esKuery.fromKueryExpression( + normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery || '') + ); + + if (!acc) { + return normalizedKuery; } - return `${acc} and (${kuery})`; - }, ''); + return { + type: 'function', + function: 'and', + arguments: [acc, normalizedKuery], + }; + }, undefined as KueryNode | undefined); } export async function getAgentStatusForAgentPolicy( @@ -58,6 +71,7 @@ export async function getAgentStatusForAgentPolicy( ...[ kuery, filterKuery, + `${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`, agentPolicyId ? `${AGENT_SAVED_OBJECT_TYPE}.policy_id:"${agentPolicyId}"` : undefined, ] ), diff --git a/x-pack/plugins/fleet/server/types/rest_spec/common.ts b/x-pack/plugins/fleet/server/types/rest_spec/common.ts index cdb23da5b6b1..88d60116672d 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/common.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/common.ts @@ -11,7 +11,12 @@ export const ListWithKuerySchema = schema.object({ sortField: schema.maybe(schema.string()), sortOrder: schema.maybe(schema.oneOf([schema.literal('desc'), schema.literal('asc')])), showUpgradeable: schema.maybe(schema.boolean()), - kuery: schema.maybe(schema.string()), + kuery: schema.maybe( + schema.oneOf([ + schema.string(), + schema.any(), // KueryNode + ]) + ), }); export type ListWithKuery = TypeOf;