-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Bug][Investigations] - Fix slow timeline queries (#176838)
## Summary **Version Affected: 8.11.x, 8.12.0, 8.12.1** ### Background The ID field necessary to track long running timeline search strategy queries was no longer being passed to ES search after work in 8.11. This led to what looked like long running timeline queries, but in reality were queries being repeated due to the ID not being tracked. This pr re-introduces the ID field necessary for long running timeline search strategies in security solution **Views Affected:** - Timeline tabs (query, correlation, pinned) - Explore events tables (hosts, users, network) - Rule preview table Pre-fix: Observer the changing ID's for the `timelineSearchStrategy` `eventsAll` queries. https://github.com/elastic/kibana/assets/17211684/5731d310-d3ed-452d-8c34-783b2cfe76e1 Post-fix: Observer the same ID for the `timelineSearchStrategy` `eventsAll` queries. https://github.com/elastic/kibana/assets/17211684/a20d4b28-2748-4475-a257-96133bb8efc7 --------- Co-authored-by: kibanamachine <[email protected]>
- Loading branch information
1 parent
e2dfb09
commit 68bdd7c
Showing
8 changed files
with
434 additions
and
0 deletions.
There are no files selected for viewing
109 changes: 109 additions & 0 deletions
109
x-pack/plugins/timelines/common/api/search_strategy/timeline/eql.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { timelineEqlRequestOptionsSchema } from './eql'; | ||
import { mockBaseTimelineRequest } from './mocks/base_timeline_request'; | ||
|
||
const mockEqlRequestOptions = { | ||
...mockBaseTimelineRequest, | ||
filterQuery: 'sequence\n[any where true]\n[any where true]', | ||
eventCategoryField: 'event.category', | ||
tiebreakerField: '', | ||
fieldRequested: [ | ||
'@timestamp', | ||
'message', | ||
'event.category', | ||
'event.action', | ||
'host.name', | ||
'source.ip', | ||
'destination.ip', | ||
'user.name', | ||
'@timestamp', | ||
'kibana.alert.workflow_status', | ||
'kibana.alert.workflow_tags', | ||
'kibana.alert.workflow_assignee_ids', | ||
'kibana.alert.group.id', | ||
'kibana.alert.original_time', | ||
'kibana.alert.building_block_type', | ||
'kibana.alert.rule.from', | ||
'kibana.alert.rule.name', | ||
'kibana.alert.rule.to', | ||
'kibana.alert.rule.uuid', | ||
'kibana.alert.rule.rule_id', | ||
'kibana.alert.rule.type', | ||
'kibana.alert.suppression.docs_count', | ||
'kibana.alert.original_event.kind', | ||
'kibana.alert.original_event.module', | ||
'file.path', | ||
'file.Ext.code_signature.subject_name', | ||
'file.Ext.code_signature.trusted', | ||
'file.hash.sha256', | ||
'host.os.family', | ||
'event.code', | ||
'process.entry_leader.entity_id', | ||
], | ||
language: 'eql', | ||
pagination: { | ||
activePage: 0, | ||
querySize: 25, | ||
}, | ||
runtimeMappings: {}, | ||
size: 100, | ||
sort: [ | ||
{ | ||
direction: 'asc', | ||
esTypes: ['date'], | ||
field: '@timestamp', | ||
type: 'date', | ||
}, | ||
], | ||
timerange: { | ||
from: '2018-02-12T20:39:22.229Z', | ||
interval: '12h', | ||
to: '2024-02-13T20:39:22.229Z', | ||
}, | ||
timestampField: '@timestamp', | ||
}; | ||
|
||
describe('timelineEqlRequestOptionsSchema', () => { | ||
it('should correctly parse the last eql request object without unknown fields', () => { | ||
expect(timelineEqlRequestOptionsSchema.parse(mockEqlRequestOptions)).toEqual( | ||
mockEqlRequestOptions | ||
); | ||
}); | ||
|
||
it('should correctly parse the last eql request object and remove unknown fields', () => { | ||
const invalidEqlRequest = { | ||
...mockEqlRequestOptions, | ||
unknownField: 'should-be-removed', | ||
}; | ||
expect(timelineEqlRequestOptionsSchema.parse(invalidEqlRequest)).toEqual(mockEqlRequestOptions); | ||
}); | ||
|
||
it('should correctly error if an incorrect field type is provided for a schema key', () => { | ||
const invalidEqlRequest = { | ||
...mockEqlRequestOptions, | ||
fieldRequested: 123, | ||
}; | ||
|
||
expect(() => { | ||
timelineEqlRequestOptionsSchema.parse(invalidEqlRequest); | ||
}).toThrowErrorMatchingInlineSnapshot(` | ||
"[ | ||
{ | ||
\\"code\\": \\"invalid_type\\", | ||
\\"expected\\": \\"array\\", | ||
\\"received\\": \\"number\\", | ||
\\"path\\": [ | ||
\\"fieldRequested\\" | ||
], | ||
\\"message\\": \\"Expected array, received number\\" | ||
} | ||
]" | ||
`); | ||
}); | ||
}); |
76 changes: 76 additions & 0 deletions
76
x-pack/plugins/timelines/common/api/search_strategy/timeline/events_all.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { timelineEventsAllSchema } from './events_all'; | ||
import { mockBaseTimelineRequest } from './mocks/base_timeline_request'; | ||
|
||
const mockEventsAllRequest = { | ||
...mockBaseTimelineRequest, | ||
factoryQueryType: 'eventsAll', | ||
excludeEcsData: false, | ||
pagination: { activePage: 0, querySize: 25 }, | ||
fieldRequested: [ | ||
'@timestamp', | ||
'_index', | ||
'message', | ||
'host.name', | ||
'event.module', | ||
'agent.type', | ||
'event.dataset', | ||
'event.action', | ||
'user.name', | ||
'source.ip', | ||
'destination.ip', | ||
], | ||
sort: [ | ||
{ | ||
field: '@timestamp', | ||
type: 'date', | ||
direction: 'desc', | ||
esTypes: [], | ||
}, | ||
], | ||
fields: [], | ||
language: 'kuery', | ||
}; | ||
|
||
describe('timelineEventsAllSchema', () => { | ||
it('should correctly parse the events request object', () => { | ||
expect(timelineEventsAllSchema.parse(mockEventsAllRequest)).toEqual(mockEventsAllRequest); | ||
}); | ||
|
||
it('should correctly parse the events request object and remove unknown fields', () => { | ||
const invalidEventsRequest = { | ||
...mockEventsAllRequest, | ||
unknownField: 'shouldBeRemoved', | ||
}; | ||
expect(timelineEventsAllSchema.parse(invalidEventsRequest)).toEqual(mockEventsAllRequest); | ||
}); | ||
|
||
it('should correctly error if an incorrect field type is provided for a schema key', () => { | ||
const invalidEventsRequest = { | ||
...mockEventsAllRequest, | ||
excludeEcsData: 'notABoolean', | ||
}; | ||
|
||
expect(() => { | ||
timelineEventsAllSchema.parse(invalidEventsRequest); | ||
}).toThrowErrorMatchingInlineSnapshot(` | ||
"[ | ||
{ | ||
\\"code\\": \\"invalid_type\\", | ||
\\"expected\\": \\"boolean\\", | ||
\\"received\\": \\"string\\", | ||
\\"path\\": [ | ||
\\"excludeEcsData\\" | ||
], | ||
\\"message\\": \\"Expected boolean, received string\\" | ||
} | ||
]" | ||
`); | ||
}); | ||
}); |
55 changes: 55 additions & 0 deletions
55
x-pack/plugins/timelines/common/api/search_strategy/timeline/events_details.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { timelineEventsDetailsSchema } from './events_details'; | ||
|
||
const mockEventsDetails = { | ||
entityType: 'events', | ||
indexName: 'test-large-index', | ||
eventId: 'enfXnY0Byt9Ce9tO1aWh', | ||
factoryQueryType: 'eventsDetails', | ||
runtimeMappings: {}, | ||
}; | ||
|
||
describe('timelineEventsDetailsSchema', () => { | ||
it('should correctly parse the event details request schema', () => { | ||
expect(timelineEventsDetailsSchema.parse(mockEventsDetails)).toEqual(mockEventsDetails); | ||
}); | ||
|
||
it('should correctly parse the event details request schema and remove unknown fields', () => { | ||
const invalidEventsDetailsRequest = { | ||
...mockEventsDetails, | ||
unknownField: 'should-be-removed', | ||
}; | ||
expect(timelineEventsDetailsSchema.parse(invalidEventsDetailsRequest)).toEqual( | ||
mockEventsDetails | ||
); | ||
}); | ||
|
||
it('should correctly error if an incorrect field type is provided for a schema key', () => { | ||
const invalidEventsDetailsRequest = { | ||
...mockEventsDetails, | ||
indexName: 123, | ||
}; | ||
|
||
expect(() => { | ||
timelineEventsDetailsSchema.parse(invalidEventsDetailsRequest); | ||
}).toThrowErrorMatchingInlineSnapshot(` | ||
"[ | ||
{ | ||
\\"code\\": \\"invalid_type\\", | ||
\\"expected\\": \\"string\\", | ||
\\"received\\": \\"number\\", | ||
\\"path\\": [ | ||
\\"indexName\\" | ||
], | ||
\\"message\\": \\"Expected string, received number\\" | ||
} | ||
]" | ||
`); | ||
}); | ||
}); |
69 changes: 69 additions & 0 deletions
69
x-pack/plugins/timelines/common/api/search_strategy/timeline/events_last_event_time.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { timelineEventsLastEventTimeRequestSchema } from './events_last_event_time'; | ||
import { mockBaseTimelineRequest } from './mocks/base_timeline_request'; | ||
|
||
const mockEventsLastEventTimeRequest = { | ||
...mockBaseTimelineRequest, | ||
// Remove fields that are omitted in the schema | ||
runtimeMappings: undefined, | ||
filterQuery: undefined, | ||
timerange: undefined, | ||
// Add eventsLastEventTime specific fields | ||
factoryQueryType: 'eventsLastEventTime', | ||
indexKey: 'hosts', | ||
details: {}, | ||
}; | ||
|
||
describe('timelineEventsLastEventTimeRequestSchema', () => { | ||
it('should correctly parse the last event time request object without unknown fields', () => { | ||
expect(timelineEventsLastEventTimeRequestSchema.parse(mockEventsLastEventTimeRequest)).toEqual( | ||
mockEventsLastEventTimeRequest | ||
); | ||
}); | ||
|
||
it('should correctly parse the last event time request object and remove unknown fields', () => { | ||
const invalidEventsDetailsRequest = { | ||
...mockEventsLastEventTimeRequest, | ||
unknownField: 'should-be-removed', | ||
}; | ||
expect(timelineEventsLastEventTimeRequestSchema.parse(invalidEventsDetailsRequest)).toEqual( | ||
mockEventsLastEventTimeRequest | ||
); | ||
}); | ||
|
||
it('should correctly error if an incorrect field type is provided for a schema key', () => { | ||
const invalidEventsDetailsRequest = { | ||
...mockEventsLastEventTimeRequest, | ||
indexKey: 'unknown-key', | ||
}; | ||
|
||
expect(() => { | ||
timelineEventsLastEventTimeRequestSchema.parse(invalidEventsDetailsRequest); | ||
}).toThrowErrorMatchingInlineSnapshot(` | ||
"[ | ||
{ | ||
\\"received\\": \\"unknown-key\\", | ||
\\"code\\": \\"invalid_enum_value\\", | ||
\\"options\\": [ | ||
\\"hostDetails\\", | ||
\\"hosts\\", | ||
\\"users\\", | ||
\\"userDetails\\", | ||
\\"ipDetails\\", | ||
\\"network\\" | ||
], | ||
\\"path\\": [ | ||
\\"indexKey\\" | ||
], | ||
\\"message\\": \\"Invalid enum value. Expected 'hostDetails' | 'hosts' | 'users' | 'userDetails' | 'ipDetails' | 'network', received 'unknown-key'\\" | ||
} | ||
]" | ||
`); | ||
}); | ||
}); |
51 changes: 51 additions & 0 deletions
51
x-pack/plugins/timelines/common/api/search_strategy/timeline/kpi.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { timelineKpiRequestOptionsSchema } from './kpi'; | ||
import { mockBaseTimelineRequest } from './mocks/base_timeline_request'; | ||
|
||
const mockKpiRequest = { | ||
...mockBaseTimelineRequest, | ||
factoryQueryType: 'eventsKpi', | ||
}; | ||
|
||
describe('timelineKpiRequestOptionsSchema', () => { | ||
it('should correctly parse the events kpi request object', () => { | ||
expect(timelineKpiRequestOptionsSchema.parse(mockKpiRequest)).toEqual(mockKpiRequest); | ||
}); | ||
|
||
it('should correctly parse the events kpi request object and remove unknown fields', () => { | ||
const invalidKpiRequest = { | ||
...mockKpiRequest, | ||
unknownField: 'shouldBeRemoved', | ||
}; | ||
expect(timelineKpiRequestOptionsSchema.parse(invalidKpiRequest)).toEqual(mockKpiRequest); | ||
}); | ||
|
||
it('should correctly error if an incorrect field type is provided for a schema key', () => { | ||
const invalidKpiRequest = { | ||
...mockKpiRequest, | ||
factoryQueryType: 'someOtherType', | ||
}; | ||
|
||
expect(() => { | ||
timelineKpiRequestOptionsSchema.parse(invalidKpiRequest); | ||
}).toThrowErrorMatchingInlineSnapshot(` | ||
"[ | ||
{ | ||
\\"received\\": \\"someOtherType\\", | ||
\\"code\\": \\"invalid_literal\\", | ||
\\"expected\\": \\"eventsKpi\\", | ||
\\"path\\": [ | ||
\\"factoryQueryType\\" | ||
], | ||
\\"message\\": \\"Invalid literal value, expected \\\\\\"eventsKpi\\\\\\"\\" | ||
} | ||
]" | ||
`); | ||
}); | ||
}); |
20 changes: 20 additions & 0 deletions
20
x-pack/plugins/timelines/common/api/search_strategy/timeline/mocks/base_timeline_request.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
export const mockBaseTimelineRequest = { | ||
id: 'Fnh1dVQ4SDRTUldtRXpUcDEwZXliWHcdZXdlWVBFWkVSWHVIdzY4a19JbFRvUTozMzgzNzk=', | ||
defaultIndex: ['*-large-index'], | ||
filterQuery: | ||
'{"bool":{"must":[],"filter":[{"bool":{"should":[{"exists":{"field":"host.name"}}],"minimum_should_match":1}},{"range":{"@timestamp":{"gte":"2019-02-13T15:39:10.392Z","lt":"2024-02-14T04:59:59.999Z","format":"strict_date_optional_time"}}}],"should":[],"must_not":[]}}', | ||
runtimeMappings: {}, | ||
timerange: { | ||
interval: '12h', | ||
from: '2019-02-13T15:39:10.392Z', | ||
to: '2024-02-14T04:59:59.999Z', | ||
}, | ||
entityType: 'events', | ||
}; |
Oops, something went wrong.