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

Rename alert status OK to Recovered and fix some UX issues around disabling a rule while being in an error state #98135

Merged
merged 11 commits into from
May 13, 2021
Binary file modified docs/user/alerting/images/rule-details-alerts-inactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions x-pack/plugins/alerting/server/alerts_client/alerts_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,11 @@ export class AlertsClient {
...this.apiKeyAsAlertAttributes(createdAPIKey, username),
updatedBy: username,
updatedAt: new Date().toISOString(),
executionStatus: {
status: 'pending',
lastExecutionDate: new Date().toISOString(),
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Does it make sense to reset the lastExecutionDate here? I guess it would quickly be overwritten the next time the rule runs, but technically, this date is not the last time the rule was executed.

Copy link
Member

Choose a reason for hiding this comment

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

It looks like we do set that field to the same "current date" for other cases of status: 'pending'. So, it's consistent. I think we picked the name lastExecutionDate before starting to use pending, and so ... the name kinda doesn't make sense any more. Would be better described (I think) as "lastStateUpdateDate" or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would be better described (I think) as "lastStateUpdateDate" or something.

I think that makes sense. Should I create an issue for 8.0 release? This way we can make it a breaking change.

I think copying how it's done on create is ok for now but definitely strange.

Copy link
Member

Choose a reason for hiding this comment

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

DateDateDate

I'm not against changing the name to better reflect reality, especially as an 8.0 thing. Though I wonder if lastStateUpdate makes sense - the date value is supposed to reflect the last execution, except we knew we didn't have that date in some previous 7.x release, and obviously don't have one for newly created rules. So it does kind of make sense to continue with the current name, with the caveat that you need to check to see if the status is 'pending' which means "it hasn't run yet". Basically, if we call it lastStateUpdate, would folks expect other changes might also change this date? What happens to these fields when disabling a rule?

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 read this as "the execution status is pending, and it's been pending since lastExecutionDate". So any name that can reflect that and last time the rule executed I'm +1. Seems like a separate issue to be created?

error: null,
},
});
try {
await this.unsecuredSavedObjectsClient.update('alert', id, updateAttributes, { version });
Expand Down
10 changes: 10 additions & 0 deletions x-pack/plugins/alerting/server/alerts_client/tests/enable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ describe('enable()', () => {
},
},
],
executionStatus: {
status: 'pending',
lastExecutionDate: '2019-02-12T21:01:22.479Z',
error: null,
},
},
{
version: '123',
Expand Down Expand Up @@ -352,6 +357,11 @@ describe('enable()', () => {
},
},
],
executionStatus: {
status: 'pending',
lastExecutionDate: '2019-02-12T21:01:22.479Z',
error: null,
},
},
{
version: '123',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import * as React from 'react';
import uuid from 'uuid';
import { shallow } from 'enzyme';
import { mountWithIntl, nextTick } from '@kbn/test/jest';
import { act } from '@testing-library/react';
import { AlertDetails } from './alert_details';
import { Alert, ActionType, AlertTypeModel, AlertType } from '../../../../types';
import { EuiTitle, EuiBadge, EuiFlexItem, EuiSwitch, EuiButtonEmpty, EuiText } from '@elastic/eui';
Expand Down Expand Up @@ -463,6 +465,74 @@ describe('disable button', () => {
handler!({} as React.FormEvent);
expect(enableAlert).toHaveBeenCalledTimes(1);
});

it('should reset error banner dismissal after re-enabling the alert', async () => {
const alert = mockAlert({
enabled: true,
executionStatus: {
status: 'error',
lastExecutionDate: new Date('2020-08-20T19:23:38Z'),
error: {
reason: AlertExecutionStatusErrorReasons.Execute,
message: 'Fail',
},
},
});

const alertType: AlertType = {
id: '.noop',
name: 'No Op',
actionGroups: [{ id: 'default', name: 'Default' }],
recoveryActionGroup,
actionVariables: { context: [], state: [], params: [] },
defaultActionGroupId: 'default',
producer: ALERTS_FEATURE_ID,
authorizedConsumers,
minimumLicenseRequired: 'basic',
enabledInLicense: true,
};

const disableAlert = jest.fn();
const enableAlert = jest.fn();
const wrapper = mountWithIntl(
<AlertDetails
alert={alert}
alertType={alertType}
actionTypes={[]}
{...mockAlertApis}
disableAlert={disableAlert}
enableAlert={enableAlert}
/>
);

await act(async () => {
await nextTick();
wrapper.update();
});

// Dismiss the error banner
await act(async () => {
wrapper.find('[data-test-subj="dismiss-execution-error"]').first().simulate('click');
await nextTick();
});

// Disable the alert
await act(async () => {
wrapper.find('[data-test-subj="disableSwitch"] .euiSwitch__button').first().simulate('click');
await nextTick();
});
expect(disableAlert).toHaveBeenCalled();

// Enable the alert
await act(async () => {
wrapper.find('[data-test-subj="disableSwitch"] .euiSwitch__button').first().simulate('click');
await nextTick();
});
expect(enableAlert).toHaveBeenCalled();

// Ensure error banner is back
expect(wrapper.find('[data-test-subj="dismiss-execution-error"]').length).toBeGreaterThan(0);
});
});

describe('mute button', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
if (isEnabled) {
setIsEnabled(false);
await disableAlert(alert);
// Reset dismiss if previously clicked
setDissmissAlertErrors(false);
} else {
setIsEnabled(true);
await enableAlert(alert);
Expand Down Expand Up @@ -277,7 +279,7 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
{!dissmissAlertErrors && alert.executionStatus.status === 'error' ? (
{alert.enabled && !dissmissAlertErrors && alert.executionStatus.status === 'error' ? (
<EuiFlexGroup>
<EuiFlexItem>
<EuiCallOut
Expand All @@ -293,7 +295,11 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
<EuiSpacer size="s" />
<EuiFlexGroup gutterSize="s" wrap={true}>
<EuiFlexItem grow={false}>
<EuiButton color="danger" onClick={() => setDissmissAlertErrors(true)}>
<EuiButton
data-test-subj="dismiss-execution-error"
color="danger"
onClick={() => setDissmissAlertErrors(true)}
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle"
defaultMessage="Dismiss"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ describe('alertInstanceToListItem', () => {
};
expect(alertInstanceToListItem(fakeNow.getTime(), alertType, 'id', instance)).toEqual({
instance: 'id',
status: { label: 'OK', healthColor: 'subdued' },
status: { label: 'Recovered', healthColor: 'subdued' },
start: undefined,
duration: 0,
sortPriority: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const ACTIVE_LABEL = i18n.translate(

const INACTIVE_LABEL = i18n.translate(
'xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive',
{ defaultMessage: 'OK' }
{ defaultMessage: 'Recovered' }
);

function getActionGroupName(alertType: AlertType, actionGroupId?: string): string | undefined {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
).to.eql([
{
instance: 'eu/east',
status: 'OK',
status: 'Recovered',
start: '',
duration: '',
},
Expand Down