Skip to content

[ResponseOps][Alerts] Implement alerts filters form #214982

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

Merged
merged 28 commits into from
Apr 17, 2025

Conversation

umbopepato
Copy link
Member

@umbopepato umbopepato commented Mar 18, 2025

Summary

Implements the alerts filters form that will be used to pre-filter the alerts table embeddable.

image

Note

I'm using the terminology "form" to distinguish this from the alert filter controls or other type of more KQL-bar-like filters. Other alternatives that came to mind were alerts-boolean-filters-... or alerts-filters-builder.

Implementation details

Filters expression state

I opted for a tree state representation of the form's boolean expression to accommodate potential future requirements such as more complex boolean expressions (negation, parenthesized subexpressions to manually control operators precedence):

{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}

This state is saved in the embeddable panel state and represents the editor form. The embeddable alerts table wrapper component will then transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent flattened state is used:

[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]

Filters model

Each filter is described by an AlertsFilterMetadata<T> object, where T is the type of the filter value:

export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};

Verification steps

  1. Run Kibana with examples (yarn start --run-examples)
  2. Create rules in different solutions with tags
  3. Navigate to /app/triggersActionsUiExample/alerts_filters_form
  4. Check that the solution selector options are coherent with the rule types the user can access
  5. Select a solution
  6. Build filters expressions, checking that the rule tags and rule types are coherent with the solution selection and the rules created previously
  7. Repeat steps 3-6 with different roles:
    7.1. having access to rule types from just one solution (in this case the solution selector shouldn't appear at all),
    7.2. having access just to Observability and Stack but not Security (in this case the solution selector shouldn't appear at all),
  8. Repeat steps 3-6 in the three serverless project types:
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    (If the authentication fails when switching between project types, use a clean session)
    8.1. ES project types should have access only to Stack rules (no selector)
    8.2. Observability project types should have access only to Observability and Stack rules (no selector)
    8.3. Security project types should have access only to Security and Stack rules (selector shows Stack instead of Observability)

References

Depends on #214187
Closes #213061

Checklist

@umbopepato umbopepato force-pushed the 213061-alerts-boolean-filters-ui branch 2 times, most recently from 03c52ed to 1647136 Compare March 18, 2025 14:57
@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) backport:version Backport to applied version labels v9.1.0 v8.19.0 labels Mar 18, 2025
@umbopepato umbopepato force-pushed the 213061-alerts-boolean-filters-ui branch 6 times, most recently from 0ba7dbc to 9876eba Compare March 24, 2025 13:27
@umbopepato umbopepato force-pushed the 213061-alerts-boolean-filters-ui branch from 9876eba to 9982fb6 Compare March 26, 2025 13:56
@umbopepato umbopepato marked this pull request as ready for review March 26, 2025 13:57
@umbopepato umbopepato requested a review from a team as a code owner March 26, 2025 13:57
@elasticmachine
Copy link
Contributor

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

isDisabled?: boolean;
}

const DEFAULT_VALUE: AlertsFiltersExpression = {
Copy link
Member Author

Choose a reason for hiding this comment

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

This ensures that the form is initialized with an initially empty "Filter by" selector

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this comment here could be a comment in code for future us

@umbopepato umbopepato force-pushed the 213061-alerts-boolean-filters-ui branch from 2b3bc5c to 1d8fca4 Compare March 27, 2025 11:21
Copy link
Contributor

@js-jankisalvi js-jankisalvi left a comment

Choose a reason for hiding this comment

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

Great work! looks really good 🎉
Could you please add an integration test or functional test to check different roles and users to verify solutions and rule types privileges?

I have a user with `security` and `stack rules` privileges. However the solution shows `observability`. Shouldn't it be security and stack like serverless?
security_and_stack.mov
security_and_stack_permissions.mov

@umbopepato
Copy link
Member Author

Great work! looks really good 🎉

Thanks for taking a look Janki! 😊

Could you please add an integration test or functional test to check different roles and users to verify solutions and rule types privileges?

I was hoping to test the complete creation flow with the Dashboard panel as well 🙂

I have a user with security and stack rules privileges. However the solution shows observability. Shouldn't it be security and stack like serverless?

Yes, that's normal since in non-serverless envs when enabling the Stack rules privilege you also get access to multi-consumer rule types, one of which is categorized under observability. That shouldn't be a problem since it's just a label we show, but it includes both solutions. That is to say: the privileges of the users are always honored

@umbopepato umbopepato removed Team:Fleet Team label for Observability Data Collection Fleet team Team:Obs AI Assistant Observability AI Assistant labels Apr 14, 2025
@umbopepato umbopepato force-pushed the 213061-alerts-boolean-filters-ui branch from 745bcea to 8786ed0 Compare April 14, 2025 12:39
@jcger jcger self-requested a review April 15, 2025 13:57
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 and with addressing my comments!

export const getRuleTypeIdsForSolution = (
ruleTypes: InternalRuleType[],
solution: RuleTypeSolution,
includeStackInObservability = true
Copy link
Member

Choose a reason for hiding this comment

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

nit: Do not forget to remove this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done ✅

});

it.each([null, undefined])('should return false for %s items', (filter) => {
expect(isFilter(filter as Parameters<typeof isFilter>[0])).toBeFalsy();
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
expect(isFilter(filter as Parameters<typeof isFilter>[0])).toBeFalsy();
// @ts-expect-error: testing empty values
expect(isFilter(filter)).toBeFalsy();

Copy link
Member Author

Choose a reason for hiding this comment

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

Done ✅

return null;
}
const FilterComponent = alertsFiltersMetadata[type].component as AlertsFilterComponentType<T>;
return <FilterComponent value={value} onChange={onValueChange} isDisabled={isDisabled} />;
Copy link
Member

Choose a reason for hiding this comment

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

I was referring to const filter = useMemo(() => {. Any idea on that?

Comment on lines +90 to +97
if (options.length < 2) {
if (options.length === 1) {
// Select the only available solution and
// don't show the selector
onSolutionChange(options[0].value);
}
return null;
}
Copy link
Member

Choose a reason for hiding this comment

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

A pseudo example of how it can be done without any useEffects or call of onSolutionChange.

// top-level component
const { data: ruleTypes, isLoading, isError } = useGetInternalRuleTypesQuery({ http });

if (isLoading) {
   return null;
}

return <AlertsFilterFormWraper ruleTypes={ruleTypes}> // name tbd


// AlertsFilterFormWraper
// ruleTypes always available as the component will render after the fetch
const AlertsFilterFormWraper = ({ ruleTypes }) => {

const availableSolutions = useMemo(() => getAvailableSolutions(ruleTypes), [ruleTypes]);

const [selectedSolution, setSelectedSolution] = useState(availableSolutions.length === 1 ? availableSolutions[0].value : undefined) // or whatever default we want.

availableSolutions.length > 1 && <AlertsSolutionSelector availableSolutions={availableSolutions} selectedSolution={selectedSolution} onSolutionChange={setSolution}>

}

It is very similar to what you have in the sandbox with some tweaks. We can do it on the final PR.

@umbopepato umbopepato requested a review from a team as a code owner April 17, 2025 08:35
Copy link
Member

@azasypkin azasypkin left a comment

Choose a reason for hiding this comment

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

Changes in package.json LGTM

@umbopepato umbopepato enabled auto-merge (squash) April 17, 2025 12:16
@umbopepato umbopepato merged commit c44efc5 into elastic:main Apr 17, 2025
10 checks passed
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.19

https://github.com/elastic/kibana/actions/runs/14517822494

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

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.4MB 1.4MB +40.0B
Unknown metric groups

ESLint disabled line counts

id before after diff
@kbn/response-ops-alerts-filters-form - 1 +1

Total ESLint disabled count

id before after diff
@kbn/response-ops-alerts-filters-form - 1 +1

History

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.19 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 214982

Questions ?

Please refer to the Backport tool documentation

@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Apr 21, 2025
@kibanamachine
Copy link
Contributor

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

davismcphee pushed a commit to davismcphee/kibana that referenced this pull request Apr 22, 2025
## Summary

Implements the alerts filters form that will be used to pre-filter the
alerts table embeddable.

<img width="1004" alt="image"
src="https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af"
/>

> [!NOTE]
> I'm using the terminology "form" to distinguish this from the alert
filter _controls_ or other type of more KQL-bar-like filters. Other
alternatives that came to mind were `alerts-boolean-filters-...` or
`alerts-filters-builder`.

<details>
<summary>

## Implementation details

</summary>

### Filters expression state

I opted for a tree state representation of the form's boolean expression
to accommodate potential future requirements such as more complex
boolean expressions (negation, parenthesized subexpressions to manually
control operators precedence):

```ts
{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}
```

This state is saved in the embeddable panel state and represents the
editor form. The embeddable alerts table wrapper component will then
transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent
flattened state is used:

```ts
[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]
```

### Filters model

Each filter is described by an `AlertsFilterMetadata<T>` object, where
`T` is the type of the filter value:

```tsx
export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};
```

</details>

## Verification steps

1. Run Kibana with examples (`yarn start --run-examples`)
2. Create rules in different solutions with tags
3. Navigate to `/app/triggersActionsUiExample/alerts_filters_form`
4. Check that the solution selector options are coherent with the rule
types the user can access
5. Select a solution
6. Build filters expressions, checking that the rule tags and rule types
are coherent with the solution selection and the rules created
previously
7. Repeat steps 3-6 with different roles:
7.1. having access to rule types from just one solution (in this case
the solution selector shouldn't appear at all),
7.2. having access just to Observability and Stack but not Security (in
this case the solution selector shouldn't appear at all),
8. Repeat steps 3-6 in the three serverless project types:
    ```shell
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    ```
(If the authentication fails when switching between project types, use a
clean session)
8.1. ES project types should have access only to Stack rules (no
selector)
8.2. Observability project types should have access only to
Observability and Stack rules (no selector)
8.3. Security project types should have access only to Security and
Stack rules (selector shows Stack instead of Observability)

## References

Depends on elastic#214187
Closes elastic#213061

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <xristosnasikas@gmail.com>
@umbopepato
Copy link
Member Author

💚 All backports created successfully

Status Branch Result
8.19

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

umbopepato added a commit to umbopepato/kibana that referenced this pull request Apr 22, 2025
## Summary

Implements the alerts filters form that will be used to pre-filter the
alerts table embeddable.

<img width="1004" alt="image"
src="https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af"
/>

> [!NOTE]
> I'm using the terminology "form" to distinguish this from the alert
filter _controls_ or other type of more KQL-bar-like filters. Other
alternatives that came to mind were `alerts-boolean-filters-...` or
`alerts-filters-builder`.

<details>
<summary>

## Implementation details

</summary>

### Filters expression state

I opted for a tree state representation of the form's boolean expression
to accommodate potential future requirements such as more complex
boolean expressions (negation, parenthesized subexpressions to manually
control operators precedence):

```ts
{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}
```

This state is saved in the embeddable panel state and represents the
editor form. The embeddable alerts table wrapper component will then
transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent
flattened state is used:

```ts
[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]
```

### Filters model

Each filter is described by an `AlertsFilterMetadata<T>` object, where
`T` is the type of the filter value:

```tsx
export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};
```

</details>

## Verification steps

1. Run Kibana with examples (`yarn start --run-examples`)
2. Create rules in different solutions with tags
3. Navigate to `/app/triggersActionsUiExample/alerts_filters_form`
4. Check that the solution selector options are coherent with the rule
types the user can access
5. Select a solution
6. Build filters expressions, checking that the rule tags and rule types
are coherent with the solution selection and the rules created
previously
7. Repeat steps 3-6 with different roles:
7.1. having access to rule types from just one solution (in this case
the solution selector shouldn't appear at all),
7.2. having access just to Observability and Stack but not Security (in
this case the solution selector shouldn't appear at all),
8. Repeat steps 3-6 in the three serverless project types:
    ```shell
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    ```
(If the authentication fails when switching between project types, use a
clean session)
8.1. ES project types should have access only to Stack rules (no
selector)
8.2. Observability project types should have access only to
Observability and Stack rules (no selector)
8.3. Security project types should have access only to Security and
Stack rules (selector shows Stack instead of Observability)

## References

Depends on elastic#214187
Closes elastic#213061

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <xristosnasikas@gmail.com>
(cherry picked from commit c44efc5)

# Conflicts:
#	x-pack/examples/triggers_actions_ui_example/public/application.tsx
umbopepato added a commit that referenced this pull request Apr 22, 2025
…218759)

# Backport

This will backport the following commits from `main` to `8.19`:
- [[ResponseOps][Alerts] Implement alerts filters form
(#214982)](#214982)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Umberto
Pepato","email":"umbopepato@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-04-17T14:18:24Z","message":"[ResponseOps][Alerts]
Implement alerts filters form (#214982)\n\n## Summary\n\nImplements the
alerts filters form that will be used to pre-filter the\nalerts table
embeddable.\n\n<img width=\"1004\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af\"\n/>\n\n>
[!NOTE]\n> I'm using the terminology \"form\" to distinguish this from
the alert\nfilter _controls_ or other type of more KQL-bar-like filters.
Other\nalternatives that came to mind were `alerts-boolean-filters-...`
or\n`alerts-filters-builder`.\n\n<details>\n<summary>\n\n##
Implementation details\n\n</summary>\n\n### Filters expression
state\n\nI opted for a tree state representation of the form's boolean
expression\nto accommodate potential future requirements such as more
complex\nboolean expressions (negation, parenthesized subexpressions to
manually\ncontrol operators precedence):\n\n```ts\n{\n operator: 'or',\n
operands: [\n {\n operator: 'or',\n operands: [\n { type: 'ruleTags',
value: ['tag-1'] },\n { type: 'ruleTags', value: ['tag-2'] },\n {\n
operator: 'and',\n operands: [{ type: 'ruleTypes', value: ['type-1'] },
{ type: 'ruleTypes', value: ['type-2'] }],\n },\n ],\n },\n { type:
'ruleTags', value: ['tag-3'] },\n ],\n}\n```\n\nThis state is saved in
the embeddable panel state and represents the\neditor form. The
embeddable alerts table wrapper component will then\ntransform this to
an actual ES query.\n\nTo simplify interactions inside the form, an
intermediate equivalent\nflattened state is used:\n\n```ts\n[\n {
filter: { type: 'ruleTags', value: ['tag-1'] } },\n { operator: 'or'
},\n { filter: { type: 'ruleTags', value: ['tag-2'] } },\n { operator:
'or' },\n { filter: { type: 'ruleTypes', value: ['type-1'] }},\n {
operator: 'and' },\n { filter: { type: 'ruleTypes', value: ['type-2'] }
},\n { operator: 'or' },\n { filter: { type: 'ruleTags', value:
['tag-3'] } },\n]\n```\n\n### Filters model\n\nEach filter is described
by an `AlertsFilterMetadata<T>` object, where\n`T` is the type of the
filter value:\n\n```tsx\nexport const filterMetadata:
AlertsFilterMetadata<string[]> = {\n id: 'ruleTags',\n displayName:
RULE_TAGS_FILTER_LABEL,\n component: AlertsFilterByRuleTags,\n //
Filter-specific empty check\n isEmpty: (value?: string[]) =>
!value?.length,\n // Conversion to ES query DSL\n toEsQuery: (value:
string[]) => {\n return {\n terms: {\n [ALERT_RULE_TAGS]: value,\n },\n
};\n },\n};\n```\n\n</details>\n\n## Verification steps\n\n1. Run Kibana
with examples (`yarn start --run-examples`)\n2. Create rules in
different solutions with tags\n3. Navigate to
`/app/triggersActionsUiExample/alerts_filters_form`\n4. Check that the
solution selector options are coherent with the rule\ntypes the user can
access\n5. Select a solution\n6. Build filters expressions, checking
that the rule tags and rule types\nare coherent with the solution
selection and the rules created\npreviously\n7. Repeat steps 3-6 with
different roles:\n7.1. having access to rule types from just one
solution (in this case\nthe solution selector shouldn't appear at
all),\n7.2. having access just to Observability and Stack but not
Security (in\nthis case the solution selector shouldn't appear at
all),\n8. Repeat steps 3-6 in the three serverless project types:\n
```shell\n $ yarn es serverless —ssl --projectType <es|oblt|security>\n
$ yarn serverless-<es|oblt|security> --ssl --run-examples\n ```\n(If the
authentication fails when switching between project types, use a\nclean
session)\n8.1. ES project types should have access only to Stack rules
(no\nselector)\n8.2. Observability project types should have access only
to\nObservability and Stack rules (no selector)\n8.3. Security project
types should have access only to Security and\nStack rules (selector
shows Stack instead of Observability)\n\n## References\n\nDepends on
#214187\nCloses #213061\n\n### Checklist\n\n- [x] Any text added follows
[EUI's
writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\nsentence case text and includes
[i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n-
[x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Christos Nasikas
<xristosnasikas@gmail.com>","sha":"c44efc52f62f2bb80c8cb8c288cfb40fc3164344","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:ResponseOps","backport
missing","backport:version","v9.1.0","v8.19.0"],"title":"[ResponseOps][Alerts]
Implement alerts filters
form","number":214982,"url":"https://github.com/elastic/kibana/pull/214982","mergeCommit":{"message":"[ResponseOps][Alerts]
Implement alerts filters form (#214982)\n\n## Summary\n\nImplements the
alerts filters form that will be used to pre-filter the\nalerts table
embeddable.\n\n<img width=\"1004\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af\"\n/>\n\n>
[!NOTE]\n> I'm using the terminology \"form\" to distinguish this from
the alert\nfilter _controls_ or other type of more KQL-bar-like filters.
Other\nalternatives that came to mind were `alerts-boolean-filters-...`
or\n`alerts-filters-builder`.\n\n<details>\n<summary>\n\n##
Implementation details\n\n</summary>\n\n### Filters expression
state\n\nI opted for a tree state representation of the form's boolean
expression\nto accommodate potential future requirements such as more
complex\nboolean expressions (negation, parenthesized subexpressions to
manually\ncontrol operators precedence):\n\n```ts\n{\n operator: 'or',\n
operands: [\n {\n operator: 'or',\n operands: [\n { type: 'ruleTags',
value: ['tag-1'] },\n { type: 'ruleTags', value: ['tag-2'] },\n {\n
operator: 'and',\n operands: [{ type: 'ruleTypes', value: ['type-1'] },
{ type: 'ruleTypes', value: ['type-2'] }],\n },\n ],\n },\n { type:
'ruleTags', value: ['tag-3'] },\n ],\n}\n```\n\nThis state is saved in
the embeddable panel state and represents the\neditor form. The
embeddable alerts table wrapper component will then\ntransform this to
an actual ES query.\n\nTo simplify interactions inside the form, an
intermediate equivalent\nflattened state is used:\n\n```ts\n[\n {
filter: { type: 'ruleTags', value: ['tag-1'] } },\n { operator: 'or'
},\n { filter: { type: 'ruleTags', value: ['tag-2'] } },\n { operator:
'or' },\n { filter: { type: 'ruleTypes', value: ['type-1'] }},\n {
operator: 'and' },\n { filter: { type: 'ruleTypes', value: ['type-2'] }
},\n { operator: 'or' },\n { filter: { type: 'ruleTags', value:
['tag-3'] } },\n]\n```\n\n### Filters model\n\nEach filter is described
by an `AlertsFilterMetadata<T>` object, where\n`T` is the type of the
filter value:\n\n```tsx\nexport const filterMetadata:
AlertsFilterMetadata<string[]> = {\n id: 'ruleTags',\n displayName:
RULE_TAGS_FILTER_LABEL,\n component: AlertsFilterByRuleTags,\n //
Filter-specific empty check\n isEmpty: (value?: string[]) =>
!value?.length,\n // Conversion to ES query DSL\n toEsQuery: (value:
string[]) => {\n return {\n terms: {\n [ALERT_RULE_TAGS]: value,\n },\n
};\n },\n};\n```\n\n</details>\n\n## Verification steps\n\n1. Run Kibana
with examples (`yarn start --run-examples`)\n2. Create rules in
different solutions with tags\n3. Navigate to
`/app/triggersActionsUiExample/alerts_filters_form`\n4. Check that the
solution selector options are coherent with the rule\ntypes the user can
access\n5. Select a solution\n6. Build filters expressions, checking
that the rule tags and rule types\nare coherent with the solution
selection and the rules created\npreviously\n7. Repeat steps 3-6 with
different roles:\n7.1. having access to rule types from just one
solution (in this case\nthe solution selector shouldn't appear at
all),\n7.2. having access just to Observability and Stack but not
Security (in\nthis case the solution selector shouldn't appear at
all),\n8. Repeat steps 3-6 in the three serverless project types:\n
```shell\n $ yarn es serverless —ssl --projectType <es|oblt|security>\n
$ yarn serverless-<es|oblt|security> --ssl --run-examples\n ```\n(If the
authentication fails when switching between project types, use a\nclean
session)\n8.1. ES project types should have access only to Stack rules
(no\nselector)\n8.2. Observability project types should have access only
to\nObservability and Stack rules (no selector)\n8.3. Security project
types should have access only to Security and\nStack rules (selector
shows Stack instead of Observability)\n\n## References\n\nDepends on
#214187\nCloses #213061\n\n### Checklist\n\n- [x] Any text added follows
[EUI's
writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\nsentence case text and includes
[i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n-
[x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Christos Nasikas
<xristosnasikas@gmail.com>","sha":"c44efc52f62f2bb80c8cb8c288cfb40fc3164344"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/214982","number":214982,"mergeCommit":{"message":"[ResponseOps][Alerts]
Implement alerts filters form (#214982)\n\n## Summary\n\nImplements the
alerts filters form that will be used to pre-filter the\nalerts table
embeddable.\n\n<img width=\"1004\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af\"\n/>\n\n>
[!NOTE]\n> I'm using the terminology \"form\" to distinguish this from
the alert\nfilter _controls_ or other type of more KQL-bar-like filters.
Other\nalternatives that came to mind were `alerts-boolean-filters-...`
or\n`alerts-filters-builder`.\n\n<details>\n<summary>\n\n##
Implementation details\n\n</summary>\n\n### Filters expression
state\n\nI opted for a tree state representation of the form's boolean
expression\nto accommodate potential future requirements such as more
complex\nboolean expressions (negation, parenthesized subexpressions to
manually\ncontrol operators precedence):\n\n```ts\n{\n operator: 'or',\n
operands: [\n {\n operator: 'or',\n operands: [\n { type: 'ruleTags',
value: ['tag-1'] },\n { type: 'ruleTags', value: ['tag-2'] },\n {\n
operator: 'and',\n operands: [{ type: 'ruleTypes', value: ['type-1'] },
{ type: 'ruleTypes', value: ['type-2'] }],\n },\n ],\n },\n { type:
'ruleTags', value: ['tag-3'] },\n ],\n}\n```\n\nThis state is saved in
the embeddable panel state and represents the\neditor form. The
embeddable alerts table wrapper component will then\ntransform this to
an actual ES query.\n\nTo simplify interactions inside the form, an
intermediate equivalent\nflattened state is used:\n\n```ts\n[\n {
filter: { type: 'ruleTags', value: ['tag-1'] } },\n { operator: 'or'
},\n { filter: { type: 'ruleTags', value: ['tag-2'] } },\n { operator:
'or' },\n { filter: { type: 'ruleTypes', value: ['type-1'] }},\n {
operator: 'and' },\n { filter: { type: 'ruleTypes', value: ['type-2'] }
},\n { operator: 'or' },\n { filter: { type: 'ruleTags', value:
['tag-3'] } },\n]\n```\n\n### Filters model\n\nEach filter is described
by an `AlertsFilterMetadata<T>` object, where\n`T` is the type of the
filter value:\n\n```tsx\nexport const filterMetadata:
AlertsFilterMetadata<string[]> = {\n id: 'ruleTags',\n displayName:
RULE_TAGS_FILTER_LABEL,\n component: AlertsFilterByRuleTags,\n //
Filter-specific empty check\n isEmpty: (value?: string[]) =>
!value?.length,\n // Conversion to ES query DSL\n toEsQuery: (value:
string[]) => {\n return {\n terms: {\n [ALERT_RULE_TAGS]: value,\n },\n
};\n },\n};\n```\n\n</details>\n\n## Verification steps\n\n1. Run Kibana
with examples (`yarn start --run-examples`)\n2. Create rules in
different solutions with tags\n3. Navigate to
`/app/triggersActionsUiExample/alerts_filters_form`\n4. Check that the
solution selector options are coherent with the rule\ntypes the user can
access\n5. Select a solution\n6. Build filters expressions, checking
that the rule tags and rule types\nare coherent with the solution
selection and the rules created\npreviously\n7. Repeat steps 3-6 with
different roles:\n7.1. having access to rule types from just one
solution (in this case\nthe solution selector shouldn't appear at
all),\n7.2. having access just to Observability and Stack but not
Security (in\nthis case the solution selector shouldn't appear at
all),\n8. Repeat steps 3-6 in the three serverless project types:\n
```shell\n $ yarn es serverless —ssl --projectType <es|oblt|security>\n
$ yarn serverless-<es|oblt|security> --ssl --run-examples\n ```\n(If the
authentication fails when switching between project types, use a\nclean
session)\n8.1. ES project types should have access only to Stack rules
(no\nselector)\n8.2. Observability project types should have access only
to\nObservability and Stack rules (no selector)\n8.3. Security project
types should have access only to Security and\nStack rules (selector
shows Stack instead of Observability)\n\n## References\n\nDepends on
#214187\nCloses #213061\n\n### Checklist\n\n- [x] Any text added follows
[EUI's
writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\nsentence case text and includes
[i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n-
[x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Christos Nasikas
<xristosnasikas@gmail.com>","sha":"c44efc52f62f2bb80c8cb8c288cfb40fc3164344"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Apr 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:version Backport to applied version labels 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.19.0 v9.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ResponseOps][Alerts] Alerts boolean query filters UI
8 participants