Skip to content

[Rules] Adding actions to the rules details action menu (Part 1)#219635

Merged
baileycash-elastic merged 5 commits intoelastic:mainfrom
baileycash-elastic:rules-199421
May 1, 2025
Merged

[Rules] Adding actions to the rules details action menu (Part 1)#219635
baileycash-elastic merged 5 commits intoelastic:mainfrom
baileycash-elastic:rules-199421

Conversation

@baileycash-elastic
Copy link
Contributor

@baileycash-elastic baileycash-elastic commented Apr 29, 2025

Summary

Partially implements #199421

This PR adds snooze and enable/disable options to the action menu of the rule details header action menu.

Note: A second PR with the other 2 required actions and a slight redesign is here

Screenshot 2025-04-29 at 4 37 45 PM
Screenshot 2025-04-29 at 4 37 37 PM

@baileycash-elastic baileycash-elastic added release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// Team:actionable-obs Formerly "obs-ux-management", responsible for SLO, o11y alerting, significant events, & synthetics. backport:version Backport to applied version labels v9.1.0 v8.19.0 labels Apr 29, 2025
@baileycash-elastic baileycash-elastic requested review from a team as code owners April 29, 2025 20:45
@elasticmachine
Copy link
Contributor

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

@elasticmachine
Copy link
Contributor

Pinging @elastic/obs-ux-management-team (Team:obs-ux-management)

Copy link
Contributor

@justinkambic justinkambic left a comment

Choose a reason for hiding this comment

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

Functionality LGTM.

I tested this against a custom threshold rule and everything seemed to be working well! I have a bunch of opinionated comments that aren't required for merging but could make the code simpler/more testable.

Comment on lines +200 to +202
onRuleChanged={async () => {
refetch();
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
onRuleChanged={async () => {
refetch();
}}
onRuleChanged={refetch}

Comment on lines +12 to +59
export function useDisableRule() {
const {
http,
notifications: { toasts },
} = useKibana().services;

const queryClient = useQueryClient();

const disableRule = useMutation<string, string, { id: string; untrack: boolean }>(
['disableRule'],
({ id, untrack }) => {
const body = JSON.stringify({
...(untrack ? { untrack } : {}),
});
try {
return http.post(`/api/alerting/rule/${id}/_disable`, { body });
} catch (e) {
throw new Error(`Unable to parse id: ${e}`);
}
},
{
onError: (_err) => {
toasts.addDanger(
i18n.translate(
'xpack.observability.rules.disableErrorModal.errorNotification.descriptionText',
{
defaultMessage: 'Failed to disable rule',
}
)
);
},

onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['fetchRule', variables.id], exact: false });
toasts.addSuccess(
i18n.translate(
'xpack.observability.rules.disableConfirmationModal.successNotification.descriptionText',
{
defaultMessage: 'Disabled rule',
}
)
);
},
}
);

return disableRule;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is an opinionated comment, but I think we have a good amount of repetition between use_disable_rule and use_enable_rule that we can abstract away. If we were to combine these two files and extract the unique values, we'd end up with a hook that requires fewer tests and allows enable/disable procedures to share common code.

Here's an example re-implementation I made that works fine with your patch:

// common code between the two hooks
function useRuleMutation({
  mutationKey,
  apiEndpoint,
  successMessage,
  errorMessage,
}: {
  mutationKey: string;
  apiEndpoint: (id: string) => string;
  successMessage: string;
  errorMessage: string;
}) {
  const {
    http,
    notifications: { toasts },
  } = useKibana().services;

  const queryClient = useQueryClient();

  return useMutation<string, string, { id: string; untrack?: boolean }>(
    [mutationKey],
    ({ id, untrack }) => {
      const body = untrack ? JSON.stringify({ untrack }) : undefined;
      try {
        return http.post(apiEndpoint(id), { body });
      } catch (e) {
        throw new Error(`Unable to parse id: ${e}`);
      }
    },
    {
      onError: () => {
        toasts.addDanger(errorMessage);
      },
      onSuccess: (_, variables) => {
        queryClient.invalidateQueries({ queryKey: ['fetchRule', variables.id], exact: false });
        toasts.addSuccess(successMessage);
      },
    }
  );
}

// implementation details provided for enable/disable, core functionality is shared
export function useEnableRule() {
  return {
    enableRule: useRuleMutation({
      mutationKey: 'enableRule',
      apiEndpoint: (id) => `/api/alerting/rule/${id}/_enable`,
      successMessage: i18n.translate(
        'xpack.observability.rules.enableConfirmationModal.successNotification.descriptionText',
        {
          defaultMessage: 'Enabled rule',
        }
      ),
      errorMessage: i18n.translate(
        'xpack.observability.rules.enableErrorModal.errorNotification.descriptionText',
        {
          defaultMessage: 'Failed to enable rule',
        }
      ),
    }),
    disableRule: useRuleMutation({
      mutationKey: 'disableRule',
      apiEndpoint: (id) => `/api/alerting/rule/${id}/_disable`,
      successMessage: i18n.translate(
        'xpack.observability.rules.disableConfirmationModal.successNotification.descriptionText',
        {
          defaultMessage: 'Disabled rule',
        }
      ),
      errorMessage: i18n.translate(
        'xpack.observability.rules.disableErrorModal.errorNotification.descriptionText',
        {
          defaultMessage: 'Failed to disable rule',
        }
      ),
    }),
  };
}

This increases the parameter footprint for the internal hook, but makes it so that the functionality of "request query and issue appropriate toast on response" is separated from the actual enable/disable details. Then the implementation in the component side looks like:

  const {
    enableRule: { mutateAsync: enableRule },
    disableRule: { mutateAsync: disableRule },
  } = useEnableRule();

We could also simply return the mutateAsync and rename it to simplify the destructuring in the component.

I wouldn't say this is required for merging but it follows DRY principles a bit more.

Comment on lines +512 to +514
getUntrackModal: (props: UntrackAlertsModalProps) => {
return getUntrackModalLazy(props);
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
getUntrackModal: (props: UntrackAlertsModalProps) => {
return getUntrackModalLazy(props);
},
getUntrackModal: UntrackAlertsModal,

I don't know why they have this pattern here, perhaps someone from the maintaining team can respond, but this works for me locally. Probably best to just keep it this way as they have others around it that follow the same pattern.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is a long followed practice of this plugin, mostly to allow dynamic import for this components- load them when they are rendered for the first time.

Comment on lines +54 to +60
const onDisableModalClose = () => {
setIsUntrackAlertsModalOpen(false);
};

const onDisableModalOpen = () => {
setIsUntrackAlertsModalOpen(true);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const onDisableModalClose = () => {
setIsUntrackAlertsModalOpen(false);
};
const onDisableModalOpen = () => {
setIsUntrackAlertsModalOpen(true);
};

Another opinionated commented; I don't think declaring these functions is necessary.

Comment on lines +74 to +88
const handleEnableRule = () => {
setIsRuleEditPopoverOpen(false);
enableRule({
id: ruleId,
});
};

const handleDisableRule = (untrack: boolean) => {
setIsRuleEditPopoverOpen(false);
onDisableModalClose();
disableRule({
id: ruleId,
untrack,
});
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Another opinionated comment.

Suggested change
const handleEnableRule = () => {
setIsRuleEditPopoverOpen(false);
enableRule({
id: ruleId,
});
};
const handleDisableRule = (untrack: boolean) => {
setIsRuleEditPopoverOpen(false);
onDisableModalClose();
disableRule({
id: ruleId,
untrack,
});
};

Regarding handleEditRule, handleRemoveRule, handleEnableRule, handleDisableRule, these functions are only referenced once, further down where they're supplied as handlers to some components. Why not just put them there and leave the functions anonymous? The code will be closer to where it's called and will remove the mental load of the reader to go back up and figure out what each handle function is doing.

I realize that the first two handle functions were already there but I think this will simplify the component.

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.

These actions are added only to Observability > Rule details page. Response ops changes lgtm 👍

Comment on lines +512 to +514
getUntrackModal: (props: UntrackAlertsModalProps) => {
return getUntrackModalLazy(props);
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is a long followed practice of this plugin, mostly to allow dynamic import for this components- load them when they are rendered for the first time.

@prodsecmachine
Copy link
Collaborator

prodsecmachine commented May 1, 2025

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

license/snyk check is complete. No issues have been found. (View Details)

@baileycash-elastic baileycash-elastic merged commit 1ee2f62 into elastic:main May 1, 2025
8 of 10 checks passed
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.19

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

kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request May 1, 2025
…stic#219635)

## Summary

Partially implements elastic#199421

This PR adds snooze and enable/disable options to the action menu of the
rule details header action menu.

Note: A second PR with the other 2 required actions and a slight
redesign is [here](elastic#219790)

![Screenshot 2025-04-29 at 4 37
45 PM](https://github.com/user-attachments/assets/e0ba273d-56f0-433f-b1b0-bb2842ed634b)
![Screenshot 2025-04-29 at 4 37
37 PM](https://github.com/user-attachments/assets/fa6d70e9-3582-412f-aaa9-e0fb8c219d10)

(cherry picked from commit 1ee2f62)
@kibanamachine
Copy link
Contributor

💚 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

@elasticmachine
Copy link
Contributor

elasticmachine commented May 1, 2025

💔 Build Failed

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #82 / apis guided onboarding GET /internal/guided_onboarding/guides returns all created guides (active and inactive)
  • [job] [logs] FTR Configs #56 / ObservabilityApp Observability Rule Details page User permissions "after all" hook for "should not show the actions button if user has no permissions"
  • [job] [logs] FTR Configs #56 / ObservabilityApp Observability Rule Details page User permissions "after all" hook for "should not show the actions button if user has no permissions"
  • [job] [logs] FTR Configs #56 / ObservabilityApp Observability Rule Details page User permissions should show the rule edit and delete button if user has permissions
  • [job] [logs] FTR Configs #56 / ObservabilityApp Observability Rule Details page User permissions should show the rule edit and delete button if user has permissions

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
observability 1277 1281 +4
triggersActionsUi 731 732 +1
total +5

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
triggersActionsUi 529 533 +4

Async chunks

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

id before after diff
observability 1.3MB 1.3MB +4.2KB
triggersActionsUi 1.4MB 1.4MB -3.0KB
total +1.2KB

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 36 37 +1

Page load bundle

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

id before after diff
observability 94.3KB 94.3KB -1.0B
triggersActionsUi 100.3KB 102.0KB +1.7KB
total +1.7KB
Unknown metric groups

API count

id before after diff
triggersActionsUi 535 539 +4

History

kibanamachine added a commit that referenced this pull request May 1, 2025
…1) (#219635) (#219848)

# Backport

This will backport the following commits from `main` to `8.19`:
- [[Rules] Adding actions to the rules details action menu (Part 1)
(#219635)](#219635)

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

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

<!--BACKPORT [{"author":{"name":"Bailey
Cash","email":"bailey.cash@elastic.co"},"sourceCommit":{"committedDate":"2025-05-01T13:51:33Z","message":"[Rules]
Adding actions to the rules details action menu (Part 1) (#219635)\n\n##
Summary\n\nPartially implements #199421\n\nThis PR adds snooze and
enable/disable options to the action menu of the\nrule details header
action menu.\n\nNote: A second PR with the other 2 required actions and
a slight\nredesign is
[here](https://github.com/elastic/kibana/pull/219790)\n\n\n![Screenshot
2025-04-29 at 4
37\n45 PM](https://github.com/user-attachments/assets/e0ba273d-56f0-433f-b1b0-bb2842ed634b)\n![Screenshot
2025-04-29 at 4
37\n37 PM](https://github.com/user-attachments/assets/fa6d70e9-3582-412f-aaa9-e0fb8c219d10)","sha":"1ee2f62791b413e656aae31bb5d55f62630583d9","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:ResponseOps","Team:obs-ux-management","backport:version","v9.1.0","v8.19.0"],"title":"[Rules]
Adding actions to the rules details action menu (Part
1)","number":219635,"url":"https://github.com/elastic/kibana/pull/219635","mergeCommit":{"message":"[Rules]
Adding actions to the rules details action menu (Part 1) (#219635)\n\n##
Summary\n\nPartially implements #199421\n\nThis PR adds snooze and
enable/disable options to the action menu of the\nrule details header
action menu.\n\nNote: A second PR with the other 2 required actions and
a slight\nredesign is
[here](https://github.com/elastic/kibana/pull/219790)\n\n\n![Screenshot
2025-04-29 at 4
37\n45 PM](https://github.com/user-attachments/assets/e0ba273d-56f0-433f-b1b0-bb2842ed634b)\n![Screenshot
2025-04-29 at 4
37\n37 PM](https://github.com/user-attachments/assets/fa6d70e9-3582-412f-aaa9-e0fb8c219d10)","sha":"1ee2f62791b413e656aae31bb5d55f62630583d9"}},"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/219635","number":219635,"mergeCommit":{"message":"[Rules]
Adding actions to the rules details action menu (Part 1) (#219635)\n\n##
Summary\n\nPartially implements #199421\n\nThis PR adds snooze and
enable/disable options to the action menu of the\nrule details header
action menu.\n\nNote: A second PR with the other 2 required actions and
a slight\nredesign is
[here](https://github.com/elastic/kibana/pull/219790)\n\n\n![Screenshot
2025-04-29 at 4
37\n45 PM](https://github.com/user-attachments/assets/e0ba273d-56f0-433f-b1b0-bb2842ed634b)\n![Screenshot
2025-04-29 at 4
37\n37 PM](https://github.com/user-attachments/assets/fa6d70e9-3582-412f-aaa9-e0fb8c219d10)","sha":"1ee2f62791b413e656aae31bb5d55f62630583d9"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Bailey Cash <bailey.cash@elastic.co>
akowalska622 pushed a commit to akowalska622/kibana that referenced this pull request May 29, 2025
…stic#219635)

## Summary

Partially implements elastic#199421

This PR adds snooze and enable/disable options to the action menu of the
rule details header action menu.

Note: A second PR with the other 2 required actions and a slight
redesign is [here](elastic#219790)


![Screenshot 2025-04-29 at 4 37
45 PM](https://github.com/user-attachments/assets/e0ba273d-56f0-433f-b1b0-bb2842ed634b)
![Screenshot 2025-04-29 at 4 37
37 PM](https://github.com/user-attachments/assets/fa6d70e9-3582-412f-aaa9-e0fb8c219d10)
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:actionable-obs Formerly "obs-ux-management", responsible for SLO, o11y alerting, significant events, & synthetics. Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// v8.19.0 v9.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants