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

[Alert details page] Fix metric threshold chart time range for bigger lookback windows #184409

Merged
merged 3 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,27 @@ describe('getPaddedAlertTimeRange', () => {
'Duration 4 hour, time range will be extended it with 30 minutes from each side',
'2023-03-28T04:15:32.660Z',
'2023-03-28T08:15:32.660Z',
undefined,
{ from: '2023-03-28T03:45:32.660Z', to: '2023-03-28T08:45:32.660Z' },
],
[
'Duration 5 minutes, time range will be extended it with 20 minutes from each side',
'2023-03-28T08:22:33.660Z',
'2023-03-28T08:27:33.660Z',
undefined,
{ from: '2023-03-28T08:02:33.660Z', to: '2023-03-28T08:47:33.660Z' },
],
[
'Duration 5 minutes with 1 day lookBack, time range will be extended it with 20 days from each side',
'2023-01-28T22:22:33.660Z',
'2023-01-28T23:27:33.660Z',
{ size: 1, unit: 'd' },
{ from: '2023-01-08T22:22:33.660Z', to: '2023-02-17T23:27:33.660Z' },
],
];

it.each(testData)('%s', (_, start, end, output) => {
expect(getPaddedAlertTimeRange(start, end)).toEqual(output);
it.each(testData)('%s', (_, start, end, lookBackWindow, output) => {
expect(getPaddedAlertTimeRange(start, end, lookBackWindow)).toEqual(output);
});

describe('active alert', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,32 @@ export interface TimeRange {
to: string;
}

export const getPaddedAlertTimeRange = (alertStart: string, alertEnd?: string): TimeRange => {
export const getPaddedAlertTimeRange = (
alertStart: string,
alertEnd?: string,
lookBackWindow?: {
size: number;
unit: 's' | 'm' | 'h' | 'd';
}
): TimeRange => {
const alertDuration = moment.duration(moment(alertEnd).diff(moment(alertStart)));
const now = moment().toISOString();
const durationMs =

// If alert duration is less than 160 min, we use 20 minute buffer
// Otherwise, we use 8 times alert duration
const defaultDurationMs =
alertDuration.asMinutes() < 160
? moment.duration(20, 'minutes').asMilliseconds()
: alertDuration.asMilliseconds() / 8;
// To ensure the alert time range at least covers 20 times lookback window,
// we compare lookBackDurationMs and defaultDurationMs to use any of those that is longer
const lookBackDurationMs =
lookBackWindow &&
moment.duration(lookBackWindow.size * 20, lookBackWindow.unit).asMilliseconds();
const durationMs =
lookBackDurationMs && lookBackDurationMs - defaultDurationMs > 0
? lookBackDurationMs
: defaultDurationMs;

const from = moment(alertStart).subtract(durationMs, 'millisecond').toISOString();
const to =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useEffect } from 'react';
import moment from 'moment';
import {
Expand All @@ -15,7 +14,6 @@ import {
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
useEuiTheme,
} from '@elastic/eui';
Expand All @@ -31,7 +29,6 @@ import { Rule } from '@kbn/alerting-plugin/common';
import { AlertAnnotation, AlertActiveTimeRangeAnnotation } from '@kbn/observability-alert-details';
import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util';
import { metricValueFormatter } from '../../../../common/alerting/metrics/metric_value_formatter';
import { TIME_LABELS } from '../../common/criterion_preview_chart/criterion_preview_chart';
import { Threshold } from '../../common/components/threshold';
import { withSourceProvider } from '../../../containers/metrics_source';
import { generateUniqueKey } from '../lib/generate_unique_key';
Expand Down Expand Up @@ -88,7 +85,6 @@ export function AlertDetailsAppSection({
const chartProps = {
baseTheme: charts.theme.useChartsBaseTheme(),
};
const timeRange = getPaddedAlertTimeRange(alert.fields[ALERT_START]!, alert.fields[ALERT_END]);
const alertEnd = alert.fields[ALERT_END] ? moment(alert.fields[ALERT_END]).valueOf() : undefined;
const annotations = [
<AlertAnnotation
Expand Down Expand Up @@ -140,61 +136,61 @@ export function AlertDetailsAppSection({

return !!rule.params.criteria ? (
<EuiFlexGroup direction="column" data-test-subj="metricThresholdAppSection">
{rule.params.criteria.map((criterion, index) => (
<EuiFlexItem key={generateUniqueKey(criterion)}>
<EuiPanel hasBorder hasShadow={false}>
<EuiTitle size="xs">
<h4>
{criterion.aggType.toUpperCase()}{' '}
{'metric' in criterion ? criterion.metric : undefined}
</h4>
</EuiTitle>
<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.infra.metrics.alertDetailsAppSection.criterion.subtitle"
defaultMessage="Last {lookback} {timeLabel}"
values={{
lookback: criterion.timeSize,
timeLabel: TIME_LABELS[criterion.timeUnit as keyof typeof TIME_LABELS],
}}
/>
</EuiText>
<EuiSpacer size="s" />
<EuiFlexGroup>
<EuiFlexItem style={{ minHeight: 150, minWidth: 160 }} grow={1}>
<Threshold
chartProps={chartProps}
id={`threshold-${generateUniqueKey(criterion)}`}
threshold={criterion.threshold[0]}
value={alert.fields[ALERT_EVALUATION_VALUES]![index]}
valueFormatter={(d) =>
metricValueFormatter(d, 'metric' in criterion ? criterion.metric : undefined)
}
title={i18n.translate(
'xpack.infra.metrics.alertDetailsAppSection.thresholdTitle',
{
defaultMessage: 'Threshold breached',
{rule.params.criteria.map((criterion, index) => {
const timeRange = getPaddedAlertTimeRange(
Copy link
Member Author

Choose a reason for hiding this comment

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

In this section, I only added timeRange and removed FormattedMessage related to Last {lookback} {timeLabel}.

alert.fields[ALERT_START]!,
alert.fields[ALERT_END],
{
size: criterion.timeSize,
unit: criterion.timeUnit,
}
);
return (
<EuiFlexItem key={generateUniqueKey(criterion)}>
<EuiPanel hasBorder hasShadow={false}>
<EuiTitle size="xs">
<h4>
{criterion.aggType.toUpperCase()}{' '}
{'metric' in criterion ? criterion.metric : undefined}
</h4>
</EuiTitle>
<EuiSpacer size="m" />
<EuiFlexGroup>
<EuiFlexItem style={{ minHeight: 150, minWidth: 160 }} grow={1}>
<Threshold
chartProps={chartProps}
id={`threshold-${generateUniqueKey(criterion)}`}
threshold={criterion.threshold[0]}
value={alert.fields[ALERT_EVALUATION_VALUES]![index]}
valueFormatter={(d) =>
metricValueFormatter(d, 'metric' in criterion ? criterion.metric : undefined)
}
)}
comparator={criterion.comparator}
/>
</EuiFlexItem>
<EuiFlexItem grow={5}>
<ExpressionChart
annotations={annotations}
chartType={MetricsExplorerChartType.line}
expression={criterion}
filterQuery={rule.params.filterQueryText}
groupBy={rule.params.groupBy}
groupInstance={groupInstance}
hideTitle
timeRange={timeRange}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
))}
title={i18n.translate(
'xpack.infra.metrics.alertDetailsAppSection.thresholdTitle',
{
defaultMessage: 'Threshold breached',
}
)}
comparator={criterion.comparator}
/>
</EuiFlexItem>
<EuiFlexItem grow={5}>
<ExpressionChart
annotations={annotations}
chartType={MetricsExplorerChartType.line}
expression={criterion}
filterQuery={rule.params.filterQueryText}
groupBy={rule.params.groupBy}
groupInstance={groupInstance}
hideTitle
timeRange={timeRange}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
);
})}
</EuiFlexGroup>
) : null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@

import chroma from 'chroma-js';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useEffect, useState } from 'react';
import {
EuiFlexGroup,
EuiFlexItem,
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
EuiToolTip,
useEuiTheme,
Expand Down Expand Up @@ -45,7 +43,6 @@ import { getGroupFilters } from '../../../../../common/custom_threshold_rule/hel
import { metricValueFormatter } from '../../../../../common/custom_threshold_rule/metric_value_formatter';
import { AlertSummaryField } from '../../../..';
import { AlertParams } from '../../types';
import { TIME_LABELS } from '../criterion_preview_chart/criterion_preview_chart';
import { Threshold } from '../custom_threshold';
import { CustomThresholdRule, CustomThresholdAlert } from '../types';
import { LogRateAnalysis } from './log_rate_analysis';
Expand Down Expand Up @@ -236,17 +233,7 @@ export default function AlertDetailsAppSection({
<h4 data-test-subj={`chartTitle-${index}`}>{chartTitleAndTooltip[index].title}</h4>
</EuiTitle>
</EuiToolTip>
<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.observability.customThreshold.rule.alertDetailsAppSection.criterion.subtitle"
defaultMessage="Last {lookback} {timeLabel}"
values={{
lookback: criterion.timeSize,
timeLabel: TIME_LABELS[criterion.timeUnit as keyof typeof TIME_LABELS],
}}
/>
</EuiText>
<EuiSpacer size="s" />
<EuiSpacer size="m" />
<EuiFlexGroup>
<EuiFlexItem style={{ minHeight: 150, minWidth: 160 }} grow={1}>
<Threshold
Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/translations/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -21002,7 +21002,6 @@
"xpack.infra.logSourceConfiguration.missingMessageFieldErrorMessage": "La vue de données doit contenir un champ {messageField}.",
"xpack.infra.logSourceErrorPage.savedObjectNotFoundErrorMessage": "Impossible de localiser ce {savedObjectType} : {savedObjectId}",
"xpack.infra.metadataEmbeddable.errorMessage": "Une erreur s'est produite lors du chargement des données. Essayez de {refetch} et d'ouvrir à nouveau les détails de l'hôte.",
"xpack.infra.metrics.alertDetailsAppSection.criterion.subtitle": "Dernier {lookback} {timeLabel}",
"xpack.infra.metrics.alertFlyout.alertPerRedundantFilterError": "Il est possible que cette règle signale {matchedGroups} moins que prévu, car la requête de filtre comporte une correspondance pour {groupCount, plural, one {ce champ} other {ces champs}}. Pour en savoir plus, veuillez consulter {filteringAndGroupingLink}.",
"xpack.infra.metrics.alertFlyout.customEquationEditor.aggregationLabel": "{name} de l'agrégation",
"xpack.infra.metrics.alertFlyout.customEquationEditor.fieldLabel": "{name} du champ",
Expand Down Expand Up @@ -29762,7 +29761,6 @@
"xpack.observability.customThreshold.rule.aggregators.p99": "99e centile de {metric}",
"xpack.observability.customThreshold.rule.aggregators.rate": "Taux de {metric}",
"xpack.observability.customThreshold.rule.aggregators.sum": "Somme de {metric}",
"xpack.observability.customThreshold.rule.alertDetailsAppSection.criterion.subtitle": "Dernier {lookback} {timeLabel}",
"xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags": "+{number} de plus",
"xpack.observability.customThreshold.rule.alertFlyout.alertPerRedundantFilterError": "Il est possible que cette règle signale {matchedGroups} moins que prévu, car la requête de filtre comporte une correspondance pour {groupCount, plural, one {ce champ} other {ces champs}}. Pour en savoir plus, veuillez consulter {filteringAndGroupingLink}.",
"xpack.observability.customThreshold.rule.alertFlyout.condition": "Condition {conditionNumber}",
Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -20971,7 +20971,6 @@
"xpack.infra.logSourceConfiguration.missingMessageFieldErrorMessage": "データビューには{messageField}フィールドが必要です。",
"xpack.infra.logSourceErrorPage.savedObjectNotFoundErrorMessage": "{savedObjectType}:{savedObjectId}が見つかりませんでした",
"xpack.infra.metadataEmbeddable.errorMessage": "データの読み込みエラーが発生しました。{refetch}し、ホスト詳細をもう一度開いてください。",
"xpack.infra.metrics.alertDetailsAppSection.criterion.subtitle": "過去{lookback} {timeLabel}",
"xpack.infra.metrics.alertFlyout.alertPerRedundantFilterError": "このルールは想定未満の{matchedGroups}に対してアラートを通知できます。フィルタークエリには{groupCount, plural, one {このフィールド} other {これらのフィールド}}の完全一致が含まれるためです。詳細については、{filteringAndGroupingLink}を参照してください。",
"xpack.infra.metrics.alertFlyout.customEquationEditor.aggregationLabel": "集約{name}",
"xpack.infra.metrics.alertFlyout.customEquationEditor.fieldLabel": "フィールド{name}",
Expand Down Expand Up @@ -29735,7 +29734,6 @@
"xpack.observability.customThreshold.rule.aggregators.p99": "{metric}の99パーセンタイル",
"xpack.observability.customThreshold.rule.aggregators.rate": "{metric}の比率",
"xpack.observability.customThreshold.rule.aggregators.sum": "{metric}の合計",
"xpack.observability.customThreshold.rule.alertDetailsAppSection.criterion.subtitle": "過去{lookback} {timeLabel}",
"xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags": "その他{number}",
"xpack.observability.customThreshold.rule.alertFlyout.alertPerRedundantFilterError": "このルールは想定未満の{matchedGroups}に対してアラートを通知できます。フィルタークエリには{groupCount, plural, one {このフィールド} other {これらのフィールド}}の完全一致が含まれるためです。詳細については、{filteringAndGroupingLink}を参照してください。",
"xpack.observability.customThreshold.rule.alertFlyout.condition": "条件{conditionNumber}",
Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -21010,7 +21010,6 @@
"xpack.infra.logSourceConfiguration.missingMessageFieldErrorMessage": "数据视图必须包含 {messageField} 字段。",
"xpack.infra.logSourceErrorPage.savedObjectNotFoundErrorMessage": "无法找到该{savedObjectType}:{savedObjectId}",
"xpack.infra.metadataEmbeddable.errorMessage": "加载数据时出错。尝试{refetch}并再次打开主机详情。",
"xpack.infra.metrics.alertDetailsAppSection.criterion.subtitle": "过去 {lookback} {timeLabel}",
"xpack.infra.metrics.alertFlyout.alertPerRedundantFilterError": "此规则可能针对低于预期的 {matchedGroups} 告警,因为筛选查询包含{groupCount, plural, one {此字段} other {这些字段}}的匹配项。有关更多信息,请参阅 {filteringAndGroupingLink}。",
"xpack.infra.metrics.alertFlyout.customEquationEditor.aggregationLabel": "聚合 {name}",
"xpack.infra.metrics.alertFlyout.customEquationEditor.fieldLabel": "字段 {name}",
Expand Down Expand Up @@ -29775,7 +29774,6 @@
"xpack.observability.customThreshold.rule.aggregators.p99": "{metric} 的第 99 个百分位",
"xpack.observability.customThreshold.rule.aggregators.rate": "{metric} 的比率",
"xpack.observability.customThreshold.rule.aggregators.sum": "{metric} 的总和",
"xpack.observability.customThreshold.rule.alertDetailsAppSection.criterion.subtitle": "过去 {lookback} {timeLabel}",
"xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags": "+ 另外 {number} 个",
"xpack.observability.customThreshold.rule.alertFlyout.alertPerRedundantFilterError": "此规则可能针对低于预期的 {matchedGroups} 告警,因为筛选查询包含{groupCount, plural, one {此字段} other {这些字段}}的匹配项。有关更多信息,请参阅 {filteringAndGroupingLink}。",
"xpack.observability.customThreshold.rule.alertFlyout.condition": "条件 {conditionNumber}",
Expand Down