Skip to content

Commit

Permalink
[7.x] [Uptime] Availability alert (#70284) (#71303)
Browse files Browse the repository at this point in the history
* [Uptime] Availability alert (#70284)

* Add new fields to monitor status alert for availability.

* Add UI code for availability threshold expression + translations/a11y fields.

* Add availability selection to alert UI.

* Disable expression popover button functionality when not enabled.

* Add select box for monitor status alert, reorganize layout.

* Add new runtime types for parsing in alert executor.

* Add new enablement field for monitor status checks.

* Add availability check query function and tests. Extract helper function from similar test file to generic file.

* Add availability checking to status check alert type.

* Change availability threshold to be number type.

* Remove clearing of fields when disabled.

* Change alert validation to require availability or status check.

* Fix threshold input functionality.

* Add tests and refine alert validation.

* Add test for new validation logic.

* Add any type temporarily.

* Delete unused code, fix types.

* Add filter capabilities to availability type.

* Disable availability by default for old alerts.

* Add filtering to availability query.

* Clean up types and refresh test snapshots.

* Change threshold storage value to string. Add bucket selector agg.

* Update copy.

* Add tests and improve should check flag evaluation.

* Improve old alert detection code.

* Fix issue with status check enablement.

* Update unit tests to reflect changes to query.

* Fix types.

* Improve tests, refactor a function to clean up code.

* Remove fields from aggregate key and retrieve them from top hits instead.

* Add sort parameter to top_hits aggregation.

* Update context message of monitor status alert, and add translations for availability message.

* Modify default alert message.

* Add a comment.

* Fix outdated translations.

* Revert unknown to any to simplify validation.

* Improve readability of array manipulation for availability result description.

* Add a flex item wrapper to fix layout problem.

* Update snaps for 7.x.
  • Loading branch information
justinkambic authored Jul 10, 2020
1 parent 1d8e67e commit c37931c
Show file tree
Hide file tree
Showing 31 changed files with 2,583 additions and 286 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -16374,7 +16374,7 @@
"xpack.uptime.alerts.monitorStatus.addFilter.tag": "タグ",
"xpack.uptime.alerts.monitorStatus.addFilter.type": "タイプ",
"xpack.uptime.alerts.monitorStatus.clientName": "稼働状況の監視ステータス",
"xpack.uptime.alerts.monitorStatus.defaultActionMessage": "{contextMessage}\n前回トリガー日時:{lastTriggered}\n{downMonitors}",
"xpack.uptime.alerts.monitorStatus.defaultActionMessage": "{contextMessage}\n前回トリガー日時:{lastTriggered}\n",
"xpack.uptime.alerts.monitorStatus.filterBar.ariaLabel": "監視状態アラートのフィルター基準を許可するインプット",
"xpack.uptime.alerts.monitorStatus.filters.anyLocation": "任意の場所",
"xpack.uptime.alerts.monitorStatus.filters.anyPort": "任意のポート",
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -16381,7 +16381,7 @@
"xpack.uptime.alerts.monitorStatus.addFilter.tag": "标记",
"xpack.uptime.alerts.monitorStatus.addFilter.type": "类型",
"xpack.uptime.alerts.monitorStatus.clientName": "运行时间监测状态",
"xpack.uptime.alerts.monitorStatus.defaultActionMessage": "{contextMessage}\n上次触发时间:{lastTriggered}\n{downMonitors}",
"xpack.uptime.alerts.monitorStatus.defaultActionMessage": "{contextMessage}\n上次触发时间:{lastTriggered}\n",
"xpack.uptime.alerts.monitorStatus.filterBar.ariaLabel": "允许对监测状态告警使用筛选条件的输入",
"xpack.uptime.alerts.monitorStatus.filters.anyLocation": "任意位置",
"xpack.uptime.alerts.monitorStatus.filters.anyPort": "任意端口",
Expand Down
40 changes: 40 additions & 0 deletions x-pack/plugins/uptime/common/runtime_types/alerts/status_check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const AtomicStatusCheckParamsType = t.intersection([
t.partial({
search: t.string,
filters: StatusCheckFiltersType,
shouldCheckStatus: t.boolean,
}),
]);

Expand All @@ -32,6 +33,7 @@ export type AtomicStatusCheckParams = t.TypeOf<typeof AtomicStatusCheckParamsTyp
export const StatusCheckParamsType = t.intersection([
t.partial({
filters: t.string,
shouldCheckStatus: t.boolean,
}),
t.type({
locations: t.array(t.string),
Expand All @@ -43,4 +45,42 @@ export const StatusCheckParamsType = t.intersection([
}),
]);

export const RangeUnitType = t.union([
t.literal('s', 'Second'),
t.literal('m', 'Minute'),
t.literal('h', 'Hour'),
t.literal('d', 'Day'),
t.literal('w', 'Week'),
t.literal('M', 'Month'),
t.literal('y', 'Year'),
]);

export type RangeUnit = t.TypeOf<typeof RangeUnitType>;

export type StatusCheckParams = t.TypeOf<typeof StatusCheckParamsType>;

export const GetMonitorAvailabilityParamsType = t.intersection([
t.type({
range: t.number,
rangeUnit: RangeUnitType,
threshold: t.string,
}),
t.partial({
filters: t.string,
}),
]);

export type GetMonitorAvailabilityParams = t.TypeOf<typeof GetMonitorAvailabilityParamsType>;

export const MonitorAvailabilityType = t.intersection([
t.type({
availability: GetMonitorAvailabilityParamsType,
shouldCheckAvailability: t.boolean,
}),
t.partial({
filters: StatusCheckFiltersType,
search: t.string,
}),
]);

export type MonitorAvailability = t.Type<typeof MonitorAvailabilityType>;
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,9 @@ describe('alert monitor status component', () => {
<EuiSpacer
size="s"
/>
<DownNoExpressionSelect
defaultNumTimes={3}
hasFilters={false}
setAlertParams={[MockFunction]}
/>
<EuiSpacer
size="xs"
/>
<TimeExpressionSelect
defaultTimerangeCount={21}
defaultTimerangeUnit="h"
setAlertParams={[MockFunction]}
/>
<EuiSpacer
size="xs"
<AddFilterButton
newFilters={Array []}
onNewFilter={[Function]}
/>
<FiltersExpressionSelectContainer
alertParams={
Expand All @@ -89,15 +77,34 @@ describe('alert monitor status component', () => {
setAlertParams={[MockFunction]}
shouldUpdateUrl={false}
/>
<EuiSpacer
size="xs"
<EuiHorizontalRule />
<StatusExpressionSelect
alertParams={
Object {
"numTimes": 3,
"search": "monitor.id: foo",
"timerangeCount": 21,
"timerangeUnit": "h",
}
}
hasFilters={false}
setAlertParams={[MockFunction]}
/>
<AddFilterButton
newFilters={Array []}
onNewFilter={[Function]}
<EuiHorizontalRule />
<AvailabilityExpressionSelect
alertParams={
Object {
"numTimes": 3,
"search": "monitor.id: foo",
"timerangeCount": 21,
"timerangeUnit": "h",
}
}
isOldAlert={true}
setAlertParams={[MockFunction]}
/>
<EuiSpacer
size="m"
size="l"
/>
<EuiCallOut
iconType="iInCircle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('OldAlertCallOut', () => {
size="s"
title={
<FormattedMessage
defaultMessage="You are editing an older alert, some fields may not auto-populate."
defaultMessage="You may be editing an older alert, some fields may not auto-populate."
id="xpack.uptime.alerts.monitorStatus.oldAlertCallout.title"
values={Object {}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@ interface AlertExpressionPopoverProps {
content: React.ReactElement;
description: string;
'data-test-subj': string;
isEnabled?: boolean;
id: string;
isInvalid?: boolean;
value: string;
}

const getColor = (
isOpen: boolean,
isEnabled?: boolean,
isInvalid?: boolean
): 'primary' | 'secondary' | 'subdued' | 'danger' => {
if (isInvalid === true) return 'danger';
if (isEnabled === false) return 'subdued';
return isOpen ? 'primary' : 'secondary';
};

export const AlertExpressionPopover: React.FC<AlertExpressionPopoverProps> = ({
'aria-label': ariaLabel,
content,
'data-test-subj': dataTestSubj,
description,
isEnabled,
isInvalid,
id,
value,
}) => {
Expand All @@ -32,11 +46,11 @@ export const AlertExpressionPopover: React.FC<AlertExpressionPopoverProps> = ({
button={
<EuiExpression
aria-label={ariaLabel}
color={isOpen ? 'primary' : 'secondary'}
color={getColor(isOpen, isEnabled, isInvalid)}
data-test-subj={dataTestSubj}
description={description}
isActive={isOpen}
onClick={() => setIsOpen(!isOpen)}
onClick={isEnabled ? () => setIsOpen(!isOpen) : undefined}
value={value}
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@
*/

import React, { useState } from 'react';
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
import { EuiCallOut, EuiSpacer, EuiHorizontalRule } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { DataPublicPluginSetup } from 'src/plugins/data/public';
import * as labels from './translations';
import {
DownNoExpressionSelect,
TimeExpressionSelect,
FiltersExpressionSelectContainer,
} from './monitor_expressions';
import { FiltersExpressionSelectContainer, StatusExpressionSelect } from './monitor_expressions';
import { AddFilterButton } from './add_filter_btn';
import { OldAlertCallOut } from './old_alert_call_out';
import { AvailabilityExpressionSelect } from './monitor_expressions/availability_expression_select';
import { KueryBar } from '..';

export interface AlertMonitorStatusProps {
Expand Down Expand Up @@ -69,22 +66,14 @@ export const AlertMonitorStatusComponent: React.FC<AlertMonitorStatusProps> = (p

<EuiSpacer size="s" />

<DownNoExpressionSelect
defaultNumTimes={alertParams.numTimes}
hasFilters={hasFilters}
setAlertParams={setAlertParams}
/>

<EuiSpacer size="xs" />

<TimeExpressionSelect
defaultTimerangeUnit={alertParams.timerangeUnit}
defaultTimerangeCount={alertParams.timerangeCount}
setAlertParams={setAlertParams}
<AddFilterButton
alertFilters={alertParams.filters}
newFilters={newFilters}
onNewFilter={(newFilter) => {
setNewFilters([...newFilters, newFilter]);
}}
/>

<EuiSpacer size="xs" />

<FiltersExpressionSelectContainer
alertParams={alertParams}
newFilters={newFilters}
Expand All @@ -97,17 +86,23 @@ export const AlertMonitorStatusComponent: React.FC<AlertMonitorStatusProps> = (p
shouldUpdateUrl={shouldUpdateUrl}
/>

<EuiSpacer size="xs" />
<EuiHorizontalRule />

<AddFilterButton
alertFilters={alertParams.filters}
newFilters={newFilters}
onNewFilter={(newFilter) => {
setNewFilters([...newFilters, newFilter]);
}}
<StatusExpressionSelect
alertParams={alertParams}
hasFilters={hasFilters}
setAlertParams={setAlertParams}
/>

<EuiSpacer size="m" />
<EuiHorizontalRule />

<AvailabilityExpressionSelect
alertParams={alertParams}
isOldAlert={isOldAlert}
setAlertParams={setAlertParams}
/>

<EuiSpacer size="l" />

<EuiCallOut
size="s"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import {
setEsKueryString,
getSnapshotCountAction,
} from '../../../../state/actions';
import { AtomicStatusCheckParamsType } from '../../../../../common/runtime_types';
import {
AtomicStatusCheckParamsType,
GetMonitorAvailabilityParamsType,
} from '../../../../../common/runtime_types';
import { useIndexPattern } from '../../kuery_bar/use_index_pattern';
import { useUpdateKueryString } from '../../../../hooks';

Expand Down Expand Up @@ -85,7 +88,10 @@ export const AlertMonitorStatus: React.FC<Props> = ({
}, [dispatch, esFilters]);

const isOldAlert = React.useMemo(
() => !isRight(AtomicStatusCheckParamsType.decode(alertParams)),
() =>
Object.entries(alertParams).length > 0 &&
!isRight(AtomicStatusCheckParamsType.decode(alertParams)) &&
!isRight(GetMonitorAvailabilityParamsType.decode(alertParams)),
[alertParams]
);
useEffect(() => {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c37931c

Please sign in to comment.