[RAM] Add shareable rule tag filter#130710
Conversation
|
@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. |
|
@elasticmachine merge upstream |
|
@mgiota I added changes to the |
|
@elasticmachine merge upstream |
|
Pinging @elastic/response-ops (Team:ResponseOps) |
|
@JiaweiWu I gave it a try and yep it works! I will have a look again a bit later and approve the PR. |
|
|
||
| const getRuleTagFilter = () => { | ||
| if (isRuleTagFilterEnabled) { | ||
| return [<RuleTagFilter tags={tags} selectedTags={tagsFilter} onChange={setTagsFilter} />]; |
There was a problem hiding this comment.
@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?

There was a problem hiding this comment.
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.
|
It would be great if we could get this PR merged soon, so that I can working on #127013 |
| snoozed: snoozedBuckets.reduce((acc, bucket) => acc + bucket.doc_count, 0), | ||
| }; | ||
|
|
||
| const tagsBuckets = resp.aggregations.tags.buckets; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I tested it with rules that have no tags, but I'll add a fall back just in case
There was a problem hiding this comment.
Always build these things defensively, otherwise the UI breaks and we have no idea unless someone files an SDH.
Thanks 🙏
chrisronline
left a comment
There was a problem hiding this comment.
Looking great so far, had a couple of thoughts/questions in my first pass
| JSON.stringify(typesFilter), | ||
| JSON.stringify(actionTypesFilter), | ||
| JSON.stringify(ruleStatusesFilter), | ||
| JSON.stringify(tagsFilter), |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
@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.
There was a problem hiding this comment.
Yep, this is getting improved in my rules_list refactor
|
@elasticmachine merge upstream |
| } | ||
| } | ||
|
|
||
| async function loadRuleTags() { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
yea thought so, ok I'll add a new endpoint to expose tags
💔 Build FailedFailed CI StepsMetrics [docs]Module Count
Public APIs missing comments
Async chunks
Public APIs missing exports
Page load bundle
Unknown metric groupsAPI count
async chunk count
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
chrisronline
left a comment
There was a problem hiding this comment.
LGTM! Great work here
|
@elasticmachine merge upstream |
|
Hey there! It seems like I have to slightly bump the bundle size for |
|
@elasticmachine merge upstream |
💚 Build SucceededMetrics [docs]Module Count
Public APIs missing comments
Async chunks
Public APIs missing exports
Page load bundle
Unknown metric groupsAPI count
async chunk count
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
…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
* 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 <42973632+kibanamachine@users.noreply.github.com>

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.