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

[Security Solution] Improve rule execution logging #166070

Merged
merged 23 commits into from
Sep 19, 2023

Conversation

maximpn
Copy link
Contributor

@maximpn maximpn commented Sep 8, 2023

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.

image

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

  • Adds search bar to search for specific messages
image
  • Adds a date range filter by default set to show logs for last 24 hours
image
  • Improves error, warning and debug messages
  • Returns rule metrics in a message as a serialized JSON
image
  • Adds execution_id to the response
image

Tasks to address later

  • Further improve logging messages. We have either error, warning or debug messages. In fact info or trace levels aren't used but it can give useful info.
  • Add an OpenAPI spec for the rule execution log endpoint

@maximpn maximpn added technical debt Improvement of the software architecture and operational architecture Team:Detections and Resp Security Detection Response Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Feature:Rule Monitoring Security Solution Detection Rule Monitoring area Team:Detection Rule Management Security Detection Rule Management Team v8.11.0 labels Sep 8, 2023
@maximpn maximpn self-assigned this Sep 8, 2023
@maximpn maximpn force-pushed the improve-rule-event-log branch from 041e660 to dc87714 Compare September 8, 2023 21:26
@maximpn maximpn changed the title [Security Solution] Improve rule event log [Security Solution] Improve rule execution logging Sep 10, 2023
@maximpn maximpn force-pushed the improve-rule-event-log branch from f855671 to f3c7960 Compare September 11, 2023 14:15
@maximpn maximpn marked this pull request as ready for review September 12, 2023 14:21
@maximpn maximpn requested review from a team as code owners September 12, 2023 14:21
@elasticmachine
Copy link
Contributor

Pinging @elastic/security-detections-response (Team:Detections and Resp)

@maximpn maximpn requested a review from jpdjere September 12, 2023 14:21
@elasticmachine
Copy link
Contributor

Pinging @elastic/security-solution (Team: SecuritySolution)

@maximpn maximpn force-pushed the improve-rule-event-log branch from f3c7960 to 8f54db1 Compare September 12, 2023 14:23
@maximpn maximpn removed the request for review from jpdjere September 13, 2023 09:28
@maximpn maximpn force-pushed the improve-rule-event-log branch from 8f54db1 to 50ccd5c Compare September 13, 2023 09:46
@@ -5,6 +5,7 @@
* 2.0.
*/

import _ from 'lodash';
Copy link
Member

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

Copy link
Contributor Author

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
* 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
* 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.

onChange: (value: string) => void;
}

export function EventMessageFilter({ value, onChange }: EventMessageFilterProps): JSX.Element {
Copy link
Member

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

Copy link
Contributor Author

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?

Copy link
Member

@ashokaditya ashokaditya Sep 14, 2023

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

Copy link
Contributor Author

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.

Copy link
Member

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.

Comment on lines 53 to 56
const startDate = dateRange?.start ? dateMath.parse(dateRange.start)?.toISOString() : undefined;
const endDate = dateRange?.end
? dateMath.parse(dateRange.end, { roundUp: true })?.toISOString()
: undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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();

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Member

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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log_levels: logLevels?.length ? logLevels?.join(',') : undefined,
log_levels: logLevels?.length ? logLevels.join(',') : undefined,

@maximpn maximpn force-pushed the improve-rule-event-log branch from 50ccd5c to 01b6171 Compare September 13, 2023 13:19
@maximpn maximpn added the release_note:skip Skip the PR/issue when compiling release notes label Sep 13, 2023
Copy link
Contributor

@dhurley14 dhurley14 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detections changes LGTM 👍

@maximpn maximpn force-pushed the improve-rule-event-log branch from 01b6171 to 0d0529e Compare September 14, 2023 21:51
@maximpn maximpn force-pushed the improve-rule-event-log branch from 236dcd4 to fa54d80 Compare September 15, 2023 23:15
@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #24 / apis UI Counters UI Counters API stores ui counter events in usage counters savedObjects

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 4505 4508 +3

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
securitySolution 12.6MB 12.6MB +1.8KB

History

  • 💚 Build #159284 succeeded 0d0529ea753de774b589b7525433cf2dee75f754
  • 💔 Build #158704 failed 01b6171d0f2f85a98e3dc025d5b7eaa5330ee684
  • 💔 Build #158603 failed 50ccd5c230d809bbb41762ee450218442f2dc991
  • 💔 Build #158371 failed 8f54db10b5529a4f9712d239a5c28ad625de4092
  • 💛 Build #158005 was flaky f3c79600deeae33153cadd5a8cf51598cdf4b86b
  • 💔 Build #157935 failed f8556710182806b106ee1465d3a1bc4d9de5c62d

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @maximpn

@dplumlee dplumlee self-requested a review September 18, 2023 14:40
return createSearchAfterReturnType({
success: false,
errors: ['malformed date tuple'],
});
}

while (toReturn.createdSignalsCount <= tuple.maxSignals) {
const cycleNum = `cycle ${searchingIteration++}`;
Copy link
Contributor

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

Copy link
Contributor

@dplumlee dplumlee left a 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 👍

@maximpn maximpn merged commit 6a96906 into elastic:main Sep 19, 2023
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Sep 19, 2023
@maximpn maximpn deleted the improve-rule-event-log branch September 19, 2023 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Rule Monitoring Security Solution Detection Rule Monitoring area release_note:skip Skip the PR/issue when compiling release notes Team:Detection Rule Management Security Detection Rule Management Team Team:Detections and Resp Security Detection Response Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. technical debt Improvement of the software architecture and operational architecture v8.11.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants