[Fleet] Fix performance issue in agent status endpoint (#90066)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nicolas Chaulet 2021-02-02 20:23:56 -05:00 committed by GitHub
parent 75d9e0a071
commit 20654388a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 18 deletions

View file

@ -12,18 +12,35 @@ import { AgentSOAttributes, Agent, ListWithKuery } from '../../types';
import { escapeSearchQueryPhrase, normalizeKuery, findAllSOs } from '../saved_object'; import { escapeSearchQueryPhrase, normalizeKuery, findAllSOs } from '../saved_object';
import { savedObjectToAgent } from './saved_objects'; import { savedObjectToAgent } from './saved_objects';
import { appContextService } from '../../services'; import { appContextService } from '../../services';
import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server';
const ACTIVE_AGENT_CONDITION = `${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`; const ACTIVE_AGENT_CONDITION = `${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`;
const INACTIVE_AGENT_CONDITION = `NOT (${ACTIVE_AGENT_CONDITION})`; const INACTIVE_AGENT_CONDITION = `NOT (${ACTIVE_AGENT_CONDITION})`;
function _joinFilters(filters: string[], operator = 'AND') { function _joinFilters(filters: Array<string | undefined | KueryNode>) {
return filters.reduce((acc: string | undefined, filter) => { return filters
if (acc) { .filter((filter) => filter !== undefined)
return `${acc} ${operator} (${filter})`; .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})`; if (!acc) {
}, undefined); return kueryNode;
}
return {
type: 'function',
function: 'and',
arguments: [acc, kueryNode],
};
}, undefined as KueryNode | undefined);
} }
export async function listAgents( export async function listAgents(
@ -46,19 +63,18 @@ export async function listAgents(
showInactive = false, showInactive = false,
showUpgradeable, showUpgradeable,
} = options; } = options;
const filters = []; const filters: Array<string | KueryNode | undefined> = [];
if (kuery && kuery !== '') { if (kuery && kuery !== '') {
filters.push(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery)); filters.push(kuery);
} }
if (showInactive === false) { if (showInactive === false) {
filters.push(ACTIVE_AGENT_CONDITION); filters.push(ACTIVE_AGENT_CONDITION);
} }
let { saved_objects: agentSOs, total } = await soClient.find<AgentSOAttributes>({ let { saved_objects: agentSOs, total } = await soClient.find<AgentSOAttributes>({
type: AGENT_SAVED_OBJECT_TYPE, type: AGENT_SAVED_OBJECT_TYPE,
filter: _joinFilters(filters), filter: _joinFilters(filters) || '',
sortField, sortField,
sortOrder, sortOrder,
page, page,
@ -94,7 +110,7 @@ export async function listAllAgents(
const filters = []; const filters = [];
if (kuery && kuery !== '') { if (kuery && kuery !== '') {
filters.push(normalizeKuery(AGENT_SAVED_OBJECT_TYPE, kuery)); filters.push(kuery);
} }
if (showInactive === false) { if (showInactive === false) {

View file

@ -11,6 +11,8 @@ import { AGENT_EVENT_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE } from '../../co
import { AgentStatus } from '../../types'; import { AgentStatus } from '../../types';
import { AgentStatusKueryHelper } from '../../../common/services'; import { AgentStatusKueryHelper } from '../../../common/services';
import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server';
import { normalizeKuery } from '../saved_object';
export async function getAgentStatusById( export async function getAgentStatusById(
soClient: SavedObjectsClientContract, soClient: SavedObjectsClientContract,
@ -26,13 +28,24 @@ export const getAgentStatus = AgentStatusKueryHelper.getAgentStatus;
function joinKuerys(...kuerys: Array<string | undefined>) { function joinKuerys(...kuerys: Array<string | undefined>) {
return kuerys return kuerys
.filter((kuery) => kuery !== undefined) .filter((kuery) => kuery !== undefined)
.reduce((acc, kuery) => { .reduce((acc: KueryNode | undefined, kuery: string | undefined): KueryNode | undefined => {
if (acc === '') { if (kuery === undefined) {
return `(${kuery})`; 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( export async function getAgentStatusForAgentPolicy(
@ -58,6 +71,7 @@ export async function getAgentStatusForAgentPolicy(
...[ ...[
kuery, kuery,
filterKuery, filterKuery,
`${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`,
agentPolicyId ? `${AGENT_SAVED_OBJECT_TYPE}.policy_id:"${agentPolicyId}"` : undefined, agentPolicyId ? `${AGENT_SAVED_OBJECT_TYPE}.policy_id:"${agentPolicyId}"` : undefined,
] ]
), ),

View file

@ -11,7 +11,12 @@ export const ListWithKuerySchema = schema.object({
sortField: schema.maybe(schema.string()), sortField: schema.maybe(schema.string()),
sortOrder: schema.maybe(schema.oneOf([schema.literal('desc'), schema.literal('asc')])), sortOrder: schema.maybe(schema.oneOf([schema.literal('desc'), schema.literal('asc')])),
showUpgradeable: schema.maybe(schema.boolean()), showUpgradeable: schema.maybe(schema.boolean()),
kuery: schema.maybe(schema.string()), kuery: schema.maybe(
schema.oneOf([
schema.string(),
schema.any(), // KueryNode
])
),
}); });
export type ListWithKuery = TypeOf<typeof ListWithKuerySchema>; export type ListWithKuery = TypeOf<typeof ListWithKuerySchema>;