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

[ResponseOps][Alerts] Add alerts grouping aggregations endpoint #186475

Conversation

umbopepato
Copy link
Member

@umbopepato umbopepato commented Jun 19, 2024

Summary

Adds an endpoint dedicated to fetching alerts group aggregations to avoid adding runtime mappings and client-side controlled scripts to the internal/rac/alerts/find endpoint.
The new endpoint injects a groupByField runtime field used to normalize the values of the field used for grouping, to account for null and multi-element arrays.

#184635 depends on this

Closes #186383

To verify

Review the added tests.
Use the Kibana Dev Console to test various body params and aggregations:

  1. Create any type of rule that fire alerts
  2. Wait for the alerts to be created
  3. Call the _group_aggregations endpoint, using the feature id(s) that cover the type of rules you used:
POST kbn:internal/rac/alerts/_group_aggregations
{
   "featureIds": [...],
  ...
}

See here and here to know the available params and pre-defined aggregations.

Checklist

@umbopepato
Copy link
Member Author

/ci

@umbopepato
Copy link
Member Author

/ci

@umbopepato
Copy link
Member Author

/ci

@umbopepato
Copy link
Member Author

/ci

@umbopepato umbopepato added release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) v8.15.0 labels Jun 20, 2024
@umbopepato umbopepato marked this pull request as ready for review June 20, 2024 08:19
@umbopepato umbopepato requested review from a team as code owners June 20, 2024 08:19
@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@umbopepato umbopepato requested review from adcoelho and JiaweiWu June 20, 2024 08:42
});
});

test('returns error status if rac client find fails', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you also add a test where getGroupAggregations resolves but alerts == null? If I understand correctly the message should be different right? Satus 404 and message alerts not found?

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed on Slack that case is unreachable without an exception being thrown, I've removed the check altogether

/**
* Performs a `find` query to extract aggregations on alert groups
*/
public getGroupAggregations({
Copy link
Contributor

Choose a reason for hiding this comment

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

How about adding something like x-pack/plugins/rule_registry/server/alert_data_client/tests/getGroupAggregations.test.ts that tests this?

Nothing too elaborate, to ensure that find is called with the correct params and no changes break this function.

I know we do some testing in x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts but that is like "indirectly" 😛

Copy link
Member

Choose a reason for hiding this comment

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

+1

pageSize?: number;
}) {
const uniqueValue = uuid();
return this.find({
Copy link
Contributor

@adcoelho adcoelho Jun 20, 2024

Choose a reason for hiding this comment

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

Like you were saying yesterday, QueryDSL gives me headaches 😄

@@ -5,6 +5,7 @@
* 2.0.
*/
import Boom from '@hapi/boom';
import { v4 as uuid } from 'uuid';
Copy link
Contributor

Choose a reason for hiding this comment

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

super nit:

Suggested change
import { v4 as uuid } from 'uuid';
import { v4 as uuidv4 } from 'uuid';

*
* Applies alerting RBAC through featureIds.
*/
export const useGetAlertsGroupAggregationsQuery = <T>({
Copy link
Contributor

@adcoelho adcoelho Jun 20, 2024

Choose a reason for hiding this comment

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

Could you please add tests for this in packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.ts? Stuff like displays error toast if params are not JSON or API gets called with the correct body..

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
observability 467 468 +1
triggersActionsUi 764 765 +1
total +2

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
ruleRegistry 247 249 +2

Async chunks

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

id before after diff
triggersActionsUi 1.7MB 1.7MB +6.0B
Unknown metric groups

API count

id before after diff
ruleRegistry 276 286 +10

History

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

Copy link
Member

@cnasikas cnasikas left a comment

Choose a reason for hiding this comment

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

LGTM! I left some comments.

/**
* Any sort options to apply to the groupByField aggregations
*/
sort?: object[];
Copy link
Member

Choose a reason for hiding this comment

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

In the useGetAlertsGroupAggregationsQuery you used the SortCombinations type for the sort. Should we use the same here?

/**
* Performs a `find` query to extract aggregations on alert groups
*/
public getGroupAggregations({
Copy link
Member

Choose a reason for hiding this comment

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

+1

pageIndex = 0,
pageSize = DEFAULT_ALERTS_GROUP_BY_FIELD_SIZE,
} = request.body;
if (pageIndex < 0 || pageIndex > 100) {
Copy link
Member

Choose a reason for hiding this comment

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

With this validation, it seems that we cap users to not be able to go over the 100th page if the pageSize is 1. What about the following?

if (pageIndex > maxPerPage) { <--- 100 items per page
  throw Boom.badRequest('The provided pageIndex value is too high. The maximum allowed pageIndex value is ${maxPerPage}.');
}

if (Math.max(pageIndex, pageIndex * pageSize) > MAX_DOCS_PER_PAGE) { <-- 10K max documents
   throw Boom.badRequest('The number of documents is too high. Paginating through more than ${MAX_DOCS_PER_PAGE} documents is not possible.');
}

Also, I am wondering if we should move the validation inside the alertsClient.getGroupAggregations. This way consumers of the alert client will have the same validation. Wdyt?

Copy link
Member

@cnasikas cnasikas left a comment

Choose a reason for hiding this comment

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

Thanks for your patience with the review! LGTM 🚀 !

cnasikas

This comment was marked as duplicate.

Copy link
Contributor

@JiaweiWu JiaweiWu left a comment

Choose a reason for hiding this comment

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

LGTM, just some small comments

index?: string;
_source?: string[] | undefined;
_source?: string[] | false;
Copy link
Contributor

Choose a reason for hiding this comment

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

curious about this type, why can it be false?

Copy link
Member Author

Choose a reason for hiding this comment

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

To disable the _source field (docs)

this.logger.error(errorMessage);
throw Boom.badData(errorMessage);
}
if (result?.hits?.hits?.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: can return early here

if (!result?.hits?.hits?.length) {
  return result;
}
... rest

);

export const alertsGroupFilterSchema = t.record(
t.union([
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have existing enums for these literals? Just so we can have a more centralized source of truth

Copy link
Member Author

Choose a reason for hiding this comment

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

Would have been nice, but I was only able to find type-level information. I added a type assertion to check that the keys are correctly aligned to the es types though 🙂

script: {
source:
// When size()==0, emits a uniqueValue as the value to represent this group else join by uniqueValue.
"if (doc[params['selectedGroup']].size()==0) { emit(params['uniqueValue']) }" +
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: can use `` to avoid concatenating the strings

Copy link
Member Author

@umbopepato umbopepato Jul 4, 2024

Choose a reason for hiding this comment

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

Yep, I thought it was worth keeping it as it was originally written by Security though, to comment the two parts separately 🙂

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
observability 469 470 +1
triggersActionsUi 770 771 +1
total +2

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
ruleRegistry 247 249 +2

Async chunks

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

id before after diff
triggersActionsUi 1.7MB 1.7MB +6.0B
Unknown metric groups

API count

id before after diff
ruleRegistry 276 286 +10

History

@umbopepato umbopepato merged commit 52ccd17 into elastic:main Jul 4, 2024
35 of 36 checks passed
@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.16 The branch "8.16" does not exist

Manual backport

To create the backport manually run:

node scripts/backport --pr 186475

Questions ?

Please refer to the Backport tool documentation

@cnasikas cnasikas removed the v8.16.0 label Jul 5, 2024
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Aug 27, 2024
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add the label auto-backport or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 186475 locally

@cnasikas cnasikas added backport:skip This commit does not require backporting and removed backport missing Added to PRs automatically when the are determined to be missing a backport. labels Sep 3, 2024
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 release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) v8.15.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ResponseOps][Alerts] Grouping aggregations endpoint
7 participants