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

[Metrics UI] Add warning severity to Metric Alerts #90070

Merged
merged 10 commits into from
Feb 9, 2021
4 changes: 2 additions & 2 deletions x-pack/plugins/infra/common/alerting/metrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export const INFRA_ALERT_PREVIEW_PATH = '/api/infra/alerting/preview';

export const TOO_MANY_BUCKETS_PREVIEW_EXCEPTION = 'TOO_MANY_BUCKETS_PREVIEW_EXCEPTION';
export interface TooManyBucketsPreviewExceptionMetadata {
TOO_MANY_BUCKETS_PREVIEW_EXCEPTION: any;
maxBuckets: number;
TOO_MANY_BUCKETS_PREVIEW_EXCEPTION: boolean;
maxBuckets: any;
}
export const isTooManyBucketsPreviewException = (
value: any
Expand Down
17 changes: 11 additions & 6 deletions x-pack/plugins/infra/common/alerting/metrics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,17 @@ export type AlertPreviewRequestParams = rt.TypeOf<typeof alertPreviewRequestPara

export const alertPreviewSuccessResponsePayloadRT = rt.type({
numberOfGroups: rt.number,
resultTotals: rt.type({
fired: rt.number,
noData: rt.number,
error: rt.number,
notifications: rt.number,
}),
resultTotals: rt.intersection([
rt.type({
fired: rt.number,
noData: rt.number,
error: rt.number,
notifications: rt.number,
}),
rt.partial({
warning: rt.number,
}),
]),
});
export type AlertPreviewSuccessResponsePayload = rt.TypeOf<
typeof alertPreviewSuccessResponsePayloadRT
Expand Down
208 changes: 159 additions & 49 deletions x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ export const AlertPreview: React.FC<Props> = (props) => {
return unthrottledNotifications > notifications;
}, [previewResult, showNoDataResults]);

const hasWarningThreshold = useMemo(
() => alertParams.criteria?.some((c) => Reflect.has(c, 'warningThreshold')),
[alertParams]
);

return (
<EuiFormRow
label={i18n.translate('xpack.infra.metrics.alertFlyout.previewLabel', {
Expand Down Expand Up @@ -160,66 +165,32 @@ export const AlertPreview: React.FC<Props> = (props) => {
<EuiCallOut
size="s"
title={
<>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewResult"
defaultMessage="There were {firedTimes}"
values={{
firedTimes: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.firedTimes"
defaultMessage="{fired, plural, one {# instance} other {# instances}}"
values={{
fired: previewResult.resultTotals.fired,
}}
/>
</strong>
),
}}
/>{' '}
{previewResult.groupByDisplayName ? (
<>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewGroupsAcross"
defaultMessage="across"
/>{' '}
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewGroups"
defaultMessage="{numberOfGroups, plural, one {# {groupName}} other {# {groupName}s}}"
values={{
numberOfGroups: previewResult.numberOfGroups,
groupName: previewResult.groupByDisplayName,
}}
/>
</strong>{' '}
</>
) : null}
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewResultLookback"
defaultMessage="that satisfied the conditions of this alert in the last {lookback}."
values={{
lookback: previewOptions.find(
(e) => e.value === previewResult.previewLookbackInterval
)?.shortText,
}}
/>
</>
<PreviewTextString
previewResult={previewResult}
hasWarningThreshold={hasWarningThreshold}
/>
}
>
{showNoDataResults && previewResult.resultTotals.noData ? (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult"
defaultMessage="There {boldedResultsNumber} of no data."
defaultMessage="There {wereWas} {boldedResultsNumber} of no data."
values={{
wereWas: (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.wereWas"
defaultMessage="{plurality, plural, one {was} other {were}}"
values={{
plurality: previewResult.resultTotals.noData,
}}
/>
),
boldedResultsNumber: (
<strong>
{i18n.translate(
'xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber',
{
defaultMessage:
'{noData, plural, one {was # result} other {were # results}}',
defaultMessage: '{noData, plural, one {# result} other {# results}}',
values: {
noData: previewResult.resultTotals.noData,
},
Expand Down Expand Up @@ -361,6 +332,145 @@ export const AlertPreview: React.FC<Props> = (props) => {
);
};

const PreviewTextString = ({
previewResult,
hasWarningThreshold,
}: {
previewResult: AlertPreviewSuccessResponsePayload & Record<string, any>;
hasWarningThreshold: boolean;
}) => {
const instanceCount = hasWarningThreshold ? (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewResultWithSeverityLevels"
defaultMessage="There {wereWas} {criticalInstances} that satisfied the {boldCritical} conditions, and {warningInstances} that satisfied the {boldWarning} conditions of this alert"
values={{
wereWas: (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.wereWas"
defaultMessage="{plurality, plural, one {was} other {were}}"
values={{
plurality: previewResult.resultTotals.fired,
}}
/>
),
criticalInstances: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.firedTimes"
defaultMessage="{fired, plural, one {# instance} other {# instances}}"
values={{
fired: previewResult.resultTotals.fired,
}}
/>
</strong>
),
warningInstances: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.firedTimes"
defaultMessage="{fired, plural, one {# instance} other {# instances}}"
values={{
fired: previewResult.resultTotals.warning,
}}
/>
</strong>
),
boldCritical: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.boldCritical"
defaultMessage="critical"
/>
</strong>
),
boldWarning: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.boldWarning"
defaultMessage="warning"
/>
</strong>
),
}}
/>
) : (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewResultInstances"
defaultMessage="There {wereWas} {firedTimes} that satisfied the conditions of this alert"
values={{
wereWas: (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.wereWas"
defaultMessage="{plurality, plural, one {was} other {were}}"
values={{
plurality: previewResult.resultTotals.fired,
}}
/>
),
firedTimes: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.firedTimes"
defaultMessage="{fired, plural, one {# instance} other {# instances}}"
values={{
fired: previewResult.resultTotals.fired,
}}
/>
</strong>
),
}}
/>
);

const groupByText = previewResult.groupByDisplayName ? (
<>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewGroupBy"
defaultMessage="across {groups}"
values={{
groups: (
<strong>
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewGroups"
defaultMessage="{numberOfGroups, plural, one {# {groupName}} other {# {groupName}s}}"
values={{
numberOfGroups: previewResult.numberOfGroups,
groupName: previewResult.groupByDisplayName,
}}
/>
</strong>
),
}}
/>{' '}
</>
) : (
<></>
);

const lookbackText = (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewLookback"
defaultMessage="in the last {lookback}"
values={{
lookback: previewOptions.find((e) => e.value === previewResult.previewLookbackInterval)
?.shortText,
}}
/>
);

return (
<FormattedMessage
id="xpack.infra.metrics.alertFlyout.alertPreviewResultText"
defaultMessage="{instanceCount} {groupByWithConditionalTrailingSpace}{lookbackText}."
values={{
instanceCount,
groupByWithConditionalTrailingSpace: groupByText,
lookbackText,
}}
/>
);
};

const previewOptions = [
{
value: 'h',
Expand Down
Loading