diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/alert_details_app_section.tsx similarity index 93% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/alert_details_app_section.tsx index 49c9da82e9511..8dade80f8a7d4 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/alert_details_app_section.tsx @@ -9,8 +9,8 @@ import React, { useEffect } from 'react'; import { EuiFlexGroup, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AlertDetailsAppSectionProps } from '@kbn/observability-plugin/public'; -import { useKibana } from '../../../../hooks/use_kibana'; -import { useFetchSloDetails } from '../../../../hooks/use_fetch_slo_details'; +import { useKibana } from '../../hooks/use_kibana'; +import { useFetchSloDetails } from '../../hooks/use_fetch_slo_details'; import { CustomAlertDetailsPanel } from './components/custom_panels/custom_panels'; import { ErrorRatePanel } from './components/error_rate/error_rate_panel'; import { BurnRateAlert, BurnRateRule } from './types'; diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/apm/apm_alert_details.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/apm/apm_alert_details.tsx similarity index 100% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/apm/apm_alert_details.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/apm/apm_alert_details.tsx diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/apm/embeddable_root.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/apm/embeddable_root.tsx similarity index 100% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/apm/embeddable_root.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/apm/embeddable_root.tsx diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx similarity index 92% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx index 418f7c5d08d41..1a75a30766423 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx @@ -9,7 +9,7 @@ import { GetSLOResponse } from '@kbn/slo-schema'; import React from 'react'; import { LogRateAnalysisPanel } from './log_rate_analysis_panel'; import { BurnRateAlert, BurnRateRule } from '../../../types'; -import { useLicense } from '../../../../../../../hooks/use_license'; +import { useLicense } from '../../../../../hooks/use_license'; interface Props { slo: GetSLOResponse; diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.test.ts b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.test.ts rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.test.ts diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.ts b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.ts rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/helpers/log_rate_analysis_query.ts diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/log_rate_analysis_panel.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/log_rate_analysis_panel.tsx similarity index 98% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/log_rate_analysis_panel.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/log_rate_analysis_panel.tsx index 4a43fb85be824..69826dd64dc14 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_kql/log_rate_analysis_panel.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_kql/log_rate_analysis_panel.tsx @@ -23,11 +23,11 @@ import { colorTransformer } from '@kbn/observability-shared-plugin/common'; import { KQLCustomIndicator, DurationUnit } from '@kbn/slo-schema'; import { i18n } from '@kbn/i18n'; import type { Message } from '@kbn/observability-ai-assistant-plugin/public'; -import type { WindowSchema } from '../../../../../../../typings'; -import { TimeRange } from '../../../../../error_rate_chart/use_lens_definition'; +import type { WindowSchema } from '../../../../../typings'; +import { TimeRange } from '../../../../slo/error_rate_chart/use_lens_definition'; import { BurnRateAlert, BurnRateRule } from '../../../types'; import { getActionGroupFromReason } from '../../../utils/alert'; -import { useKibana } from '../../../../../../../hooks/use_kibana'; +import { useKibana } from '../../../../../hooks/use_kibana'; import { getESQueryForLogRateAnalysis } from './helpers/log_rate_analysis_query'; function getDataTimeRange( timeRange: { gte: string; lte?: string }, diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_panels.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_panels.tsx similarity index 100% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/custom_panels/custom_panels.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/custom_panels/custom_panels.tsx diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/error_rate/error_rate_panel.tsx b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/error_rate/error_rate_panel.tsx similarity index 95% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/error_rate/error_rate_panel.tsx rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/components/error_rate/error_rate_panel.tsx index 1c371ea1abd30..0e8cc17757c37 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/components/error_rate/error_rate_panel.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/components/error_rate/error_rate_panel.tsx @@ -23,9 +23,9 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { ALERT_EVALUATION_VALUE, ALERT_TIME_RANGE } from '@kbn/rule-data-utils'; import { GetSLOResponse } from '@kbn/slo-schema'; import React from 'react'; -import { useKibana } from '../../../../../../hooks/use_kibana'; -import { ErrorRateChart } from '../../../../error_rate_chart'; -import { TimeRange } from '../../../../error_rate_chart/use_lens_definition'; +import { useKibana } from '../../../../hooks/use_kibana'; +import { ErrorRateChart } from '../../../slo/error_rate_chart'; +import { TimeRange } from '../../../slo/error_rate_chart/use_lens_definition'; import { BurnRateAlert } from '../../types'; import { getActionGroupWindow } from '../../utils/alert'; import { getLastDurationInUnit } from '../../utils/last_duration_i18n'; @@ -153,7 +153,7 @@ export function ErrorRatePanel({ alert, slo, isLoading }: Props) { dataTimeRange={dataTimeRange} alertTimeRange={alertTimeRange} threshold={actionGroupWindow!.burnRateThreshold} - showErrorRateAsLine + variant="danger" /> diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/types.ts b/x-pack/plugins/observability_solution/slo/public/components/alert_details/types.ts similarity index 76% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/types.ts rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/types.ts index 71aeb901d2b84..4592f4e2b4f1d 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/types.ts +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/types.ts @@ -7,8 +7,8 @@ import type { Rule } from '@kbn/alerting-plugin/common'; import type { TopAlert } from '@kbn/observability-plugin/public'; -import type { BurnRateRuleParams } from '../../../../typings/slo'; -export type { TimeRange } from '../../error_rate_chart/use_lens_definition'; +import type { BurnRateRuleParams } from '../../typings/slo'; +export type { TimeRange } from '../slo/error_rate_chart/use_lens_definition'; export type BurnRateRule = Rule; export type BurnRateAlert = TopAlert; diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/alert.ts b/x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/alert.ts similarity index 92% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/alert.ts rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/alert.ts index 9857973446d16..cf47d6949c796 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/alert.ts +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/alert.ts @@ -10,9 +10,9 @@ import { HIGH_PRIORITY_ACTION_ID, LOW_PRIORITY_ACTION_ID, MEDIUM_PRIORITY_ACTION_ID, -} from '../../../../../../common/constants'; +} from '../../../../common/constants'; import { BurnRateAlert } from '../types'; -import { WindowSchema } from '../../../../../typings'; +import { WindowSchema } from '../../../typings'; export function getActionGroupFromReason(reason: string): string { const prefix = reason.split(':')[0]?.toLowerCase() ?? undefined; diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/last_duration_i18n.ts b/x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/last_duration_i18n.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/last_duration_i18n.ts rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/last_duration_i18n.ts index cda5f292a8a8e..a1b34bf427f9a 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/last_duration_i18n.ts +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/last_duration_i18n.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import moment from 'moment'; -import { TimeRange } from '../../../error_rate_chart/use_lens_definition'; +import { TimeRange } from '../../slo/error_rate_chart/use_lens_definition'; export function getLastDurationInUnit(timeRange: TimeRange): string { const duration = moment.duration(moment(timeRange.to).diff(timeRange.from)); diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/time_range.ts b/x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/time_range.ts similarity index 92% rename from x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/time_range.ts rename to x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/time_range.ts index 0f5358978478e..9fd813dff5e90 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/utils/time_range.ts +++ b/x-pack/plugins/observability_solution/slo/public/components/alert_details/utils/time_range.ts @@ -6,7 +6,7 @@ */ import type { DateRange } from '@kbn/alerting-plugin/common'; import { ALERT_TIME_RANGE } from '@kbn/rule-data-utils'; -import { TimeRange } from '../../../error_rate_chart/use_lens_definition'; +import { TimeRange } from '../../slo/error_rate_chart/use_lens_definition'; import { BurnRateAlert } from '../types'; import { getActionGroupWindow } from './alert'; diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate.test.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate.test.tsx deleted file mode 100644 index 5185fa73758d1..0000000000000 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate.test.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 { screen } from '@testing-library/react'; -import React from 'react'; - -import { buildSlo } from '../../../data/slo/slo'; -import { render } from '../../../utils/test_helper'; -import { BurnRate } from './burn_rate'; - -describe('BurnRate', () => { - it("displays '--' when burn rate is 'undefined'", async () => { - const slo = buildSlo(); - render(); - - expect(screen.queryByTestId('sloDetailsBurnRateStat')).toHaveTextContent('--'); - }); - - it("displays the burn rate value when not 'undefined'", async () => { - const slo = buildSlo(); - render(); - - expect(screen.queryByTestId('sloDetailsBurnRateStat')).toHaveTextContent('3.4x'); - }); - - it("displays the burn rate value when '0'", async () => { - const slo = buildSlo(); - render(); - - expect(screen.queryByTestId('sloDetailsBurnRateStat')).toHaveTextContent('0x'); - }); -}); diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate.tsx deleted file mode 100644 index 9d32524a2ce58..0000000000000 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate.tsx +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat, EuiText, EuiTextColor } from '@elastic/eui'; -import numeral from '@elastic/numeral'; -import { i18n } from '@kbn/i18n'; -import { SLODefinitionResponse } from '@kbn/slo-schema'; -import moment from 'moment'; -import React from 'react'; -import { toDuration, toMinutes } from '../../../utils/slo/duration'; - -export interface BurnRateParams { - slo: SLODefinitionResponse; - threshold: number; - burnRate?: number; - isLoading?: boolean; -} - -type Status = 'NO_DATA' | 'BREACHED' | 'OK'; - -function getTitleFromStatus(status: Status): string { - if (status === 'NO_DATA') - return i18n.translate('xpack.slo.burnRate.noDataStatusTitle', { - defaultMessage: 'No value', - }); - if (status === 'BREACHED') - return i18n.translate('xpack.slo.burnRate.breachedStatustTitle', { - defaultMessage: 'Critical value breached', - }); - - return i18n.translate('xpack.slo.burnRate.okStatusTitle', { - defaultMessage: 'Acceptable value', - }); -} - -function getSubtitleFromStatus( - status: Status, - burnRate: number | undefined = 1, - slo: SLODefinitionResponse -): string { - if (status === 'NO_DATA') - return i18n.translate('xpack.slo.burnRate.noDataStatusSubtitle', { - defaultMessage: 'Waiting for more data.', - }); - if (status === 'BREACHED') - return i18n.translate('xpack.slo.burnRate.breachedStatustSubtitle', { - defaultMessage: 'At current rate, the error budget will be exhausted in {hour} hours.', - values: { - hour: numeral( - moment - .duration(toMinutes(toDuration(slo.timeWindow.duration)) / burnRate, 'minutes') - .asHours() - ).format('0'), - }, - }); - - return i18n.translate('xpack.slo.burnRate.okStatusSubtitle', { - defaultMessage: 'There is no risk of error budget exhaustion.', - }); -} - -export function BurnRate({ threshold, burnRate, slo, isLoading }: BurnRateParams) { - const status: Status = - burnRate === undefined ? 'NO_DATA' : burnRate > threshold ? 'BREACHED' : 'OK'; - const color = status === 'NO_DATA' ? 'subdued' : status === 'BREACHED' ? 'danger' : 'success'; - - return ( - - - - - -
{getTitleFromStatus(status)}
-
-
- - - {getSubtitleFromStatus(status, burnRate, slo)} - - -
- - - - - - {i18n.translate('xpack.slo.burnRate.threshold', { - defaultMessage: 'Threshold is {threshold}x', - values: { threshold: numeral(threshold).format('0.[00]') }, - })} - - - } - /> - - -
-
- ); -} diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate_header.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate_header.tsx deleted file mode 100644 index 4c878735a5857..0000000000000 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rate_header.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 { EuiButtonGroup, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { SloTabId } from '../../../pages/slo_details/components/slo_details'; -import { BurnRateOption } from './burn_rates'; -interface Props { - burnRateOption: BurnRateOption; - setBurnRateOption: (option: BurnRateOption) => void; - burnRateOptions: BurnRateOption[]; - selectedTabId: SloTabId; -} -export function BurnRateHeader({ - burnRateOption, - burnRateOptions, - setBurnRateOption, - selectedTabId, -}: Props) { - const onBurnRateOptionChange = (optionId: string) => { - const selected = burnRateOptions.find((opt) => opt.id === optionId) ?? burnRateOptions[0]; - setBurnRateOption(selected); - }; - return ( - - - -

- {i18n.translate('xpack.slo.burnRate.title', { - defaultMessage: 'Burn rate', - })} -

-
-
- {selectedTabId !== 'history' && ( - - ({ - id: opt.id, - label: opt.label, - 'aria-label': opt.ariaLabel, - }))} - idSelected={burnRateOption.id} - onChange={onBurnRateOptionChange} - buttonSize="compressed" - /> - - )} -
- ); -} diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rates.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rates.tsx deleted file mode 100644 index a6c02572d10fe..0000000000000 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/burn_rates.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; -import { SLOWithSummaryResponse } from '@kbn/slo-schema'; -import moment from 'moment'; -import React, { useEffect, useState } from 'react'; -import { TimeBounds } from '../../../pages/slo_details/types'; -import { TimeRange } from '../error_rate_chart/use_lens_definition'; -import { SloTabId } from '../../../pages/slo_details/components/slo_details'; -import { BurnRateHeader } from './burn_rate_header'; -import { useFetchSloBurnRates } from '../../../hooks/use_fetch_slo_burn_rates'; -import { ErrorRateChart } from '../error_rate_chart'; -import { BurnRate } from './burn_rate'; - -interface Props { - slo: SLOWithSummaryResponse; - isAutoRefreshing?: boolean; - burnRateOptions: BurnRateOption[]; - selectedTabId: SloTabId; - range?: TimeRange; - onBrushed?: (timeBounds: TimeBounds) => void; -} - -export interface BurnRateOption { - id: string; - label: string; - windowName: string; - threshold: number; - duration: number; - ariaLabel: string; -} - -function getWindowsFromOptions(opts: BurnRateOption[]): Array<{ name: string; duration: string }> { - return opts.map((opt) => ({ name: opt.windowName, duration: `${opt.duration}h` })); -} - -export function BurnRates({ - slo, - isAutoRefreshing, - burnRateOptions, - selectedTabId, - range, - onBrushed, -}: Props) { - const [burnRateOption, setBurnRateOption] = useState(burnRateOptions[0]); - const { isLoading, data } = useFetchSloBurnRates({ - slo, - shouldRefetch: isAutoRefreshing, - windows: getWindowsFromOptions(burnRateOptions), - }); - - useEffect(() => { - if (burnRateOptions.length) { - setBurnRateOption(burnRateOptions[0]); - } - }, [burnRateOptions]); - - const dataTimeRange = range ?? { - from: moment().subtract(burnRateOption.duration, 'hour').toDate(), - to: new Date(), - }; - - const threshold = burnRateOption.threshold; - const burnRate = data?.burnRates.find( - (curr) => curr.name === burnRateOption.windowName - )?.burnRate; - - return ( - - - - - {selectedTabId !== 'history' && ( - - - - )} - - - - - - - ); -} diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx index fec552354102e..fad8077e7811e 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx @@ -9,7 +9,6 @@ import { ViewMode } from '@kbn/embeddable-plugin/public'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; import moment from 'moment'; import React from 'react'; -import { SloTabId } from '../../../pages/slo_details/components/slo_details'; import { TimeBounds } from '../../../pages/slo_details/types'; import { useKibana } from '../../../hooks/use_kibana'; import { getDelayInSecondsFromSLO } from '../../../utils/slo/get_delay_in_seconds_from_slo'; @@ -18,12 +17,11 @@ import { AlertAnnotation, TimeRange, useLensDefinition } from './use_lens_defini interface Props { slo: SLOWithSummaryResponse; dataTimeRange: TimeRange; - threshold: number; + threshold?: number; alertTimeRange?: TimeRange; - showErrorRateAsLine?: boolean; annotations?: AlertAnnotation[]; - selectedTabId?: SloTabId; onBrushed?: (timeBounds: TimeBounds) => void; + variant?: 'success' | 'danger'; } export function ErrorRateChart({ @@ -31,10 +29,9 @@ export function ErrorRateChart({ dataTimeRange, threshold, alertTimeRange, - showErrorRateAsLine, annotations, onBrushed, - selectedTabId, + variant = 'success', }: Props) { const { lens: { EmbeddableComponent }, @@ -45,8 +42,7 @@ export function ErrorRateChart({ alertTimeRange, dataTimeRange, annotations, - showErrorRateAsLine, - selectedTabId, + variant, }); const delayInSeconds = getDelayInSecondsFromSLO(slo); diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/use_lens_definition.ts b/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/use_lens_definition.ts index d562706f78129..db7eb43f71188 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/use_lens_definition.ts +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/use_lens_definition.ts @@ -13,7 +13,6 @@ import { ALL_VALUE, SLOWithSummaryResponse } from '@kbn/slo-schema'; import moment from 'moment'; import { v4 as uuidv4 } from 'uuid'; import { SLO_DESTINATION_INDEX_PATTERN } from '../../../../common/constants'; -import { SloTabId } from '../../../pages/slo_details/components/slo_details'; import { getLensDefinitionInterval } from './utils'; export interface TimeRange { @@ -26,25 +25,27 @@ export interface AlertAnnotation { total: number; } +interface Props { + slo: SLOWithSummaryResponse; + threshold?: number; + dataTimeRange: TimeRange; + alertTimeRange?: TimeRange; + annotations?: AlertAnnotation[]; + variant: 'success' | 'danger'; +} + export function useLensDefinition({ slo, threshold, dataTimeRange, alertTimeRange, annotations, - showErrorRateAsLine, - selectedTabId, -}: { - slo: SLOWithSummaryResponse; - threshold: number; - dataTimeRange: TimeRange; - alertTimeRange?: TimeRange; - annotations?: AlertAnnotation[]; - showErrorRateAsLine?: boolean; - selectedTabId?: SloTabId; -}): TypedLensByValueInput['attributes'] { + variant, +}: Props): TypedLensByValueInput['attributes'] { const { euiTheme } = useEuiTheme(); + const lineColor = variant === 'danger' ? euiTheme.colors.danger : euiTheme.colors.success; + const interval = getLensDefinitionInterval(dataTimeRange, slo); return { @@ -88,18 +89,18 @@ export function useLensDefinition({ layerId: '8730e8af-7dac-430e-9cef-3b9989ff0866', accessors: ['9f69a7b0-34b9-4b76-9ff7-26dc1a06ec14'], position: 'top', - seriesType: !!showErrorRateAsLine ? 'line' : 'area', + seriesType: 'line', showGridlines: false, layerType: 'data', xAccessor: '627ded04-eae0-4437-83a1-bbb6138d2c3b', yConfig: [ { forAccessor: '9f69a7b0-34b9-4b76-9ff7-26dc1a06ec14', - color: !!showErrorRateAsLine ? euiTheme.colors.primary : euiTheme.colors.danger, + color: lineColor, }, ], }, - ...(selectedTabId !== 'history' + ...(threshold !== undefined ? [ { layerId: '34298f84-681e-4fa3-8107-d6facb32ed92', @@ -398,66 +399,69 @@ export function useLensDefinition({ incompleteColumns: {}, sampling: 1, }, - '34298f84-681e-4fa3-8107-d6facb32ed92': { - linkToLayers: [], - columns: { - '0a42b72b-cd5a-4d59-81ec-847d97c268e6X0': { - label: `Part of ${threshold}x`, - dataType: 'number', - operationType: 'math', - isBucketed: false, - scale: 'ratio', - params: { - // @ts-ignore - tinymathAst: { - type: 'function', - name: 'multiply', - args: [ - { - type: 'function', - name: 'subtract', - args: [1, slo.objective.target], - location: { - min: 1, - max: 9, + + ...(threshold !== undefined && { + '34298f84-681e-4fa3-8107-d6facb32ed92': { + linkToLayers: [], + columns: { + '0a42b72b-cd5a-4d59-81ec-847d97c268e6X0': { + label: `Part of ${threshold}x`, + dataType: 'number', + operationType: 'math', + isBucketed: false, + scale: 'ratio', + params: { + // @ts-ignore + tinymathAst: { + type: 'function', + name: 'multiply', + args: [ + { + type: 'function', + name: 'subtract', + args: [1, slo.objective.target], + location: { + min: 1, + max: 9, + }, + text: `1 - ${slo.objective.target}`, }, - text: `1 - ${slo.objective.target}`, + threshold, + ], + location: { + min: 0, + max: 17, }, - threshold, - ], - location: { - min: 0, - max: 17, + text: `(1 - ${slo.objective.target}) * ${threshold}`, }, - text: `(1 - ${slo.objective.target}) * ${threshold}`, }, + references: [], + customLabel: true, }, - references: [], - customLabel: true, - }, - '0a42b72b-cd5a-4d59-81ec-847d97c268e6': { - label: `${numeral(threshold).format('0.[00]')}x`, - dataType: 'number', - operationType: 'formula', - isBucketed: false, - scale: 'ratio', - params: { - // @ts-ignore - formula: `(1 - ${slo.objective.target}) * ${threshold}`, - isFormulaBroken: false, + '0a42b72b-cd5a-4d59-81ec-847d97c268e6': { + label: `${numeral(threshold).format('0.[00]')}x`, + dataType: 'number', + operationType: 'formula', + isBucketed: false, + scale: 'ratio', + params: { + // @ts-ignore + formula: `(1 - ${slo.objective.target}) * ${threshold}`, + isFormulaBroken: false, + }, + references: ['0a42b72b-cd5a-4d59-81ec-847d97c268e6X0'], + customLabel: true, }, - references: ['0a42b72b-cd5a-4d59-81ec-847d97c268e6X0'], - customLabel: true, }, + columnOrder: [ + '0a42b72b-cd5a-4d59-81ec-847d97c268e6', + '0a42b72b-cd5a-4d59-81ec-847d97c268e6X0', + ], + sampling: 1, + ignoreGlobalFilters: false, + incompleteColumns: {}, }, - columnOrder: [ - '0a42b72b-cd5a-4d59-81ec-847d97c268e6', - '0a42b72b-cd5a-4d59-81ec-847d97c268e6X0', - ], - sampling: 1, - ignoreGlobalFilters: false, - incompleteColumns: {}, - }, + }), }, }, indexpattern: { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_panel.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_panel.tsx new file mode 100644 index 0000000000000..6b95c84abd59a --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_panel.tsx @@ -0,0 +1,133 @@ +/* + * 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 { EuiButtonGroup, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SLOWithSummaryResponse } from '@kbn/slo-schema'; +import moment from 'moment'; +import React, { useEffect, useState } from 'react'; +import { ErrorRateChart } from '../../../../components/slo/error_rate_chart'; +import { useFetchSloBurnRates } from '../../../../hooks/use_fetch_slo_burn_rates'; +import { BurnRateWindow, useFetchBurnRateWindows } from '../../hooks/use_fetch_burn_rate_windows'; +import { BurnRateStatus } from './burn_rate_status'; +import { getStatus } from './utils'; + +interface Props { + slo: SLOWithSummaryResponse; + isAutoRefreshing?: boolean; +} + +export function BurnRatePanel({ slo, isAutoRefreshing }: Props) { + const burnRateWindows = useFetchBurnRateWindows(slo); + const [selectedWindow, setSelectedwindow] = useState(burnRateWindows[0]); + const { isLoading, data } = useFetchSloBurnRates({ + slo, + shouldRefetch: isAutoRefreshing, + windows: toPayload(burnRateWindows), + }); + + useEffect(() => { + if (burnRateWindows.length > 0) { + setSelectedwindow(burnRateWindows[0]); + } + }, [burnRateWindows]); + + const onBurnRateOptionChange = (windowName: string) => { + const selected = burnRateWindows.find((opt) => opt.name === windowName) ?? burnRateWindows[0]; + setSelectedwindow(selected); + }; + + const threshold = selectedWindow.threshold; + const longWindowBurnRate = + data?.burnRates.find((curr) => curr.name === longWindowName(selectedWindow.name))?.burnRate ?? + 0; + const shortWindowbBurnRate = + data?.burnRates.find((curr) => curr.name === shortWindowName(selectedWindow.name))?.burnRate ?? + 0; + + const currentStatus = getStatus(threshold, longWindowBurnRate, shortWindowbBurnRate); + + return ( + + + + + +

+ {i18n.translate('xpack.slo.burnRates.burnRatePanelTitle', { + defaultMessage: 'Burn rate', + })} +

+
+
+ + ({ + id: burnRateWindow.name, + label: burnRateWindowLabel(burnRateWindow), + 'aria-label': burnRateWindowLabel(burnRateWindow), + }))} + idSelected={selectedWindow.name} + onChange={onBurnRateOptionChange} + buttonSize="compressed" + /> + +
+ + + + + + + + + +
+
+ ); +} + +const burnRateWindowLabel = (option: BurnRateWindow) => + i18n.translate('xpack.slo.burnRates.optionLabel', { + defaultMessage: '{duration, plural, one {# hour} other {# hours}}', + values: { duration: option.longWindow.value }, + }); + +const longWindowName = (window: string) => `${window}_LONG`; +const shortWindowName = (window: string) => `${window}_SHORT`; +const toPayload = ( + burnRateWindows: BurnRateWindow[] +): Array<{ name: string; duration: string }> => { + return burnRateWindows.flatMap((window) => [ + { + name: longWindowName(window.name), + duration: `${window.longWindow.value}${window.longWindow.unit}`, + }, + { + name: shortWindowName(window.name), + duration: `${window.shortWindow.value}${window.shortWindow.unit}`, + }, + ]); +}; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_status.test.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_status.test.tsx new file mode 100644 index 0000000000000..a8455dcbc42fc --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_status.test.tsx @@ -0,0 +1,91 @@ +/* + * 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 { screen } from '@testing-library/react'; +import React from 'react'; +import { render } from '../../../../utils/test_helper'; +import { DEFAULT_BURN_RATE_WINDOWS } from '../../hooks/use_fetch_burn_rate_windows'; +import { BurnRateStatus } from './burn_rate_status'; + +describe('BurnRateStatus', () => { + it('displays loading spinner when burn rates are being fetched', async () => { + render( + + ); + + expect(screen.queryByTestId('loadingSpinner')).toBeDefined(); + }); + + it("displays the 'breached' status", async () => { + render( + + ); + + expect(screen.queryByTestId('title')).toHaveTextContent('Breached'); + expect(screen.queryByTestId('description')).toHaveTextContent( + 'The 1h burn rate is 22.32x and the 5m burn rate is 18.45x.' + ); + }); + + it("displays the 'recovering' status", async () => { + render( + + ); + + expect(screen.queryByTestId('title')).toHaveTextContent('Recovering'); + expect(screen.queryByTestId('description')).toHaveTextContent( + 'The 1h burn rate is 22.32x and the 5m burn rate is 1.2x.' + ); + }); + + it("displays the 'Increasing' status", async () => { + render( + + ); + + expect(screen.queryByTestId('title')).toHaveTextContent('Increasing'); + expect(screen.queryByTestId('description')).toHaveTextContent( + 'The 1h burn rate is 1.32x and the 5m burn rate is 18.45x.' + ); + }); + + it("displays the 'Acceptable' status", async () => { + render( + + ); + + expect(screen.queryByTestId('title')).toHaveTextContent('Acceptable value'); + expect(screen.queryByTestId('description')).toHaveTextContent( + 'The 1h burn rate is 2.32x and the 5m burn rate is 1.45x.' + ); + }); +}); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_status.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_status.tsx new file mode 100644 index 0000000000000..ed2be19aa76fd --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/burn_rate_status.tsx @@ -0,0 +1,129 @@ +/* + * 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 { + EuiFlexGroup, + EuiFlexItem, + EuiLoadingSpinner, + EuiPanel, + EuiStat, + EuiText, + EuiTextColor, +} from '@elastic/eui'; +import numeral from '@elastic/numeral'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { BurnRateWindow } from '../../hooks/use_fetch_burn_rate_windows'; +import { getStatus } from './utils'; + +export interface BurnRateParams { + isLoading: boolean; + selectedWindow: BurnRateWindow; + longWindowBurnRate: number; + shortWindowBurnRate: number; +} + +export type Status = 'BREACHED' | 'RECOVERING' | 'INCREASING' | 'ACCEPTABLE'; + +export function BurnRateStatus({ + selectedWindow, + longWindowBurnRate, + shortWindowBurnRate, + isLoading, +}: BurnRateParams) { + const threshold = selectedWindow.threshold; + const status = getStatus(threshold, longWindowBurnRate, shortWindowBurnRate); + const color = getColor(status); + + if (isLoading) { + return ; + } + + return ( + + + + + +
{getTitle(status)}
+
+
+ + + {getDescription(shortWindowBurnRate, longWindowBurnRate, selectedWindow)} + + +
+ + + + + + {i18n.translate('xpack.slo.burnRate.thresholdLabel', { + defaultMessage: 'Threshold', + })} + + + } + /> + + +
+
+ ); +} + +function getColor(status: Status) { + return status === 'BREACHED' ? 'danger' : status === 'INCREASING' ? 'warning' : 'success'; +} + +function getTitle(status: Status): string { + switch (status) { + case 'BREACHED': + return i18n.translate('xpack.slo.burnRate.breachedStatusTitle', { + defaultMessage: 'Breached', + }); + case 'INCREASING': + return i18n.translate('xpack.slo.burnRate.increasingStatusTitle', { + defaultMessage: 'Increasing', + }); + case 'RECOVERING': + return i18n.translate('xpack.slo.burnRate.recoveringStatusTitle', { + defaultMessage: 'Recovering', + }); + case 'ACCEPTABLE': + default: + return i18n.translate('xpack.slo.burnRate.acceptableStatusTitle', { + defaultMessage: 'Acceptable value', + }); + } +} + +function getDescription( + shortWindowBurnRate: number, + longWindowBurnRate: number, + selectedWindow: BurnRateWindow +): string { + return i18n.translate('xpack.slo.burnRate.subtitle', { + defaultMessage: + 'The {longWindowDuration} burn rate is {longWindowBurnRate}x and the {shortWindowDuration} burn rate is {shortWindowBurnRate}x.', + values: { + longWindowDuration: `${selectedWindow.longWindow.value}${selectedWindow.longWindow.unit}`, + longWindowBurnRate: numeral(longWindowBurnRate).format('0.[00]'), + shortWindowDuration: `${selectedWindow.shortWindow.value}${selectedWindow.shortWindow.unit}`, + shortWindowBurnRate: numeral(shortWindowBurnRate).format('0.[00]'), + }, + }); +} diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/utils.ts b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/utils.ts new file mode 100644 index 0000000000000..028231d5327b2 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/burn_rate_panel/utils.ts @@ -0,0 +1,27 @@ +/* + * 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 type { Status } from './burn_rate_status'; + +export function getStatus( + threshold: number, + longWindowBurnRate: number, + shortWindowBurnRate: number +): Status { + const isLongWindowBurnRateAboveThreshold = longWindowBurnRate > threshold; + const isShortWindowBurnRateAboveThreshold = shortWindowBurnRate > threshold; + const areBothBurnRatesAboveThreshold = + isLongWindowBurnRateAboveThreshold && isShortWindowBurnRateAboveThreshold; + + return areBothBurnRatesAboveThreshold + ? 'BREACHED' + : isLongWindowBurnRateAboveThreshold && !isShortWindowBurnRateAboveThreshold + ? 'RECOVERING' + : !isLongWindowBurnRateAboveThreshold && isShortWindowBurnRateAboveThreshold + ? 'INCREASING' + : 'ACCEPTABLE'; +} diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx index 45177fa0d73fe..b4d45269b15d4 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx @@ -7,17 +7,18 @@ import { EuiFlexGroup, EuiFlexItem, - EuiSpacer, + EuiPanel, EuiSuperDatePicker, + EuiTitle, OnRefreshProps, OnTimeChangeProps, } from '@elastic/eui'; import DateMath from '@kbn/datemath'; +import { i18n } from '@kbn/i18n'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; import React, { useMemo, useState } from 'react'; -import { BurnRates } from '../../../../components/slo/burn_rate/burn_rates'; +import { ErrorRateChart } from '../../../../components/slo/error_rate_chart'; import { useKibana } from '../../../../hooks/use_kibana'; -import { useBurnRateOptions } from '../../hooks/use_burn_rate_options'; import { TimeBounds } from '../../types'; import { EventsChartPanel } from '../events_chart_panel'; import { HistoricalDataCharts } from '../historical_data_charts'; @@ -31,7 +32,6 @@ export interface Props { export function SLODetailsHistory({ slo, isAutoRefreshing, selectedTabId }: Props) { const { uiSettings } = useKibana().services; - const { burnRateOptions } = useBurnRateOptions(slo); const [start, setStart] = useState(`now-${slo.timeWindow.duration}`); const [end, setEnd] = useState('now'); @@ -55,7 +55,7 @@ export function SLODetailsHistory({ slo, isAutoRefreshing, selectedTabId }: Prop }; return ( - <> + - - - - - - - - - + + + +

+ {i18n.translate('xpack.slo.sloDetailsHistory.h2.errorRatePanelTitle', { + defaultMessage: 'Error rate', + })} +

+
+
+ -
-
- +
+ + + + + + ); } diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx index 249984fb3ed56..498123b0d633c 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx @@ -5,12 +5,11 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup } from '@elastic/eui'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; import moment from 'moment'; import React, { useEffect, useState } from 'react'; -import { BurnRates } from '../../../components/slo/burn_rate/burn_rates'; -import { useBurnRateOptions } from '../hooks/use_burn_rate_options'; +import { BurnRatePanel } from './burn_rate_panel/burn_rate_panel'; import { EventsChartPanel } from './events_chart_panel'; import { HistoricalDataCharts } from './historical_data_charts'; import { SLODetailsHistory } from './history/slo_details_history'; @@ -32,8 +31,6 @@ export interface Props { selectedTabId: SloTabId; } export function SloDetails({ slo, isAutoRefreshing, selectedTabId }: Props) { - const { burnRateOptions } = useBurnRateOptions(slo); - const [range, setRange] = useState<{ from: Date; to: Date }>({ from: moment().subtract(1, 'day').toDate(), to: new Date(), @@ -50,39 +47,37 @@ export function SloDetails({ slo, isAutoRefreshing, selectedTabId }: Props) { return () => clearInterval(intervalId); }, [isAutoRefreshing]); - return selectedTabId === OVERVIEW_TAB_ID ? ( + if (selectedTabId === HISTORY_TAB_ID) { + return ( + + ); + } + + if (selectedTabId === ALERTS_TAB_ID) { + return ; + } + + return ( - - - + + - - - + + - - - + + - ) : selectedTabId === ALERTS_TAB_ID ? ( - - ) : ( - ); } diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/hooks/use_burn_rate_options.ts b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/hooks/use_burn_rate_options.ts deleted file mode 100644 index 1bb86de617fac..0000000000000 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/hooks/use_burn_rate_options.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 { htmlIdGenerator } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { SLOWithSummaryResponse } from '@kbn/slo-schema'; -import { BurnRateOption } from '../../../components/slo/burn_rate/burn_rates'; -import { useFetchRulesForSlo } from '../../../hooks/use_fetch_rules_for_slo'; - -export const DEFAULT_BURN_RATE_OPTIONS: BurnRateOption[] = [ - { - id: htmlIdGenerator()(), - label: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hour', - values: { duration: 1 }, - }), - ariaLabel: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hour', - values: { duration: 1 }, - }), - windowName: 'CRITICAL', - threshold: 14.4, - duration: 1, - }, - { - id: htmlIdGenerator()(), - label: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hours', - values: { duration: 6 }, - }), - ariaLabel: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hours', - values: { duration: 6 }, - }), - windowName: 'HIGH', - threshold: 6, - duration: 6, - }, - { - id: htmlIdGenerator()(), - label: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hours', - values: { duration: 24 }, - }), - ariaLabel: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hours', - values: { duration: 24 }, - }), - windowName: 'MEDIUM', - threshold: 3, - duration: 24, - }, - { - id: htmlIdGenerator()(), - ariaLabel: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hours', - values: { duration: 72 }, - }), - label: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration} hours', - values: { duration: 72 }, - }), - windowName: 'LOW', - threshold: 1, - duration: 72, - }, -]; - -export const useBurnRateOptions = (slo: SLOWithSummaryResponse) => { - const { data: rules } = useFetchRulesForSlo({ sloIds: [slo.id] }); - const burnRateOptions = - rules?.[slo.id]?.[0]?.params?.windows?.map((window) => ({ - id: htmlIdGenerator()(), - label: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration, plural, one {# hour} other {# hours}}', - values: { duration: window.longWindow.value }, - }), - ariaLabel: i18n.translate('xpack.slo.burnRates.fromRange.label', { - defaultMessage: '{duration, plural, one {# hour} other {# hours}}', - values: { duration: window.longWindow.value }, - }), - windowName: window.actionGroup, - threshold: window.burnRateThreshold, - duration: window.longWindow.value, - })) ?? DEFAULT_BURN_RATE_OPTIONS; - - return { burnRateOptions }; -}; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/hooks/use_fetch_burn_rate_windows.ts b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/hooks/use_fetch_burn_rate_windows.ts new file mode 100644 index 0000000000000..92664f55dd653 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/hooks/use_fetch_burn_rate_windows.ts @@ -0,0 +1,67 @@ +/* + * 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 { SLOWithSummaryResponse } from '@kbn/slo-schema'; +import { useEffect, useState } from 'react'; +import { useFetchRulesForSlo } from '../../../hooks/use_fetch_rules_for_slo'; +import { Duration } from '../../../typings'; + +export interface BurnRateWindow { + name: string; + threshold: number; + longWindow: Duration; + shortWindow: Duration; +} + +export const DEFAULT_BURN_RATE_WINDOWS: BurnRateWindow[] = [ + { + name: 'CRITICAL', + threshold: 14.4, + longWindow: { value: 1, unit: 'h' }, + shortWindow: { value: 5, unit: 'm' }, + }, + { + name: 'HIGH', + threshold: 6, + longWindow: { value: 6, unit: 'h' }, + shortWindow: { value: 30, unit: 'm' }, + }, + { + name: 'MEDIUM', + threshold: 3, + longWindow: { value: 24, unit: 'h' }, + shortWindow: { value: 2, unit: 'h' }, + }, + { + name: 'LOW', + threshold: 1, + longWindow: { value: 72, unit: 'h' }, + shortWindow: { value: 6, unit: 'h' }, + }, +]; + +export const useFetchBurnRateWindows = (slo: SLOWithSummaryResponse) => { + const sloId = slo.id; + const [burnRateWindows, setBurnRateWindows] = + useState(DEFAULT_BURN_RATE_WINDOWS); + const { data: rules, isLoading } = useFetchRulesForSlo({ sloIds: [sloId] }); + + useEffect(() => { + if (!isLoading && rules && rules[sloId]) { + setBurnRateWindows( + rules[sloId][0]?.params?.windows?.map((window) => ({ + name: window.actionGroup, + threshold: window.burnRateThreshold, + longWindow: window.longWindow, + shortWindow: window.shortWindow, + })) ?? DEFAULT_BURN_RATE_WINDOWS + ); + } + }, [rules, sloId, isLoading]); + + return burnRateWindows; +}; diff --git a/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts b/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts index 5861e5ffd9032..cea53c96ab0a0 100644 --- a/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts +++ b/x-pack/plugins/observability_solution/slo/public/rules/register_burn_rate_rule_type.ts @@ -73,7 +73,7 @@ export const registerBurnRateRuleType = ( defaultActionMessage: sloBurnRateDefaultActionMessage, defaultRecoveryMessage: sloBurnRateDefaultRecoveryMessage, alertDetailsAppSection: lazyWithContextProviders( - lazy(() => import('../components/slo/burn_rate/alert_details/alert_details_app_section')) + lazy(() => import('../components/alert_details/alert_details_app_section')) ), priority: 100, }); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 4339c2fb0310c..32e78303e7be3 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -43366,17 +43366,9 @@ "xpack.slo.budgetingMethod.occurrences": "Occurrences", "xpack.slo.budgetingMethod.timeslices": "Intervalles de temps", "xpack.slo.burnRate.alertDetails.logRateAnalysis.sectionTitle": "Analyse du taux de log", - "xpack.slo.burnRate.breachedStatustSubtitle": "Au rythme actuel, le budget d'erreur sera épuisé dans {hour} heures.", - "xpack.slo.burnRate.breachedStatustTitle": "Valeur critique dépassée", "xpack.slo.burnRate.durationLabel": "Dernièr(e)(s) {duration}", "xpack.slo.burnRate.exhaustionTimeLabel": "À ce rythme, l'ensemble du budget d'erreur sera épuisé dans {hour} heures.", - "xpack.slo.burnRate.noDataStatusSubtitle": "En attente de plus de données.", - "xpack.slo.burnRate.noDataStatusTitle": "Aucune valeur", - "xpack.slo.burnRate.okStatusSubtitle": "Aucun risque d'épuisement du budget d'erreurs.", - "xpack.slo.burnRate.okStatusTitle": "Valeur acceptable", - "xpack.slo.burnRate.threshold": "Le seuil est {threshold}x", "xpack.slo.burnRate.timeRangeBtnLegend": "Sélectionner la plage temporelle", - "xpack.slo.burnRate.title": "Taux d'avancement", "xpack.slo.burnRateEmbeddable.ariaLabel": "Taux d’avancement du SLO", "xpack.slo.burnRateEmbeddable.configuration.cancelButtonLabel": "Confirmer", "xpack.slo.burnRateEmbeddable.configuration.durationLabel": "Durée", @@ -43397,7 +43389,6 @@ "xpack.slo.burnRateRule.alertDetailsAppSection.summaryField.slo": "SLO", "xpack.slo.burnRateRuleEditor.h5.chooseASLOToMonitorLabel": "Choisir un SLO pour monitorer", "xpack.slo.burnRateRuleEditor.h5.defineMultipleBurnRateLabel": "Définir des fenêtres du taux d'avancement multiples", - "xpack.slo.burnRates.fromRange.label": "{duration, plural, one {# heure} other {# heures}}", "xpack.slo.burnRates.value": "{value} fois", "xpack.slo.create.errorNotification": "Un problème est survenu lors de la création de {name}", "xpack.slo.dataPreviewChart.noResultsLabel": "aucun résultat", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b4c96ee85f3d1..6607dff1c812a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -43330,17 +43330,9 @@ "xpack.slo.budgetingMethod.occurrences": "出現回数", "xpack.slo.budgetingMethod.timeslices": "タイムスライス", "xpack.slo.burnRate.alertDetails.logRateAnalysis.sectionTitle": "ログレート分析", - "xpack.slo.burnRate.breachedStatustSubtitle": "現在のレートでは、エラー予算は{hour}時間後に使い果たされます。", - "xpack.slo.burnRate.breachedStatustTitle": "重大値違反", "xpack.slo.burnRate.durationLabel": "前回の{duration}", "xpack.slo.burnRate.exhaustionTimeLabel": "このレートでは、全体のエラー予算は{hour}時間後に使い果たされます。", - "xpack.slo.burnRate.noDataStatusSubtitle": "その他のデータを待機中です。", - "xpack.slo.burnRate.noDataStatusTitle": "値なし", - "xpack.slo.burnRate.okStatusSubtitle": "エラー予算が枯渇するリスクはありません。", - "xpack.slo.burnRate.okStatusTitle": "許容値", - "xpack.slo.burnRate.threshold": "しきい値は{threshold}xです", "xpack.slo.burnRate.timeRangeBtnLegend": "時間範囲を選択", - "xpack.slo.burnRate.title": "バーンレート", "xpack.slo.burnRateEmbeddable.ariaLabel": "SLOバーンレート", "xpack.slo.burnRateEmbeddable.configuration.cancelButtonLabel": "確認", "xpack.slo.burnRateEmbeddable.configuration.durationLabel": "期間", @@ -43362,7 +43354,6 @@ "xpack.slo.burnRateRule.name": "{name}バーンレートルール", "xpack.slo.burnRateRuleEditor.h5.chooseASLOToMonitorLabel": "監視するSLOを選択", "xpack.slo.burnRateRuleEditor.h5.defineMultipleBurnRateLabel": "複数のバーンレート時間枠を定義", - "xpack.slo.burnRates.fromRange.label": "{duration, plural, other {#時間}}", "xpack.slo.burnRates.value": "{value}x", "xpack.slo.create.errorNotification": "{name}の作成中に問題が発生しました", "xpack.slo.dataPreviewChart.noResultsLabel": "結果なし", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 661a37969e6a5..70c3805ff3aaa 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -42675,17 +42675,9 @@ "xpack.slo.budgetingMethod.occurrences": "发生次数", "xpack.slo.budgetingMethod.timeslices": "时间片", "xpack.slo.burnRate.alertDetails.logRateAnalysis.sectionTitle": "日志速率分析", - "xpack.slo.burnRate.breachedStatustSubtitle": "按照当前的速率,错误预算将在 {hour} 小时后耗尽。", - "xpack.slo.burnRate.breachedStatustTitle": "已超出临界值", "xpack.slo.burnRate.durationLabel": "过去 {duration}", "xpack.slo.burnRate.exhaustionTimeLabel": "按照此速率,整个错误预算将在 {hour} 小时后耗尽。", - "xpack.slo.burnRate.noDataStatusSubtitle": "等待更多数据。", - "xpack.slo.burnRate.noDataStatusTitle": "无值", - "xpack.slo.burnRate.okStatusSubtitle": "没有错误预算耗尽风险。", - "xpack.slo.burnRate.okStatusTitle": "可接受的值", - "xpack.slo.burnRate.threshold": "阈值为 {threshold}x", "xpack.slo.burnRate.timeRangeBtnLegend": "选择时间范围", - "xpack.slo.burnRate.title": "消耗速度", "xpack.slo.burnRateEmbeddable.ariaLabel": "SLO 消耗速度", "xpack.slo.burnRateEmbeddable.configuration.cancelButtonLabel": "确认", "xpack.slo.burnRateEmbeddable.configuration.durationLabel": "持续时间", @@ -42707,7 +42699,6 @@ "xpack.slo.burnRateRule.name": "{name} 消耗速度规则", "xpack.slo.burnRateRuleEditor.h5.chooseASLOToMonitorLabel": "选择要监测的 SLO", "xpack.slo.burnRateRuleEditor.h5.defineMultipleBurnRateLabel": "定义多个消耗速度窗口", - "xpack.slo.burnRates.fromRange.label": "{duration, plural, other {# 小时}}", "xpack.slo.burnRates.value": "{value} 倍", "xpack.slo.create.errorNotification": "创建 {name} 时出现问题", "xpack.slo.dataPreviewChart.noResultsLabel": "无结果",