Skip to content

Commit

Permalink
[ResponseOps][Alert Summaries] Add default summary message (#148749)
Browse files Browse the repository at this point in the history
Resolves #148537

## Summary

Added the capability for rule types to provide a default message for
summary actions. This default message gets pre-populated within the rule
action form whenever a user adds an action to a rule.

Also added a default framework summary message.

### 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/packages/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


### To verify

- Create a rule and add an action and select `notify on custom action
intervals`
- Verify that the default message is populated
```
The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} alerts.
```
  • Loading branch information
doakalexi authored Feb 2, 2023
1 parent 2b82cb7 commit f90bf81
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 113 deletions.
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ pageLoadAssetSize:
threatIntelligence: 44299
timelines: 327300
transform: 41007
triggersActionsUi: 120000
triggersActionsUi: 135613
uiActions: 35121
uiActionsEnhanced: 38494
unifiedFieldList: 65500
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ export const recoveredActionGroupMessage = i18n.translate(
}
);

export const summaryMessage = i18n.translate(
'xpack.triggersActionsUI.sections.actionForm.SummaryMessage',
{
defaultMessage:
'The system has detected \\{\\{alerts.new.count\\}\\} new, \\{\\{alerts.ongoing.count\\}\\} ongoing, and \\{\\{alerts.recovered.count\\}\\} alerts.',
}
);

export { TIME_UNITS } from './time_units';
export enum SORT_ORDERS {
ASCENDING = 'asc',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,78 @@ const expectedParamsTransformResult = (withBraces: boolean = false) => [
},
];

const expectedSummaryTransformResult = [
{
description: 'The configured server.publicBaseUrl value or empty string if not configured.',
name: 'kibanaBaseUrl',
},
{
description: 'The date the rule scheduled the action.',
name: 'date',
},
{
description: 'The params of the rule.',
name: 'rule.params',
},
{
description: 'The ID of the rule.',
name: 'rule.id',
},
{
description: 'The name of the rule.',
name: 'rule.name',
},
{
description: 'The type of rule.',
name: 'rule.type',
},
{
description:
'The URL to the Stack Management rule page that generated the alert. This will be an empty string if the server.publicBaseUrl is not configured.',
name: 'rule.url',
},
{
description: 'The tags of the rule.',
name: 'rule.tags',
},
{
description: 'The space ID of the rule.',
name: 'rule.spaceId',
},
{
description: 'The count of new alerts.',
name: 'alerts.new.count',
},
{
description: 'An array of objects for new alerts.',
name: 'alerts.new.data',
},
{
description: 'The count of ongoing alerts.',
name: 'alerts.ongoing.count',
},
{
description: 'An array of objects for ongoing alerts.',
name: 'alerts.ongoing.data',
},
{
description: 'The count of recovered alerts.',
name: 'alerts.recovered.count',
},
{
description: 'An array of objects for recovered alerts.',
name: 'alerts.recovered.data',
},
{
description: 'The count of all alerts.',
name: 'alerts.all.count',
},
{
description: 'An array of objects for all alerts.',
name: 'alerts.all.data',
},
];

describe('transformActionVariables', () => {
test('should return correct variables when no state, no context, no params provided', async () => {
const alertType = getAlertType({ context: [], state: [], params: [] });
Expand Down Expand Up @@ -225,6 +297,12 @@ describe('transformActionVariables', () => {
...expectedParamsTransformResult(),
]);
});
test('should return correct variables when isAlertSummary = true', async () => {
const alertType = getAlertType({ context: [], state: [], params: [] });
expect(transformActionVariables(alertType.actionVariables, undefined, true)).toEqual(
expectedSummaryTransformResult
);
});
});

function getAlertType(actionVariables: ActionVariables): RuleType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ export type OmitMessageVariablesType = 'all' | 'keepContext';
// return a "flattened" list of action variables for an alertType
export function transformActionVariables(
actionVariables: ActionVariables,
omitMessageVariables?: OmitMessageVariablesType
omitMessageVariables?: OmitMessageVariablesType,
isSummaryAction?: boolean
): ActionVariable[] {
if (isSummaryAction) {
return getSummaryAlertActionVariables();
}

const filteredActionVariables: ActionVariables = omitMessageVariables
? omitMessageVariables === 'all'
? pick(actionVariables, REQUIRED_ACTION_VARIABLES)
Expand Down Expand Up @@ -48,6 +53,7 @@ export enum AlertProvidedActionVariables {
alertActionGroupName = 'alert.actionGroupName',
alertActionSubgroup = 'alert.actionSubgroup',
alertFlapping = 'alert.flapping',
kibanaBaseUrl = 'kibanaBaseUrl',
}

export enum LegacyAlertProvidedActionVariables {
Expand All @@ -61,66 +67,95 @@ export enum LegacyAlertProvidedActionVariables {
spaceId = 'spaceId',
}

function prefixKeys(actionVariables: ActionVariable[], prefix: string): ActionVariable[] {
return actionVariables.map((actionVariable) => {
return { ...actionVariable, name: `${prefix}${actionVariable.name}` };
});
export enum SummaryAlertProvidedActionVariables {
ruleParams = 'rule.params',
newAlertsCount = 'alerts.new.count',
newAlertsData = 'alerts.new.data',
ongoingAlertsCount = 'alerts.ongoing.count',
ongoingAlertsData = 'alerts.ongoing.data',
recoveredAlertsCount = 'alerts.recovered.count',
recoveredAlertsData = 'alerts.recovered.data',
allAlertsCount = 'alerts.all.count',
allAlertsData = 'alerts.all.data',
}

// this list should be the same as in:
// x-pack/plugins/alerting/server/task_runner/transform_action_params.ts
function getAlwaysProvidedActionVariables(): ActionVariable[] {
const result: ActionVariable[] = [];

result.push({
const AlertProvidedActionVariableDescriptions = {
[AlertProvidedActionVariables.ruleId]: {
name: AlertProvidedActionVariables.ruleId,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleIdLabel', {
defaultMessage: 'The ID of the rule.',
}),
});

result.push({
},
[AlertProvidedActionVariables.ruleName]: {
name: AlertProvidedActionVariables.ruleName,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleNameLabel', {
defaultMessage: 'The name of the rule.',
}),
});

result.push({
},
[AlertProvidedActionVariables.ruleSpaceId]: {
name: AlertProvidedActionVariables.ruleSpaceId,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleSpaceIdLabel', {
defaultMessage: 'The space ID of the rule.',
}),
});

result.push({
},
[AlertProvidedActionVariables.ruleTags]: {
name: AlertProvidedActionVariables.ruleTags,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleTagsLabel', {
defaultMessage: 'The tags of the rule.',
}),
});

result.push({
},
[AlertProvidedActionVariables.ruleType]: {
name: AlertProvidedActionVariables.ruleType,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleTypeLabel', {
defaultMessage: 'The type of rule.',
}),
});

result.push({
},
[AlertProvidedActionVariables.ruleUrl]: {
name: AlertProvidedActionVariables.ruleUrl,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleUrlLabel', {
defaultMessage:
'The URL to the Stack Management rule page that generated the alert. This will be an empty string if the server.publicBaseUrl is not configured.',
}),
});

result.push({
},
[AlertProvidedActionVariables.date]: {
name: AlertProvidedActionVariables.date,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.dateLabel', {
defaultMessage: 'The date the rule scheduled the action.',
}),
},
[AlertProvidedActionVariables.kibanaBaseUrl]: {
name: AlertProvidedActionVariables.kibanaBaseUrl,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.kibanaBaseUrlLabel', {
defaultMessage:
'The configured server.publicBaseUrl value or empty string if not configured.',
}),
},
};

function prefixKeys(actionVariables: ActionVariable[], prefix: string): ActionVariable[] {
return actionVariables.map((actionVariable) => {
return { ...actionVariable, name: `${prefix}${actionVariable.name}` };
});
}

// this list should be the same as in:
// x-pack/plugins/alerting/server/task_runner/transform_action_params.ts
function getAlwaysProvidedActionVariables(): ActionVariable[] {
const result: ActionVariable[] = [];

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleId]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleName]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleSpaceId]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleTags]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleType]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleUrl]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.date]);

result.push({
name: AlertProvidedActionVariables.alertId,
Expand Down Expand Up @@ -165,13 +200,7 @@ function getAlwaysProvidedActionVariables(): ActionVariable[] {
}),
});

result.push({
name: 'kibanaBaseUrl',
description: i18n.translate('xpack.triggersActionsUI.actionVariables.kibanaBaseUrlLabel', {
defaultMessage:
'The configured server.publicBaseUrl value or empty string if not configured.',
}),
});
result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.kibanaBaseUrl]);

result.push({
name: LegacyAlertProvidedActionVariables.alertId,
Expand Down Expand Up @@ -275,3 +304,85 @@ function getAlwaysProvidedActionVariables(): ActionVariable[] {

return result;
}
function getSummaryAlertActionVariables(): ActionVariable[] {
const result: ActionVariable[] = [];
result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.kibanaBaseUrl]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.date]);

result.push({
name: SummaryAlertProvidedActionVariables.ruleParams,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ruleParamsLabel', {
defaultMessage: 'The params of the rule.',
}),
});

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleId]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleName]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleType]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleUrl]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleTags]);

result.push(AlertProvidedActionVariableDescriptions[AlertProvidedActionVariables.ruleSpaceId]);

result.push({
name: SummaryAlertProvidedActionVariables.newAlertsCount,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.newAlertsCountLabel', {
defaultMessage: 'The count of new alerts.',
}),
});
result.push({
name: SummaryAlertProvidedActionVariables.newAlertsData,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.newAlertsDataLabel', {
defaultMessage: 'An array of objects for new alerts.',
}),
});
result.push({
name: SummaryAlertProvidedActionVariables.ongoingAlertsCount,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ongoingAlertsCountLabel', {
defaultMessage: 'The count of ongoing alerts.',
}),
});
result.push({
name: SummaryAlertProvidedActionVariables.ongoingAlertsData,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.ongoingAlertsDataLabel', {
defaultMessage: 'An array of objects for ongoing alerts.',
}),
});
result.push({
name: SummaryAlertProvidedActionVariables.recoveredAlertsCount,
description: i18n.translate(
'xpack.triggersActionsUI.actionVariables.recoveredAlertsCountLabel',
{
defaultMessage: 'The count of recovered alerts.',
}
),
});
result.push({
name: SummaryAlertProvidedActionVariables.recoveredAlertsData,
description: i18n.translate(
'xpack.triggersActionsUI.actionVariables.recoveredAlertsDataLabel',
{
defaultMessage: 'An array of objects for recovered alerts.',
}
),
});
result.push({
name: SummaryAlertProvidedActionVariables.allAlertsCount,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.allAlertsCountLabel', {
defaultMessage: 'The count of all alerts.',
}),
});
result.push({
name: SummaryAlertProvidedActionVariables.allAlertsData,
description: i18n.translate('xpack.triggersActionsUI.actionVariables.allAlertsDataLabel', {
defaultMessage: 'An array of objects for all alerts.',
}),
});

return result;
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export interface ActionAccordionFormProps {
isActionGroupDisabledForActionType?: (actionGroupId: string, actionTypeId: string) => boolean;
hideActionHeader?: boolean;
hideNotifyWhen?: boolean;
defaultSummaryMessage?: string;
hasSummary?: boolean;
minimumThrottleInterval?: [number | undefined, string];
}
Expand Down Expand Up @@ -97,6 +98,7 @@ export const ActionForm = ({
isActionGroupDisabledForActionType,
hideActionHeader,
hideNotifyWhen,
defaultSummaryMessage,
hasSummary,
minimumThrottleInterval,
}: ActionAccordionFormProps) => {
Expand Down Expand Up @@ -401,6 +403,7 @@ export const ActionForm = ({
setActiveActionItem(undefined);
}}
hideNotifyWhen={hideNotifyWhen}
defaultSummaryMessage={defaultSummaryMessage}
hasSummary={hasSummary}
minimumThrottleInterval={minimumThrottleInterval}
/>
Expand Down
Loading

0 comments on commit f90bf81

Please sign in to comment.