-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Security Solution] Improve rule execution logging #166070
Conversation
041e660
to
dc87714
Compare
f855671
to
f3c7960
Compare
Pinging @elastic/security-detections-response (Team:Detections and Resp) |
Pinging @elastic/security-solution (Team: SecuritySolution) |
f3c7960
to
8f54db1
Compare
8f54db1
to
50ccd5c
Compare
@@ -5,6 +5,7 @@ | |||
* 2.0. | |||
*/ | |||
|
|||
import _ from 'lodash'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if our bundler already imports only the used methods here but consider doing named imports for omitBy
and isUndefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point 👍 I relied on my IDE to add an import and automatic checks but it seems we don't control such imports automatically. Searching in the codebase shows only specific function imports. So it makes to change to importing directly omitBy
and isUndefined
.
export interface FetchRuleExecutionEventsArgs extends RuleMonitoringApiCallArgs { | ||
/** | ||
* Saved Object ID of the rule (`rule.id`, not static `rule.rule_id`). | ||
*/ | ||
ruleId: string; | ||
|
||
/** | ||
* Filter by event message. If set, result will include only events matching the search term. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
* Filter by event message. If set, result will include only events matching the search term. | |
* Filter by event message. If set, results will include events matching the search term. |
@@ -62,6 +72,11 @@ export interface FetchRuleExecutionEventsArgs extends RuleMonitoringApiCallArgs | |||
*/ | |||
logLevels?: LogLevel[]; | |||
|
|||
/** | |||
* Filter by date range. If set, result will include only events recorded in the specified date range. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
* Filter by date range. If set, result will include only events recorded in the specified date range. | |
* Filter by date range. If set, results will include events recorded in the specified date range. |
...toring/components/execution_events_table/event_date_range_filter/event_date_range_filter.tsx
Outdated
Show resolved
Hide resolved
onChange: (value: string) => void; | ||
} | ||
|
||
export function EventMessageFilter({ value, onChange }: EventMessageFilterProps): JSX.Element { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also this component. Please use React.memo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My answer the same as here. Wrapping every possible component in React.memo
doesn't guarantee a performance boost and it doesn't come for free as it also leads to increased memory consumption. Ideally we should wrap only heavy components where render function performs a lot of operations and it's usually true for data grids, lists, components higher in a component tree hierarchy.
Do you have some examples of troubles with such components?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with your point on using memo
correctly. It does add more JS for the browser to parse and execute and we should use memo
sparingly. Is there a reason you want to create a wrapper component around EuiFieldSearch
instead of using it as is in execution_events_table.tsx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EventMessageFilter
solves an interfacing issue. It happens because components may return change events like EuiFieldSearch
's onChange
accepts ChangeEvent
. It's an implementation detail and should be incapsulated. This way useFilter
only operates on actual values while implementation detail can rely on whatever component. handleChange
inside EventMessageFilter
is an adapter transforming ChangeEvent<HTMLInputElement>
into a simpler text value. This way we can change the implementation e.g. replace EuiFieldSearch
with something else without changing anything outside of this component. Yes, handleChange
could be defined in ExecutionEventsTable
but it won't conform to EventMessageFilter
and LogLevelFilter
and break a consisting approach. It's not a case for EuiSuperDatePicker
so I made according changes by using it directly. If it required some transformation it'd be logical to wrap it in a component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation @maximpn.
const startDate = dateRange?.start ? dateMath.parse(dateRange.start)?.toISOString() : undefined; | ||
const endDate = dateRange?.end | ||
? dateMath.parse(dateRange.end, { roundUp: true })?.toISOString() | ||
: undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const startDate = dateRange?.start ? dateMath.parse(dateRange.start)?.toISOString() : undefined; | |
const endDate = dateRange?.end | |
? dateMath.parse(dateRange.end, { roundUp: true })?.toISOString() | |
: undefined; | |
const startDate = dateMath.parse(dateRange?.start ?? '')?.toISOString(); | |
const endDate = dateMath.parse(dateRange?.end ?? '', { roundUp: true })?.toISOString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid dateMath.parse('')
is undetermined and it will be unclear what this code does without deep diving into dateMath.parse
's code or running it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dateMath.parse('')
will return undefined
when an empty string is passed. So my suggestion is just a simplification of the earlier code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern was an unexpected change of such behavior due to changes to dateMath
. But we can mitigate it by properly testing it which I did and applying your suggestion. Thank you for helping to look under a different angle 👍 it will help to make sure the behavior is stable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes.
{ | ||
search_term: searchTerm?.length ? searchTerm : undefined, | ||
event_types: eventTypes?.length ? eventTypes.join(',') : undefined, | ||
log_levels: logLevels?.length ? logLevels?.join(',') : undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log_levels: logLevels?.length ? logLevels?.join(',') : undefined, | |
log_levels: logLevels?.length ? logLevels.join(',') : undefined, |
50ccd5c
to
01b6171
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Detections changes LGTM 👍
01b6171
to
0d0529e
Compare
236dcd4
to
fa54d80
Compare
💛 Build succeeded, but was flaky
Failed CI StepsTest Failures
Metrics [docs]Module Count
Async chunks
History
To update your PR or re-run it, just comment with: cc @maximpn |
return createSearchAfterReturnType({ | ||
success: false, | ||
errors: ['malformed date tuple'], | ||
}); | ||
} | ||
|
||
while (toReturn.createdSignalsCount <= tuple.maxSignals) { | ||
const cycleNum = `cycle ${searchingIteration++}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to add documentation somewhere for what a cycle
is in this instance if we're exposing these logs a lot more. At least for internal use. Especially since we could have multiple cycle 1, 2, etc...
per tuple in the rule run
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks good and works with my manual testing 👍
Relates to: #126063
Summary
This PR extends rule event log's filter and improves log messages.
Details
We have Rule execution log feature hidden by a feature flag and disabled, it's shown on a rule details page when enabled.
The feature is close to a releasable state but some tasks had to be addressed to make it usable. This PR addresses the following tasks to make rule execution log feature releasable
execution_id
to the responseTasks to address later