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

[RAM] Add shareable rule tag filter #130710

Merged
merged 20 commits into from
May 6, 2022

Conversation

JiaweiWu
Copy link
Contributor

@JiaweiWu JiaweiWu commented Apr 20, 2022

Summary

Resolves: #130158

Adds a shareable rule tags filter, this is a new component that does not exist as a part of the rule list currently. Therefore, it is not being used, except as a shareable component (hidden behind a feature flag).

This change also required new aggregations on the tags field since we need a list of all tags that the user can filter on. So the alerting aggregation function was modified. API and E2E tests were written to cover this.

rule_tags_filter

@JiaweiWu JiaweiWu added release_note:skip Skip the PR/issue when compiling release notes backport:skip This commit does not require backporting Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) Feature:Alerting/RulesManagement Issues related to the Rules Management UX v8.3.0 labels Apr 20, 2022
@mgiota
Copy link
Contributor

mgiota commented Apr 20, 2022

@JiaweiWu LGTM so far!

For the tags filter to work, I expect one change in this function call https://github.com/elastic/kibana/blob/main/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts#L40 where we need to pass the new tagsFilter along with the rest filters that are currently being passed. This means that this file https://github.com/elastic/kibana/blob/main/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.ts needs to be changed as well.

@JiaweiWu
Copy link
Contributor Author

@elasticmachine merge upstream

@JiaweiWu
Copy link
Contributor Author

@mgiota I added changes to the loadRules and API changes, feel free to give it a test

@JiaweiWu
Copy link
Contributor Author

@elasticmachine merge upstream

@JiaweiWu JiaweiWu marked this pull request as ready for review April 28, 2022 00:31
@JiaweiWu JiaweiWu requested a review from a team as a code owner April 28, 2022 00:31
@elasticmachine
Copy link
Contributor

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

@JiaweiWu JiaweiWu requested a review from mgiota April 28, 2022 00:31
@JiaweiWu JiaweiWu changed the title [RAM] Add shareable rule tags filter [RAM] Add shareable rule tag filter Apr 28, 2022
@mgiota
Copy link
Contributor

mgiota commented Apr 28, 2022

@JiaweiWu I gave it a try and yep it works!
Screenshot 2022-04-28 at 15 17 23

I will have a look again a bit later and approve the PR.

@@ -930,6 +942,13 @@ export const RulesList: React.FunctionComponent = () => {
);
};

const getRuleTagFilter = () => {
if (isRuleTagFilterEnabled) {
return [<RuleTagFilter tags={tags} selectedTags={tagsFilter} onChange={setTagsFilter} />];
Copy link
Contributor

Choose a reason for hiding this comment

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

@JiaweiWu Since I had to do the loadRuleAggregations logic on our side same way you did above in order to setTags, I was wondering if it would make sense to make the tags prop optional and have this logic implemented within the RuleTagFilter, if you know what I mean. The code I had to add is similar to what you have on your side, that's why I am wondering if we could avoid this repetition.

I don't mind merging current PR and have a follow up PR when there's more time. I just wanted to hear your opinion, regarding moving the aggregations on the tags field within the RuleTagFilter, so that consumer doesn't have to write this logic. What do you think?
Screenshot 2022-04-28 at 21 28 15

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We had a chat and I brought up the issue that the rules_list aggregations require filter parameters from other filters as well (actionTypes, ruleStatuses, etc.) which makes it outside of the responsibility of the tag filter component.

I'm currently working on refactoring and making the rules list shareable, which will involves moving the fetching logic into hooks. So I think that will indirectly solve this problem.

@mgiota mgiota self-requested a review April 28, 2022 19:48
Copy link
Contributor

@mgiota mgiota left a comment

Choose a reason for hiding this comment

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

I approve this PR! Later on we could refactor so that the server requests the tags and the consumer doesn't have to pass any tags prop.

@mgiota
Copy link
Contributor

mgiota commented Apr 29, 2022

It would be great if we could get this PR merged soon, so that I can working on #127013

@@ -990,6 +1000,9 @@ export class RulesClient {
snoozed: snoozedBuckets.reduce((acc, bucket) => acc + bucket.doc_count, 0),
};

const tagsBuckets = resp.aggregations.tags.buckets;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we confident the buckets are always there?
ES has a tendency to drop keys in aggs when there are no hits (such as a cluster with no rules in it or when a filter is applied).

Worth treading with caution and checking for undefined keys.

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 tested it with rules that have no tags, but I'll add a fall back just in case

Copy link
Contributor

Choose a reason for hiding this comment

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

Always build these things defensively, otherwise the UI breaks and we have no idea unless someone files an SDH.

Thanks 🙏

Copy link
Contributor

@chrisronline chrisronline left a comment

Choose a reason for hiding this comment

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

Looking great so far, had a couple of thoughts/questions in my first pass

@@ -226,6 +232,7 @@ export const RulesList: React.FunctionComponent = () => {
JSON.stringify(typesFilter),
JSON.stringify(actionTypesFilter),
JSON.stringify(ruleStatusesFilter),
JSON.stringify(tagsFilter),
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need to worry about this in this PR but this code should be improved. It looks like we're doing multiple JSON.stringify calls every render - we should redo this a bit to be more performant. WDYT?

Copy link
Contributor

@mgiota mgiota Apr 29, 2022

Choose a reason for hiding this comment

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

@JiaweiWu In case it is useful, here's what I used https://github.com/elastic/kibana/blob/main/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts#L36 when I moved this code under observability in a use_fetch_rules hook. I got rid of JSON.stringify and used useCallback.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, this is getting improved in my rules_list refactor

@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented May 3, 2022

@elasticmachine merge upstream

@@ -345,6 +356,24 @@ export const RulesList: React.FunctionComponent = () => {
}
}

async function loadRuleTags() {
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 want to give more context to this function here. So there's an awkward behaviour when I added the tag filters to the aggregation, because we use 1 aggregation function to get a list of tags and all of the rule execution status values, if we started filtering down the aggregation with tag filters, the list of tags would also get filtered, and thus it would replace the list of available tags with a smaller subset of tags (which is incorrect).

To fix this, i considered only calling setState on the tags list if the tagsFilter is empty. But this is also incorrect because we miss the edge case where the user adds new tags or a new rule while the tag filter is applied.

From there, I decided to add this function, which calls the aggregation with empty params, as a part of the data fetch. I think the downside here is we're doing the aggregation twice now, which has performance implications.

But aside from doing something client side like merging in new tags in react, we might eventually want to have a separate aggregation just to get a list of tags. Let me know if we want to do that in this PR or I could do it in another PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to understand this more? How can I simulate this? Or can I see this happening on an older version of this PR?

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 didn't have the tag filters passed into the aggregation for the previous commit, you can simulate it by checking out the previous commit and passing the tag filters:

rules_list.tsx:
async function loadRuleAggs() {
  try {
    const rulesAggs = await loadRuleAggregations({
      http,
      searchText,
      typesFilter,
      actionTypesFilter,
      ruleExecutionStatusesFilter,
      ruleStatusesFilter,
      tagsFilter,
  });
  ...
}
aggregate.ts:
export async function loadRuleAggregations({
  const filters = mapFiltersToKql({
    typesFilter,
    actionTypesFilter,
    ruleExecutionStatusesFilter,
    ruleStatusesFilter,
    tagsFilter,
  });
  ...
}

Switching the experiment on and filter by tags using the dropdown, you'll notice the entire list of available tags gets filtered as well

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm

What about something like:

 async function loadRuleAggs() {
    try {
      const rulesAggs = await loadRuleAggregations({
        http,
        searchText,
        typesFilter,
        actionTypesFilter,
        ruleStatusesFilter,
        tagsFilter,
      });
      if (rulesAggs?.ruleExecutionStatus) {
        setRulesStatusesTotal(rulesAggs.ruleExecutionStatus);
      }
      if (rulesAggs?.ruleTags && rulesAggs?.ruleTags.length > tags.length) {
        setTags(rulesAggs.ruleTags);
      }
    } 

I guess this doesn't work if we delete a rule and a tag is only associated with that rule though

I think we should separate these two things out into separate "things" - api that is called that is assumed to return filtered data and a separate api call that is expected to return total data. We might need to add something to the lib/rule_api layer too but it's too confusing to keep this logic as-is - definitely recommend some delineation here to make it clear in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yea thought so, ok I'll add a new endpoint to expose tags

@JiaweiWu JiaweiWu requested review from chrisronline and gmmorris May 4, 2022 17:13
@kibana-ci
Copy link
Collaborator

💔 Build Failed

Failed CI Steps

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
triggersActionsUi 373 376 +3

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
alerting 316 317 +1
triggersActionsUi 316 320 +4
total +5

Async chunks

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

id before after diff
triggersActionsUi 728.2KB 732.4KB +4.1KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
triggersActionsUi 27 28 +1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff errors
triggersActionsUi 100.5KB 101.1KB +611.0B ❌ 169.0B over limit
Unknown metric groups

API count

id before after diff
alerting 325 326 +1
triggersActionsUi 330 334 +4
total +5

async chunk count

id before after diff
triggersActionsUi 80 81 +1

ESLint disabled line counts

id before after diff
triggersActionsUi 171 172 +1

Total ESLint disabled count

id before after diff
triggersActionsUi 177 178 +1

History

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

Copy link
Contributor

@chrisronline chrisronline left a comment

Choose a reason for hiding this comment

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

LGTM! Great work here

@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented May 6, 2022

@elasticmachine merge upstream

@JiaweiWu JiaweiWu requested a review from a team as a code owner May 6, 2022 17:37
@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented May 6, 2022

Hey there! It seems like I have to slightly bump the bundle size for triggers_actions_ui again. For context, we have determined ways to lower our bundle size (#130728) + our current efforts to make make our components shareable to other plugins (which is what this PR is doing). Once that happens, our bundle size should go down quite a bit, however, right now we're in this awkward point where there's a lot of PRs happening to try and make this happen from various teams, so we're going to work on reducing the bundle size near the end of this release once the dust settles a bit.

@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented May 6, 2022

@elasticmachine merge upstream

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
triggersActionsUi 373 376 +3

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
alerting 316 317 +1
triggersActionsUi 316 320 +4
total +5

Async chunks

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

id before after diff
triggersActionsUi 725.3KB 729.4KB +4.1KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
triggersActionsUi 27 28 +1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
triggersActionsUi 100.2KB 100.8KB +611.0B
Unknown metric groups

API count

id before after diff
alerting 325 326 +1
triggersActionsUi 330 334 +4
total +5

async chunk count

id before after diff
triggersActionsUi 80 81 +1

ESLint disabled line counts

id before after diff
triggersActionsUi 171 172 +1

Total ESLint disabled count

id before after diff
triggersActionsUi 177 178 +1

History

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

@JiaweiWu JiaweiWu merged commit 19298ee into elastic:main May 6, 2022
jloleysens added a commit to jloleysens/kibana that referenced this pull request May 9, 2022
…hromium-to-print-pdf-part-1

* 'main' of github.com:elastic/kibana: (59 commits)
  [Cloud Posture] Enabled findings group by feature (elastic#131780)
  [EBT] Fix `userId` generation (elastic#131701)
  [RAM] Add shareable rule tag filter (elastic#130710)
  Optimize package installation performance, phase 2 (elastic#131627)
  [Screenshotting] instrument for benchmark tests using new EventLogger class (elastic#130356)
  [Connector] Adding internal route for requesting ad-hoc ServiceNow access token (elastic#131171)
  [ci] bump kibana-buildkite-library (elastic#131754)
  [Synthetics] UI clean up (elastic#131598)
  [RsponseOps] Fix flaky rules list test (elastic#131567)
  [Cases] Add severity field to create case (elastic#131626)
  [Discover] Monospace font in Document Explorer (elastic#131513)
  Sessions tab improvements (elastic#131583)
  Add cloud icon "ess-icon" at the end of the config keys in "alerting" documentation (elastic#131735)
  [DOCS] Updates deprecation text for legacy APIs (elastic#131741)
  [ci] break out skip patterns so they can change without triggering CI (elastic#131726)
  Adjust search session management page font size (elastic#131291)
  [Unified search] Fix uptime css problem (elastic#131730)
  [Actionable Observability] Link to filtered rules page (elastic#131629)
  Add openAPI specifications for cases endpoint (elastic#131275)
  Display rule API key owner to users who can manage API keys (elastic#131662)
  ...

# Conflicts:
#	x-pack/plugins/screenshotting/server/formats/pdf/index.ts
#	x-pack/plugins/screenshotting/server/screenshots/observable.ts
kertal pushed a commit to kertal/kibana that referenced this pull request May 24, 2022
* rule tag filter

* lower case test subj

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* Tag filter and aggregation APIs

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* Fix and add more tests

* Fix test

* Fix test and add new function test

* Addressed comments

* Lint

* Create new load tags function

* bump bundle size

Co-authored-by: kibanamachine <[email protected]>
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:Alerting/RulesManagement Issues related to the Rules Management UX 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.3.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RAM] Add tag filter to rules list and make it shareable
8 participants