[Uptime] Fix Monitor status toggle alert receovery state (#89273)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
5f57766e03
commit
18213b673f
|
@ -89,10 +89,7 @@ export const MonitorPageTitle: React.FC = () => {
|
|||
<EuiSpacer size="xs" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} style={{ justifyContent: 'center' }}>
|
||||
<EnableMonitorAlert
|
||||
monitorId={monitorId}
|
||||
monitorName={selectedMonitor?.monitor?.name || selectedMonitor?.url?.full}
|
||||
/>
|
||||
<EnableMonitorAlert monitorId={monitorId} selectedMonitor={selectedMonitor!} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EnableAlertComponent renders without errors for valid props 1`] = `
|
||||
<div
|
||||
class="euiPopover euiPopover--anchorDownCenter"
|
||||
>
|
||||
<div
|
||||
class="euiPopover__anchor"
|
||||
>
|
||||
<div
|
||||
class="euiSwitch euiSwitch--compressed"
|
||||
>
|
||||
<button
|
||||
aria-checked="false"
|
||||
aria-label="Enable status alert"
|
||||
class="euiSwitch__button"
|
||||
data-test-subj="uptimeDisplayDefineConnector"
|
||||
id="defineAlertSettingsSwitch"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="euiSwitch__body"
|
||||
>
|
||||
<span
|
||||
class="euiSwitch__thumb"
|
||||
/>
|
||||
<span
|
||||
class="euiSwitch__track"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`EnableAlertComponent shallow renders without errors for valid props 1`] = `
|
||||
<Provider
|
||||
store={
|
||||
Object {
|
||||
"dispatch": [MockFunction],
|
||||
"getState": [MockFunction],
|
||||
"replaceReducer": [MockFunction],
|
||||
"subscribe": [MockFunction],
|
||||
}
|
||||
}
|
||||
>
|
||||
<Router
|
||||
history={
|
||||
Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"canGo": [Function],
|
||||
"createHref": [Function],
|
||||
"entries": Array [
|
||||
Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"index": 0,
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
<EnableMonitorAlert
|
||||
monitorId="testMonitor"
|
||||
monitorName="My website"
|
||||
/>
|
||||
</Router>
|
||||
</Provider>
|
||||
`;
|
|
@ -7,112 +7,86 @@
|
|||
|
||||
import React from 'react';
|
||||
import { EnableMonitorAlert } from './enable_alert';
|
||||
import * as redux from 'react-redux';
|
||||
import {
|
||||
mountWithRouterRedux,
|
||||
renderWithRouterRedux,
|
||||
shallowWithRouterRedux,
|
||||
} from '../../../../lib';
|
||||
import { EuiPopover, EuiText } from '@elastic/eui';
|
||||
import { fireEvent } from '@testing-library/dom';
|
||||
|
||||
import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../../common/constants';
|
||||
import { ReactRouterEuiLink } from '../../../common/react_router_helpers';
|
||||
import { makePing } from '../../../../../common/runtime_types/ping';
|
||||
import { render } from '../../../../lib/helper/rtl_helpers';
|
||||
import { DISABLE_STATUS_ALERT, ENABLE_STATUS_ALERT } from './translations';
|
||||
import { mockState } from '../../../../lib/__mocks__/uptime_store.mock';
|
||||
import { AlertsResult } from '../../../../state/actions/types';
|
||||
|
||||
describe('EnableAlertComponent', () => {
|
||||
let defaultConnectors: string[] = [];
|
||||
let alerts: any = [];
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(redux, 'useDispatch').mockReturnValue(jest.fn());
|
||||
|
||||
jest.spyOn(redux, 'useSelector').mockImplementation((fn, d) => {
|
||||
if (fn.name === 'selectDynamicSettings') {
|
||||
return {
|
||||
settings: Object.assign(DYNAMIC_SETTINGS_DEFAULTS, {
|
||||
defaultConnectors,
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (fn.name === 'alertsSelector') {
|
||||
return {
|
||||
data: {
|
||||
data: alerts,
|
||||
},
|
||||
loading: false,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
});
|
||||
|
||||
it('shallow renders without errors for valid props', () => {
|
||||
const wrapper = shallowWithRouterRedux(
|
||||
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
|
||||
it('it displays define connectors when there is none', () => {
|
||||
const { getByTestId, getByLabelText, getByText } = render(
|
||||
<EnableMonitorAlert
|
||||
monitorId={'testMonitor'}
|
||||
selectedMonitor={makePing({ name: 'My website' })}
|
||||
/>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
expect(getByTestId('uptimeDisplayDefineConnector'));
|
||||
expect(getByLabelText(ENABLE_STATUS_ALERT));
|
||||
|
||||
it('renders without errors for valid props', () => {
|
||||
const wrapper = renderWithRouterRedux(
|
||||
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
fireEvent.click(getByTestId('uptimeDisplayDefineConnector'));
|
||||
|
||||
it('displays define connectors when there is none', () => {
|
||||
defaultConnectors = [];
|
||||
const wrapper = mountWithRouterRedux(
|
||||
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
|
||||
expect(getByTestId('uptimeSettingsLink')).toHaveAttribute(
|
||||
'href',
|
||||
'/settings?focusConnectorField=true'
|
||||
);
|
||||
expect(wrapper.find(EuiPopover)).toHaveLength(1);
|
||||
wrapper.find('button').simulate('click');
|
||||
expect(wrapper.find(EuiText).text()).toBe(
|
||||
'To start enabling alerts, please define a default alert action connector in Settings'
|
||||
expect(
|
||||
getByText('To start enabling alerts, please define a default alert action connector in')
|
||||
);
|
||||
expect(wrapper.find(ReactRouterEuiLink)).toMatchInlineSnapshot(`
|
||||
<ReactRouterEuiLink
|
||||
data-test-subj="uptimeSettingsLink"
|
||||
to="/settings?focusConnectorField=true"
|
||||
>
|
||||
<ReactRouterHelperForEui
|
||||
to="/settings?focusConnectorField=true"
|
||||
>
|
||||
<EuiLink
|
||||
data-test-subj="uptimeSettingsLink"
|
||||
href="/settings?focusConnectorField=true"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<a
|
||||
className="euiLink euiLink--primary"
|
||||
data-test-subj="uptimeSettingsLink"
|
||||
href="/settings?focusConnectorField=true"
|
||||
onClick={[Function]}
|
||||
rel="noreferrer"
|
||||
>
|
||||
Settings
|
||||
</a>
|
||||
</EuiLink>
|
||||
</ReactRouterHelperForEui>
|
||||
</ReactRouterEuiLink>
|
||||
`);
|
||||
});
|
||||
|
||||
it('does not displays define connectors when there is connector', () => {
|
||||
defaultConnectors = ['infra-slack-connector-id'];
|
||||
const wrapper = mountWithRouterRedux(
|
||||
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
|
||||
const defaultConnectors = ['infra-slack-connector-id'];
|
||||
|
||||
const { getByTestId, getByLabelText } = render(
|
||||
<EnableMonitorAlert
|
||||
monitorId={'testMonitor'}
|
||||
selectedMonitor={makePing({ name: 'My website' })}
|
||||
/>,
|
||||
{
|
||||
state: {
|
||||
dynamicSettings: {
|
||||
settings: { ...DYNAMIC_SETTINGS_DEFAULTS, defaultConnectors },
|
||||
loading: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(wrapper.find(EuiPopover)).toHaveLength(0);
|
||||
expect(getByTestId('uptimeEnableSimpleDownAlerttestMonitor'));
|
||||
expect(getByLabelText(ENABLE_STATUS_ALERT));
|
||||
});
|
||||
|
||||
it('displays disable when alert is there', () => {
|
||||
alerts = [{ id: 'test-alert', params: { search: 'testMonitor' } }];
|
||||
defaultConnectors = ['infra-slack-connector-id'];
|
||||
const alerts = [{ id: 'test-alert', params: { search: 'testMonitor' } }];
|
||||
const defaultConnectors = ['infra-slack-connector-id'];
|
||||
|
||||
const wrapper = mountWithRouterRedux(
|
||||
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
|
||||
const { getByTestId, getByLabelText } = render(
|
||||
<EnableMonitorAlert
|
||||
monitorId={'testMonitor'}
|
||||
selectedMonitor={makePing({ name: 'My website' })}
|
||||
/>,
|
||||
{
|
||||
state: {
|
||||
dynamicSettings: {
|
||||
settings: { ...DYNAMIC_SETTINGS_DEFAULTS, defaultConnectors },
|
||||
loading: false,
|
||||
},
|
||||
alerts: {
|
||||
...mockState.alerts,
|
||||
alerts: {
|
||||
data: ({ data: alerts } as unknown) as AlertsResult,
|
||||
loading: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(wrapper.find('button').prop('aria-label')).toBe('Disable status alert');
|
||||
expect(getByTestId('uptimeDisableSimpleDownAlerttestMonitor'));
|
||||
expect(getByLabelText(DISABLE_STATUS_ALERT));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,13 +21,14 @@ import {
|
|||
import { MONITOR_ROUTE } from '../../../../../common/constants';
|
||||
import { DefineAlertConnectors } from './define_connectors';
|
||||
import { DISABLE_STATUS_ALERT, ENABLE_STATUS_ALERT } from './translations';
|
||||
import { Ping } from '../../../../../common/runtime_types/ping';
|
||||
|
||||
interface Props {
|
||||
monitorId: string;
|
||||
monitorName?: string;
|
||||
selectedMonitor: Ping;
|
||||
}
|
||||
|
||||
export const EnableMonitorAlert = ({ monitorId, monitorName }: Props) => {
|
||||
export const EnableMonitorAlert = ({ monitorId, selectedMonitor }: Props) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const { settings } = useSelector(selectDynamicSettings);
|
||||
|
@ -66,7 +67,7 @@ export const EnableMonitorAlert = ({ monitorId, monitorName }: Props) => {
|
|||
createAlertAction.get({
|
||||
defaultActions,
|
||||
monitorId,
|
||||
monitorName,
|
||||
selectedMonitor,
|
||||
})
|
||||
);
|
||||
setIsLoading(true);
|
||||
|
@ -102,28 +103,26 @@ export const EnableMonitorAlert = ({ monitorId, monitorName }: Props) => {
|
|||
|
||||
return hasDefaultConnectors || hasAlert ? (
|
||||
<div className="eui-displayInlineBlock" style={{ marginRight: 10 }}>
|
||||
{
|
||||
<EuiToolTip content={btnLabel}>
|
||||
<>
|
||||
<EuiSwitch
|
||||
id={'enableDisableAlertSwitch'}
|
||||
compressed={!isMonitorPage}
|
||||
disabled={showSpinner}
|
||||
label={btnLabel}
|
||||
showLabel={!!isMonitorPage}
|
||||
aria-label={btnLabel}
|
||||
onChange={onAlertClick}
|
||||
checked={!!hasAlert}
|
||||
data-test-subj={
|
||||
hasAlert
|
||||
? 'uptimeDisableSimpleDownAlert' + monitorId
|
||||
: 'uptimeEnableSimpleDownAlert' + monitorId
|
||||
}
|
||||
/>{' '}
|
||||
{showSpinner && <EuiLoadingSpinner className="eui-alignMiddle" />}
|
||||
</>
|
||||
</EuiToolTip>
|
||||
}
|
||||
<EuiToolTip content={btnLabel}>
|
||||
<>
|
||||
<EuiSwitch
|
||||
id={'enableDisableAlertSwitch'}
|
||||
compressed={!isMonitorPage}
|
||||
disabled={showSpinner}
|
||||
label={btnLabel}
|
||||
showLabel={!!isMonitorPage}
|
||||
aria-label={btnLabel}
|
||||
onChange={onAlertClick}
|
||||
checked={!!hasAlert}
|
||||
data-test-subj={
|
||||
hasAlert
|
||||
? 'uptimeDisableSimpleDownAlert' + monitorId
|
||||
: 'uptimeEnableSimpleDownAlert' + monitorId
|
||||
}
|
||||
/>{' '}
|
||||
{showSpinner && <EuiLoadingSpinner className="eui-alignMiddle" />}
|
||||
</>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
) : (
|
||||
<DefineAlertConnectors />
|
||||
|
|
|
@ -142,7 +142,7 @@ export const MonitorListComponent: ({
|
|||
render: (item: MonitorSummary) => (
|
||||
<EnableMonitorAlert
|
||||
monitorId={item.monitor_id}
|
||||
monitorName={item.state.monitor.name || item.monitor_id}
|
||||
selectedMonitor={item.state.summaryPings[0]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
|
|
@ -55,6 +55,7 @@ describe('SyntheticsCallout', () => {
|
|||
grow={false}
|
||||
>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="uptimeDismissSyntheticsCallout"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
@ -115,6 +116,7 @@ describe('SyntheticsCallout', () => {
|
|||
grow={false}
|
||||
>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="uptimeDismissSyntheticsCallout"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -58,6 +58,7 @@ export const SyntheticsCallout = () => {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="uptimeDismissSyntheticsCallout"
|
||||
onClick={() => {
|
||||
if (shouldShow) {
|
||||
hideSyntheticsCallout();
|
||||
|
|
130
x-pack/plugins/uptime/public/state/api/alert_actions.test.ts
Normal file
130
x-pack/plugins/uptime/public/state/api/alert_actions.test.ts
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { populateAlertActions } from './alert_actions';
|
||||
import { ActionConnector } from '../alerts/alerts';
|
||||
|
||||
const selectedMonitor = {
|
||||
docId: 'X5dkPncBy0xTcvZ347hy',
|
||||
timestamp: '2021-01-26T11:12:14.519Z',
|
||||
'@timestamp': '2021-01-26T11:12:14.519Z',
|
||||
url: { scheme: 'tcp', domain: 'localhost', port: 18278, full: 'tcp://localhost:18278' },
|
||||
error: { type: 'io', message: 'dial tcp 127.0.0.1:18278: connect: connection refused' },
|
||||
ecs: { version: '1.7.0' },
|
||||
resolve: { ip: '127.0.0.1', rtt: { us: 410 } },
|
||||
summary: { down: 1, up: 0 },
|
||||
monitor: {
|
||||
ip: '127.0.0.1',
|
||||
name: 'Always Down Local Port',
|
||||
type: 'tcp',
|
||||
timespan: { gte: '2021-01-26T11:12:14.519Z', lt: '2021-01-26T11:17:14.519Z' },
|
||||
id: 'always-down',
|
||||
status: 'down',
|
||||
duration: { us: 695 },
|
||||
check_group: 'a53b0003-5fc6-11eb-9241-42010a84000f',
|
||||
},
|
||||
event: { dataset: 'uptime' },
|
||||
agent: {
|
||||
ephemeral_id: '7d86e765-9f29-46e6-b1ec-047b09b4074e',
|
||||
id: '7c9d2825-614f-4906-a13e-c9db1c6e5585',
|
||||
name: 'gke-edge-oblt-edge-oblt-pool-c9faf257-m1ci',
|
||||
type: 'heartbeat',
|
||||
version: '8.0.0',
|
||||
},
|
||||
};
|
||||
|
||||
describe('Alert Actions factory', () => {
|
||||
it('generate expected action for pager duty', async () => {
|
||||
const resp = populateAlertActions({
|
||||
selectedMonitor,
|
||||
defaultActions: ([
|
||||
{
|
||||
actionTypeId: '.pagerduty',
|
||||
group: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
params: {
|
||||
dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
eventAction: 'trigger',
|
||||
severity: 'error',
|
||||
summary:
|
||||
'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}',
|
||||
},
|
||||
id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9',
|
||||
},
|
||||
] as unknown) as ActionConnector[],
|
||||
});
|
||||
expect(resp).toEqual([
|
||||
{
|
||||
actionTypeId: '.pagerduty',
|
||||
group: 'recovered',
|
||||
id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9',
|
||||
params: {
|
||||
dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
eventAction: 'resolve',
|
||||
summary:
|
||||
'Monitor Always Down Local Port with url tcp://localhost:18278 has recovered with status Up',
|
||||
},
|
||||
},
|
||||
{
|
||||
actionTypeId: '.pagerduty',
|
||||
group: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9',
|
||||
params: {
|
||||
dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
eventAction: 'trigger',
|
||||
severity: 'error',
|
||||
summary:
|
||||
'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('generate expected action for slack action connector', async () => {
|
||||
const resp = populateAlertActions({
|
||||
selectedMonitor,
|
||||
defaultActions: ([
|
||||
{
|
||||
actionTypeId: '.pagerduty',
|
||||
group: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
params: {
|
||||
dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
eventAction: 'trigger',
|
||||
severity: 'error',
|
||||
summary:
|
||||
'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}',
|
||||
},
|
||||
id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9',
|
||||
},
|
||||
] as unknown) as ActionConnector[],
|
||||
});
|
||||
expect(resp).toEqual([
|
||||
{
|
||||
actionTypeId: '.pagerduty',
|
||||
group: 'recovered',
|
||||
id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9',
|
||||
params: {
|
||||
dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
eventAction: 'resolve',
|
||||
summary:
|
||||
'Monitor Always Down Local Port with url tcp://localhost:18278 has recovered with status Up',
|
||||
},
|
||||
},
|
||||
{
|
||||
actionTypeId: '.pagerduty',
|
||||
group: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9',
|
||||
params: {
|
||||
dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
eventAction: 'trigger',
|
||||
severity: 'error',
|
||||
summary:
|
||||
'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { NewAlertParams } from './alerts';
|
||||
import { AlertAction } from '../../../../triggers_actions_ui/public';
|
||||
import { ACTION_GROUP_DEFINITIONS } from '../../../common/constants/alerts';
|
||||
|
@ -19,6 +20,7 @@ import {
|
|||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
} from '../../../../actions/server';
|
||||
import { ActionTypeId } from '../../components/settings/types';
|
||||
import { Ping } from '../../../common/runtime_types/ping';
|
||||
|
||||
export const SLACK_ACTION_ID: ActionTypeId = '.slack';
|
||||
export const PAGER_DUTY_ACTION_ID: ActionTypeId = '.pagerduty';
|
||||
|
@ -31,7 +33,17 @@ export const WEBHOOK_ACTION_ID: ActionTypeId = '.webhook';
|
|||
|
||||
const { MONITOR_STATUS } = ACTION_GROUP_DEFINITIONS;
|
||||
|
||||
export function populateAlertActions({ defaultActions, monitorId, monitorName }: NewAlertParams) {
|
||||
const getRecoveryMessage = (selectedMonitor: Ping) => {
|
||||
return i18n.translate('xpack.uptime.alerts.monitorStatus.recoveryMessage', {
|
||||
defaultMessage: 'Monitor {monitor} with url {url} has recovered with status Up',
|
||||
values: {
|
||||
monitor: selectedMonitor?.monitor?.name || selectedMonitor?.monitor?.id,
|
||||
url: selectedMonitor?.url?.full,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export function populateAlertActions({ defaultActions, selectedMonitor }: NewAlertParams) {
|
||||
const actions: AlertAction[] = [];
|
||||
defaultActions.forEach((aId) => {
|
||||
const action: AlertAction = {
|
||||
|
@ -40,27 +52,52 @@ export function populateAlertActions({ defaultActions, monitorId, monitorName }:
|
|||
group: MONITOR_STATUS.id,
|
||||
params: {},
|
||||
};
|
||||
|
||||
const recoveredAction: AlertAction = {
|
||||
id: aId.id,
|
||||
actionTypeId: aId.actionTypeId,
|
||||
group: 'recovered',
|
||||
params: {
|
||||
message: getRecoveryMessage(selectedMonitor),
|
||||
},
|
||||
};
|
||||
|
||||
switch (aId.actionTypeId) {
|
||||
case PAGER_DUTY_ACTION_ID:
|
||||
action.params = getPagerDutyActionParams(monitorId);
|
||||
action.params = getPagerDutyActionParams(selectedMonitor);
|
||||
recoveredAction.params = getPagerDutyActionParams(selectedMonitor, true);
|
||||
actions.push(recoveredAction);
|
||||
break;
|
||||
case SERVER_LOG_ACTION_ID:
|
||||
action.params = getServerLogActionParams();
|
||||
action.params = getServerLogActionParams(selectedMonitor);
|
||||
recoveredAction.params = getServerLogActionParams(selectedMonitor, true);
|
||||
actions.push(recoveredAction);
|
||||
break;
|
||||
case INDEX_ACTION_ID:
|
||||
action.params = getIndexActionParams();
|
||||
action.params = getIndexActionParams(selectedMonitor);
|
||||
recoveredAction.params = getIndexActionParams(selectedMonitor, true);
|
||||
actions.push(recoveredAction);
|
||||
break;
|
||||
case SERVICE_NOW_ACTION_ID:
|
||||
action.params = getServiceNowActionParams();
|
||||
// Recovery action for service now is not implemented yet
|
||||
break;
|
||||
case JIRA_ACTION_ID:
|
||||
action.params = getJiraActionParams();
|
||||
// Recovery action for Jira is not implemented yet
|
||||
break;
|
||||
case WEBHOOK_ACTION_ID:
|
||||
action.params = getWebhookActionParams();
|
||||
action.params = getWebhookActionParams(selectedMonitor);
|
||||
recoveredAction.params = getWebhookActionParams(selectedMonitor, true);
|
||||
actions.push(recoveredAction);
|
||||
break;
|
||||
case SLACK_ACTION_ID:
|
||||
case TEAMS_ACTION_ID:
|
||||
action.params = {
|
||||
message: MonitorStatusTranslations.defaultActionMessage,
|
||||
};
|
||||
actions.push(recoveredAction);
|
||||
break;
|
||||
default:
|
||||
action.params = {
|
||||
message: MonitorStatusTranslations.defaultActionMessage,
|
||||
|
@ -73,7 +110,21 @@ export function populateAlertActions({ defaultActions, monitorId, monitorName }:
|
|||
return actions;
|
||||
}
|
||||
|
||||
function getIndexActionParams(): IndexActionParams {
|
||||
function getIndexActionParams(selectedMonitor: Ping, recovery = false): IndexActionParams {
|
||||
if (recovery) {
|
||||
return {
|
||||
documents: [
|
||||
{
|
||||
monitorName: '{{state.monitorName}}',
|
||||
monitorUrl: '{{{state.monitorUrl}}}',
|
||||
statusMessage: getRecoveryMessage(selectedMonitor),
|
||||
latestErrorMessage: '',
|
||||
observerLocation: '{{state.observerLocation}}',
|
||||
},
|
||||
],
|
||||
indexOverride: null,
|
||||
};
|
||||
}
|
||||
return {
|
||||
documents: [
|
||||
{
|
||||
|
@ -88,22 +139,37 @@ function getIndexActionParams(): IndexActionParams {
|
|||
};
|
||||
}
|
||||
|
||||
function getServerLogActionParams(): ServerLogActionParams {
|
||||
function getServerLogActionParams(selectedMonitor: Ping, recovery = false): ServerLogActionParams {
|
||||
if (recovery) {
|
||||
return {
|
||||
level: 'info',
|
||||
message: getRecoveryMessage(selectedMonitor),
|
||||
};
|
||||
}
|
||||
return {
|
||||
level: 'warn',
|
||||
message: MonitorStatusTranslations.defaultActionMessage,
|
||||
};
|
||||
}
|
||||
|
||||
function getWebhookActionParams(): WebhookActionParams {
|
||||
function getWebhookActionParams(selectedMonitor: Ping, recovery = false): WebhookActionParams {
|
||||
return {
|
||||
body: MonitorStatusTranslations.defaultActionMessage,
|
||||
body: recovery
|
||||
? getRecoveryMessage(selectedMonitor)
|
||||
: MonitorStatusTranslations.defaultActionMessage,
|
||||
};
|
||||
}
|
||||
|
||||
function getPagerDutyActionParams(monitorId: string): PagerDutyActionParams {
|
||||
function getPagerDutyActionParams(selectedMonitor: Ping, recovery = false): PagerDutyActionParams {
|
||||
if (recovery) {
|
||||
return {
|
||||
dedupKey: selectedMonitor.monitor.id + MONITOR_STATUS.id,
|
||||
eventAction: 'resolve',
|
||||
summary: getRecoveryMessage(selectedMonitor),
|
||||
};
|
||||
}
|
||||
return {
|
||||
dedupKey: monitorId + MONITOR_STATUS.id,
|
||||
dedupKey: selectedMonitor.monitor.id + MONITOR_STATUS.id,
|
||||
eventAction: 'trigger',
|
||||
severity: 'error',
|
||||
summary: MonitorStatusTranslations.defaultActionMessage,
|
||||
|
|
|
@ -16,6 +16,7 @@ import { Alert, AlertTypeParams } from '../../../../alerting/common';
|
|||
import { AtomicStatusCheckParams } from '../../../common/runtime_types/alerts';
|
||||
|
||||
import { populateAlertActions } from './alert_actions';
|
||||
import { Ping } from '../../../common/runtime_types/ping';
|
||||
|
||||
const UPTIME_AUTO_ALERT = 'UPTIME_AUTO';
|
||||
|
||||
|
@ -24,8 +25,7 @@ export const fetchConnectors = async () => {
|
|||
};
|
||||
|
||||
export interface NewAlertParams extends AlertTypeParams {
|
||||
monitorId: string;
|
||||
monitorName?: string;
|
||||
selectedMonitor: Ping;
|
||||
defaultActions: ActionConnector[];
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,12 @@ type NewMonitorStatusAlert = Omit<
|
|||
export const createAlert = async ({
|
||||
defaultActions,
|
||||
monitorId,
|
||||
monitorName,
|
||||
selectedMonitor,
|
||||
}: NewAlertParams): Promise<Alert> => {
|
||||
const actions: AlertAction[] = populateAlertActions({ defaultActions, monitorId, monitorName });
|
||||
const actions: AlertAction[] = populateAlertActions({
|
||||
defaultActions,
|
||||
selectedMonitor,
|
||||
});
|
||||
|
||||
const data: NewMonitorStatusAlert = {
|
||||
actions,
|
||||
|
@ -67,7 +70,7 @@ export const createAlert = async ({
|
|||
schedule: { interval: '1m' },
|
||||
notifyWhen: 'onActionGroupChange',
|
||||
tags: [UPTIME_AUTO_ALERT],
|
||||
name: `${monitorName} (Simple status alert)`,
|
||||
name: `${selectedMonitor?.monitor.name || selectedMonitor?.url?.full}(Simple status alert)`,
|
||||
enabled: true,
|
||||
throttle: null,
|
||||
};
|
||||
|
|
|
@ -264,7 +264,6 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
|
|||
state,
|
||||
services: { alertInstanceFactory },
|
||||
},
|
||||
dynamicSettings,
|
||||
uptimeEsClient,
|
||||
}) {
|
||||
const {
|
||||
|
@ -283,9 +282,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
|
|||
const filterString = await formatFilterString(uptimeEsClient, filters, search, libs);
|
||||
|
||||
const timerange = oldVersionTimeRange || {
|
||||
from: isAutoGenerated
|
||||
? state.lastCheckedAt
|
||||
: `now-${String(timerangeCount) + timerangeUnit}`,
|
||||
from: `now-${String(timerangeCount) + timerangeUnit}`,
|
||||
to: 'now',
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const uptimeService = getService('uptime');
|
||||
const retry = getService('retry');
|
||||
const supertest = getService('supertest');
|
||||
const toasts = getService('toasts');
|
||||
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
|
@ -46,6 +47,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
});
|
||||
|
||||
it('displays to define default connector', async () => {
|
||||
await testSubjects.click('uptimeDismissSyntheticsCallout');
|
||||
await hideErrorToast();
|
||||
await testSubjects.click('uptimeDisplayDefineConnector');
|
||||
await testSubjects.existOrFail('uptimeSettingsDefineConnector');
|
||||
|
@ -71,6 +73,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
});
|
||||
|
||||
it('displays relevant alert in list drawer', async () => {
|
||||
await toasts.dismissAllToasts();
|
||||
|
||||
await testSubjects.click(`xpack.uptime.monitorList.${monitorId}.expandMonitorDetail`);
|
||||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('uptimeMonitorListDrawerAlert0');
|
||||
|
@ -87,31 +91,38 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
alert = alertsFromThisTest[0];
|
||||
});
|
||||
|
||||
const { actions, alertTypeId, consumer, id, tags } = alert ?? {};
|
||||
try {
|
||||
expect(actions).to.eql([
|
||||
{
|
||||
actionTypeId: '.slack',
|
||||
group: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
id: 'my-slack1',
|
||||
params: {
|
||||
message:
|
||||
'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}',
|
||||
},
|
||||
const { actions, alertTypeId, consumer, tags } = alert ?? {};
|
||||
expect(actions).to.eql([
|
||||
{
|
||||
actionTypeId: '.slack',
|
||||
group: 'recovered',
|
||||
params: {
|
||||
message:
|
||||
'Monitor 0000-intermittent with url http://localhost:5678/pattern?r=200x5,500x1 has recovered with status Up',
|
||||
},
|
||||
]);
|
||||
expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus');
|
||||
expect(consumer).to.eql('uptime');
|
||||
expect(tags).to.eql(['UPTIME_AUTO']);
|
||||
} catch (e) {
|
||||
await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204);
|
||||
}
|
||||
id: 'my-slack1',
|
||||
},
|
||||
{
|
||||
actionTypeId: '.slack',
|
||||
group: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
params: {
|
||||
message:
|
||||
'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}',
|
||||
},
|
||||
id: 'my-slack1',
|
||||
},
|
||||
]);
|
||||
expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus');
|
||||
expect(consumer).to.eql('uptime');
|
||||
expect(tags).to.eql(['UPTIME_AUTO']);
|
||||
});
|
||||
|
||||
it('disable simple status alert', async () => {
|
||||
await testSubjects.click('uptimeDisableSimpleDownAlert' + monitorId);
|
||||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('uptimeEnableSimpleDownAlert' + monitorId);
|
||||
await retry.try(async () => {
|
||||
await testSubjects.existOrFail('uptimeEnableSimpleDownAlert' + monitorId);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue