mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
chore(slo): improve calendar slo (#159069)
This commit is contained in:
parent
6cf0c8c564
commit
1a8e0d1207
27 changed files with 194 additions and 83 deletions
25
packages/kbn-slo-schema/src/schema/time_window.test.ts
Normal file
25
packages/kbn-slo-schema/src/schema/time_window.test.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Duration } from '../..';
|
||||
import { DurationUnit } from '../models/duration';
|
||||
import { rollingTimeWindowSchema } from './time_window';
|
||||
|
||||
describe('time window schema', () => {
|
||||
it('type guards correctly', () => {
|
||||
expect(
|
||||
rollingTimeWindowSchema.is({ duration: new Duration(1, DurationUnit.Month), type: 'rolling' })
|
||||
).toBe(true);
|
||||
expect(
|
||||
rollingTimeWindowSchema.is({
|
||||
duration: new Duration(1, DurationUnit.Month),
|
||||
type: 'calendarAligned',
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
|
@ -9,16 +9,24 @@
|
|||
import * as t from 'io-ts';
|
||||
import { durationType } from './duration';
|
||||
|
||||
const rollingTimeWindowTypeSchema = t.literal('rolling');
|
||||
const rollingTimeWindowSchema = t.type({
|
||||
duration: durationType,
|
||||
isRolling: t.literal<boolean>(true),
|
||||
type: rollingTimeWindowTypeSchema,
|
||||
});
|
||||
|
||||
const calendarAlignedTimeWindowTypeSchema = t.literal('calendarAligned');
|
||||
const calendarAlignedTimeWindowSchema = t.type({
|
||||
duration: durationType,
|
||||
isCalendar: t.literal<boolean>(true),
|
||||
type: calendarAlignedTimeWindowTypeSchema,
|
||||
});
|
||||
|
||||
const timeWindowSchema = t.union([rollingTimeWindowSchema, calendarAlignedTimeWindowSchema]);
|
||||
|
||||
export { rollingTimeWindowSchema, calendarAlignedTimeWindowSchema, timeWindowSchema };
|
||||
export {
|
||||
rollingTimeWindowSchema,
|
||||
rollingTimeWindowTypeSchema,
|
||||
calendarAlignedTimeWindowSchema,
|
||||
calendarAlignedTimeWindowTypeSchema,
|
||||
timeWindowSchema,
|
||||
};
|
||||
|
|
|
@ -138,7 +138,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
|
|||
"siem-ui-timeline": "670a02b3c2a399bca781ff1e4781793b208b471a",
|
||||
"siem-ui-timeline-note": "0a32fb776907f596bedca292b8c646496ae9c57b",
|
||||
"siem-ui-timeline-pinned-event": "082daa3ce647b33873f6abccf340bdfa32057c8d",
|
||||
"slo": "4415e0ae7af10b79a207843acee454a931a01386",
|
||||
"slo": "2048ab6791df2e1ae0936f29c20765cb8d2fcfaa",
|
||||
"space": "8de4ec513e9bbc6b2f1d635161d850be7747d38e",
|
||||
"spaces-usage-stats": "3abca98713c52af8b30300e386c7779b3025a20e",
|
||||
"synthetics-monitor": "ca7c0710c0607e44b2c52e5a41086b8b4a214f63",
|
||||
|
|
|
@ -43,7 +43,7 @@ const baseSlo: Omit<SLOWithSummaryResponse, 'id'> = {
|
|||
},
|
||||
timeWindow: {
|
||||
duration: '30d',
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
objective: { target: 0.98 },
|
||||
budgetingMethod: 'occurrences',
|
||||
|
|
|
@ -12,7 +12,7 @@ export const buildRollingTimeWindow = (
|
|||
): SLOWithSummaryResponse['timeWindow'] => {
|
||||
return {
|
||||
duration: '30d',
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
...params,
|
||||
};
|
||||
};
|
||||
|
@ -22,7 +22,7 @@ export const buildCalendarAlignedTimeWindow = (
|
|||
): SLOWithSummaryResponse['timeWindow'] => {
|
||||
return {
|
||||
duration: '1M',
|
||||
isCalendar: true,
|
||||
type: 'calendarAligned',
|
||||
...params,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import numeral from '@elastic/numeral';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import { rollingTimeWindowTypeSchema, SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import React from 'react';
|
||||
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
import { toDurationLabel } from '../../../utils/slo/labels';
|
||||
import { ChartData } from '../../../typings/slo';
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
import { toDurationAdverbLabel, toDurationLabel } from '../../../utils/slo/labels';
|
||||
import { WideChart } from './wide_chart';
|
||||
|
||||
export interface Props {
|
||||
|
@ -43,10 +42,15 @@ export function ErrorBudgetChartPanel({ data, isLoading, slo }: Props) {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText color="subdued" size="s">
|
||||
{i18n.translate('xpack.observability.slo.sloDetails.errorBudgetChartPanel.duration', {
|
||||
defaultMessage: 'Last {duration}',
|
||||
values: { duration: toDurationLabel(slo.timeWindow.duration) },
|
||||
})}
|
||||
{rollingTimeWindowTypeSchema.is(slo.timeWindow.type)
|
||||
? i18n.translate(
|
||||
'xpack.observability.slo.sloDetails.errorBudgetChartPanel.duration',
|
||||
{
|
||||
defaultMessage: 'Last {duration}',
|
||||
values: { duration: toDurationLabel(slo.timeWindow.duration) },
|
||||
}
|
||||
)
|
||||
: toDurationAdverbLabel(slo.timeWindow.duration)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -8,13 +8,21 @@
|
|||
import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
|
||||
import numeral from '@elastic/numeral';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import {
|
||||
occurrencesBudgetingMethodSchema,
|
||||
rollingTimeWindowTypeSchema,
|
||||
SLOWithSummaryResponse,
|
||||
} from '@kbn/slo-schema';
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
|
||||
import { toBudgetingMethodLabel, toIndicatorTypeLabel } from '../../../utils/slo/labels';
|
||||
import { toDurationLabel } from '../../../utils/slo/labels';
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
import {
|
||||
BUDGETING_METHOD_OCCURRENCES,
|
||||
BUDGETING_METHOD_TIMESLICES,
|
||||
toDurationAdverbLabel,
|
||||
toDurationLabel,
|
||||
toIndicatorTypeLabel,
|
||||
} from '../../../utils/slo/labels';
|
||||
import { OverviewItem } from './overview_item';
|
||||
|
||||
export interface Props {
|
||||
|
@ -71,11 +79,28 @@ export function Overview({ slo }: Props) {
|
|||
<OverviewItem
|
||||
title={i18n.translate(
|
||||
'xpack.observability.slo.sloDetails.overview.budgetingMethodTitle',
|
||||
{
|
||||
defaultMessage: 'Budgeting method',
|
||||
}
|
||||
{ defaultMessage: 'Budgeting method' }
|
||||
)}
|
||||
subtitle={<EuiText size="s">{toBudgetingMethodLabel(slo.budgetingMethod)}</EuiText>}
|
||||
subtitle={
|
||||
occurrencesBudgetingMethodSchema.is(slo.budgetingMethod) ? (
|
||||
<EuiText size="s">{BUDGETING_METHOD_OCCURRENCES}</EuiText>
|
||||
) : (
|
||||
<EuiText size="s">
|
||||
{BUDGETING_METHOD_TIMESLICES} (
|
||||
{i18n.translate(
|
||||
'xpack.observability.slo.sloDetails.overview.timeslicesBudgetingMethodDetails',
|
||||
{
|
||||
defaultMessage: '{duration} slices, {target} target',
|
||||
values: {
|
||||
duration: toDurationLabel(slo.objective.timesliceWindow!),
|
||||
target: numeral(slo.objective.timesliceTarget!).format(percentFormat),
|
||||
},
|
||||
}
|
||||
)}
|
||||
)
|
||||
</EuiText>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</EuiFlexGroup>
|
||||
|
||||
|
@ -128,7 +153,7 @@ export function Overview({ slo }: Props) {
|
|||
}
|
||||
|
||||
function toTimeWindowLabel(timeWindow: SLOWithSummaryResponse['timeWindow']): string {
|
||||
if ('isRolling' in timeWindow) {
|
||||
if (rollingTimeWindowTypeSchema.is(timeWindow.type)) {
|
||||
return i18n.translate('xpack.observability.slo.sloDetails.overview.rollingTimeWindow', {
|
||||
defaultMessage: '{duration} rolling',
|
||||
values: {
|
||||
|
@ -138,9 +163,9 @@ function toTimeWindowLabel(timeWindow: SLOWithSummaryResponse['timeWindow']): st
|
|||
}
|
||||
|
||||
return i18n.translate('xpack.observability.slo.sloDetails.overview.calendarAlignedTimeWindow', {
|
||||
defaultMessage: '{duration}',
|
||||
defaultMessage: '{duration} calendar aligned',
|
||||
values: {
|
||||
duration: timeWindow.duration,
|
||||
duration: toDurationAdverbLabel(timeWindow.duration),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import numeral from '@elastic/numeral';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import { rollingTimeWindowTypeSchema, SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import React from 'react';
|
||||
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
import { toDurationLabel } from '../../../utils/slo/labels';
|
||||
import { ChartData } from '../../../typings/slo';
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
import { toDurationAdverbLabel, toDurationLabel } from '../../../utils/slo/labels';
|
||||
import { WideChart } from './wide_chart';
|
||||
|
||||
export interface Props {
|
||||
|
@ -44,10 +43,15 @@ export function SliChartPanel({ data, isLoading, slo }: Props) {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText color="subdued" size="s">
|
||||
{i18n.translate('xpack.observability.slo.sloDetails.sliHistoryChartPanel.duration', {
|
||||
defaultMessage: 'Last {duration}',
|
||||
values: { duration: toDurationLabel(slo.timeWindow.duration) },
|
||||
})}
|
||||
{rollingTimeWindowTypeSchema.is(slo.timeWindow.type)
|
||||
? i18n.translate(
|
||||
'xpack.observability.slo.sloDetails.sliHistoryChartPanel.duration',
|
||||
{
|
||||
defaultMessage: 'Last {duration}',
|
||||
values: { duration: toDurationLabel(slo.timeWindow.duration) },
|
||||
}
|
||||
)
|
||||
: toDurationAdverbLabel(slo.timeWindow.duration)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -73,7 +73,7 @@ export const SLO_EDIT_FORM_DEFAULT_VALUES: CreateSLOInput = {
|
|||
timeWindow: {
|
||||
duration:
|
||||
TIMEWINDOW_OPTIONS[TIMEWINDOW_OPTIONS.findIndex((option) => option.value === '30d')].value,
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
tags: [],
|
||||
budgetingMethod: BUDGETING_METHOD_OPTIONS[0].value,
|
||||
|
@ -98,7 +98,7 @@ export const SLO_EDIT_FORM_DEFAULT_VALUES_CUSTOM_METRIC: CreateSLOInput = {
|
|||
timeWindow: {
|
||||
duration:
|
||||
TIMEWINDOW_OPTIONS[TIMEWINDOW_OPTIONS.findIndex((option) => option.value === '30d')].value,
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
tags: [],
|
||||
budgetingMethod: BUDGETING_METHOD_OPTIONS[0].value,
|
||||
|
|
|
@ -338,7 +338,7 @@ describe('SLO Edit Page', () => {
|
|||
},
|
||||
"timeWindow": Object {
|
||||
"duration": "7d",
|
||||
"isRolling": true,
|
||||
"type": "rolling",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -26,21 +26,21 @@ const Template: ComponentStory<typeof Component> = (props: Props) => (
|
|||
);
|
||||
|
||||
export const With7DaysRolling = Template.bind({});
|
||||
With7DaysRolling.args = { slo: buildSlo({ timeWindow: { duration: '7d', isRolling: true } }) };
|
||||
With7DaysRolling.args = { slo: buildSlo({ timeWindow: { duration: '7d', type: 'rolling' } }) };
|
||||
|
||||
export const With30DaysRolling = Template.bind({});
|
||||
With30DaysRolling.args = { slo: buildSlo({ timeWindow: { duration: '30d', isRolling: true } }) };
|
||||
With30DaysRolling.args = { slo: buildSlo({ timeWindow: { duration: '30d', type: 'rolling' } }) };
|
||||
|
||||
export const WithWeeklyCalendar = Template.bind({});
|
||||
WithWeeklyCalendar.args = {
|
||||
slo: buildSlo({
|
||||
timeWindow: { duration: '1w', isCalendar: true },
|
||||
timeWindow: { duration: '1w', type: 'calendarAligned' },
|
||||
}),
|
||||
};
|
||||
|
||||
export const WithMonthlyCalendar = Template.bind({});
|
||||
WithMonthlyCalendar.args = {
|
||||
slo: buildSlo({
|
||||
timeWindow: { duration: '1M', isCalendar: true },
|
||||
timeWindow: { duration: '1M', type: 'calendarAligned' },
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import { EuiBadge, EuiFlexItem } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { rollingTimeWindowTypeSchema, SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import { toMomentUnitOfTime } from '../../../../utils/slo/duration';
|
||||
import { toDurationLabel } from '../../../../utils/slo/labels';
|
||||
|
||||
|
@ -21,7 +20,7 @@ export interface Props {
|
|||
|
||||
export function SloTimeWindowBadge({ slo }: Props) {
|
||||
const unit = slo.timeWindow.duration.slice(-1);
|
||||
if ('isRolling' in slo.timeWindow) {
|
||||
if (rollingTimeWindowTypeSchema.is(slo.timeWindow.type)) {
|
||||
return (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiBadge
|
||||
|
|
|
@ -66,16 +66,6 @@ export const BUDGETING_METHOD_TIMESLICES = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export function toBudgetingMethodLabel(
|
||||
budgetingMethod: SLOWithSummaryResponse['budgetingMethod']
|
||||
): string {
|
||||
if (budgetingMethod === 'occurrences') {
|
||||
return BUDGETING_METHOD_OCCURRENCES;
|
||||
}
|
||||
|
||||
return BUDGETING_METHOD_TIMESLICES;
|
||||
}
|
||||
|
||||
export function toDurationLabel(durationStr: string): string {
|
||||
const duration = toDuration(durationStr);
|
||||
|
||||
|
@ -124,3 +114,34 @@ export function toDurationLabel(durationStr: string): string {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function toDurationAdverbLabel(durationStr: string): string {
|
||||
const duration = toDuration(durationStr);
|
||||
|
||||
switch (duration.unit) {
|
||||
case 'm':
|
||||
return i18n.translate('xpack.observability.slo.duration.minutely', {
|
||||
defaultMessage: 'Minutely',
|
||||
});
|
||||
case 'h':
|
||||
return i18n.translate('xpack.observability.slo.duration.hourly', {
|
||||
defaultMessage: 'Hourly',
|
||||
});
|
||||
case 'd':
|
||||
return i18n.translate('xpack.observability.slo.duration.daily', {
|
||||
defaultMessage: 'Daily',
|
||||
});
|
||||
case 'w':
|
||||
return i18n.translate('xpack.observability.slo.duration.weekly', {
|
||||
defaultMessage: 'Weekly',
|
||||
});
|
||||
case 'M':
|
||||
return i18n.translate('xpack.observability.slo.duration.monthly', {
|
||||
defaultMessage: 'Monthly',
|
||||
});
|
||||
case 'Y':
|
||||
return i18n.translate('xpack.observability.slo.duration.yearly', {
|
||||
defaultMessage: 'Yearly',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,10 +65,10 @@ describe('toDateRange', () => {
|
|||
function aCalendarTimeWindow(duration: Duration): TimeWindow {
|
||||
return {
|
||||
duration,
|
||||
isCalendar: true,
|
||||
type: 'calendarAligned',
|
||||
};
|
||||
}
|
||||
|
||||
function aRollingTimeWindow(duration: Duration): TimeWindow {
|
||||
return { duration, isRolling: true };
|
||||
return { duration, type: 'rolling' };
|
||||
}
|
||||
|
|
|
@ -24,14 +24,14 @@ describe('validateSLO', () => {
|
|||
|
||||
it("throws when time window duration unit is 'm'", () => {
|
||||
const slo = createSLO({
|
||||
timeWindow: { duration: new Duration(1, DurationUnit.Minute), isRolling: true },
|
||||
timeWindow: { duration: new Duration(1, DurationUnit.Minute), type: 'rolling' },
|
||||
});
|
||||
expect(() => validateSLO(slo)).toThrowError('Invalid time_window.duration');
|
||||
});
|
||||
|
||||
it("throws when time window duration unit is 'h'", () => {
|
||||
const slo = createSLO({
|
||||
timeWindow: { duration: new Duration(1, DurationUnit.Hour), isRolling: true },
|
||||
timeWindow: { duration: new Duration(1, DurationUnit.Hour), type: 'rolling' },
|
||||
});
|
||||
expect(() => validateSLO(slo)).toThrowError('Invalid time_window.duration');
|
||||
});
|
||||
|
@ -56,7 +56,7 @@ describe('validateSLO', () => {
|
|||
expect(() =>
|
||||
validateSLO(
|
||||
createSLO({
|
||||
timeWindow: { duration, isCalendar: true },
|
||||
timeWindow: { duration, type: 'calendarAligned' },
|
||||
})
|
||||
)
|
||||
).toThrowError('Invalid time_window.duration');
|
||||
|
@ -64,7 +64,7 @@ describe('validateSLO', () => {
|
|||
expect(() =>
|
||||
validateSLO(
|
||||
createSLO({
|
||||
timeWindow: { duration, isCalendar: true },
|
||||
timeWindow: { duration, type: 'calendarAligned' },
|
||||
})
|
||||
)
|
||||
).not.toThrowError();
|
||||
|
@ -191,7 +191,7 @@ describe('validateSLO', () => {
|
|||
|
||||
it("throws when 'objective.timeslice_window' is longer than 'slo.time_window'", () => {
|
||||
const slo = createSLO({
|
||||
timeWindow: { duration: new Duration(1, DurationUnit.Week), isRolling: true },
|
||||
timeWindow: { duration: new Duration(1, DurationUnit.Week), type: 'rolling' },
|
||||
budgetingMethod: 'timeslices',
|
||||
objective: {
|
||||
target: 0.95,
|
||||
|
|
|
@ -47,14 +47,14 @@ export const fetcher = async (context: CollectorFetchContext) => {
|
|||
},
|
||||
by_rolling_duration: {
|
||||
...acc.by_rolling_duration,
|
||||
...('isRolling' in so.attributes.timeWindow && {
|
||||
...(so.attributes.timeWindow.type === 'rolling' && {
|
||||
[so.attributes.timeWindow.duration]:
|
||||
(acc.by_rolling_duration[so.attributes.timeWindow.duration] ?? 0) + 1,
|
||||
}),
|
||||
},
|
||||
by_calendar_aligned_duration: {
|
||||
...acc.by_calendar_aligned_duration,
|
||||
...('isCalendar' in so.attributes.timeWindow && {
|
||||
...(so.attributes.timeWindow.type === 'calendarAligned' && {
|
||||
[so.attributes.timeWindow.duration]:
|
||||
(acc.by_calendar_aligned_duration[so.attributes.timeWindow.duration] ?? 0) + 1,
|
||||
}),
|
||||
|
|
|
@ -5,11 +5,33 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SavedObjectsType } from '@kbn/core-saved-objects-server';
|
||||
import { SavedObjectMigrationFn, SavedObjectsType } from '@kbn/core-saved-objects-server';
|
||||
import { SavedObject } from '@kbn/core/server';
|
||||
|
||||
import { StoredSLO } from '../domain/models';
|
||||
|
||||
type StoredSLOBefore890 = StoredSLO & {
|
||||
timeWindow: {
|
||||
duration: string;
|
||||
isRolling?: boolean;
|
||||
isCalendar?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
const migrateSlo890: SavedObjectMigrationFn<StoredSLOBefore890, StoredSLO> = (doc) => {
|
||||
const { timeWindow, ...other } = doc.attributes;
|
||||
return {
|
||||
...doc,
|
||||
attributes: {
|
||||
...other,
|
||||
timeWindow: {
|
||||
duration: timeWindow.duration,
|
||||
type: timeWindow.isCalendar ? 'calendarAligned' : 'rolling',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const SO_SLO_TYPE = 'slo';
|
||||
|
||||
export const slo: SavedObjectsType = {
|
||||
|
@ -40,4 +62,7 @@ export const slo: SavedObjectsType = {
|
|||
return `SLO: [${sloSavedObject.attributes.name}]`;
|
||||
},
|
||||
},
|
||||
migrations: {
|
||||
'8.9.0': migrateSlo890,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -63,7 +63,7 @@ describe('FindSLO', () => {
|
|||
},
|
||||
timeWindow: {
|
||||
duration: '7d',
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
settings: {
|
||||
syncDelay: '1m',
|
||||
|
|
|
@ -162,7 +162,7 @@ export const createSLOWithCalendarTimeWindow = (params: Partial<SLO> = {}): SLO
|
|||
return createSLO({
|
||||
timeWindow: {
|
||||
duration: oneWeek(),
|
||||
isCalendar: true,
|
||||
type: 'calendarAligned',
|
||||
},
|
||||
...params,
|
||||
});
|
||||
|
|
|
@ -11,26 +11,26 @@ import { oneWeek, sevenDays, sixHours, thirtyDays } from './duration';
|
|||
export function sixHoursRolling(): TimeWindow {
|
||||
return {
|
||||
duration: sixHours(),
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
};
|
||||
}
|
||||
|
||||
export function sevenDaysRolling(): RollingTimeWindow {
|
||||
return {
|
||||
duration: sevenDays(),
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
};
|
||||
}
|
||||
export function thirtyDaysRolling(): RollingTimeWindow {
|
||||
return {
|
||||
duration: thirtyDays(),
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
};
|
||||
}
|
||||
|
||||
export function weeklyCalendarAligned(): TimeWindow {
|
||||
return {
|
||||
duration: oneWeek(),
|
||||
isCalendar: true,
|
||||
type: 'calendarAligned',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ describe('GetSLO', () => {
|
|||
},
|
||||
timeWindow: {
|
||||
duration: '7d',
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
settings: {
|
||||
syncDelay: '1m',
|
||||
|
|
|
@ -138,7 +138,7 @@ describe('FetchHistoricalSummary', () => {
|
|||
describe('Rolling and Occurrences SLOs', () => {
|
||||
it('returns the summary', async () => {
|
||||
const slo = createSLO({
|
||||
timeWindow: { isRolling: true, duration: thirtyDays() },
|
||||
timeWindow: { type: 'rolling', duration: thirtyDays() },
|
||||
objective: { target: 0.95 },
|
||||
});
|
||||
esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(30));
|
||||
|
@ -156,7 +156,7 @@ describe('FetchHistoricalSummary', () => {
|
|||
describe('Rolling and Timeslices SLOs', () => {
|
||||
it('returns the summary', async () => {
|
||||
const slo = createSLO({
|
||||
timeWindow: { isRolling: true, duration: thirtyDays() },
|
||||
timeWindow: { type: 'rolling', duration: thirtyDays() },
|
||||
budgetingMethod: 'timeslices',
|
||||
objective: { target: 0.95, timesliceTarget: 0.9, timesliceWindow: oneMinute() },
|
||||
});
|
||||
|
@ -177,7 +177,7 @@ describe('FetchHistoricalSummary', () => {
|
|||
const slo = createSLO({
|
||||
timeWindow: {
|
||||
duration: oneMonth(),
|
||||
isCalendar: true,
|
||||
type: 'calendarAligned',
|
||||
},
|
||||
budgetingMethod: 'timeslices',
|
||||
objective: { target: 0.95, timesliceTarget: 0.9, timesliceWindow: oneMinute() },
|
||||
|
@ -200,7 +200,7 @@ describe('FetchHistoricalSummary', () => {
|
|||
const slo = createSLO({
|
||||
timeWindow: {
|
||||
duration: oneMonth(),
|
||||
isCalendar: true,
|
||||
type: 'calendarAligned',
|
||||
},
|
||||
budgetingMethod: 'occurrences',
|
||||
objective: { target: 0.95 },
|
||||
|
|
|
@ -49,7 +49,7 @@ export class DefaultSLIClient implements SLIClient {
|
|||
const longestLookbackWindow = sortedLookbackWindows[0];
|
||||
const longestDateRange = toDateRange({
|
||||
duration: longestLookbackWindow.duration,
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
});
|
||||
|
||||
if (occurrencesBudgetingMethodSchema.is(slo.budgetingMethod)) {
|
||||
|
|
|
@ -89,7 +89,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
createCompositeSLOInput({
|
||||
timeWindow: {
|
||||
duration: '30d',
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
sources: [
|
||||
{ id: 'f9072790-f97c-11ed-895c-170d13e61076', revision: 2, weight: 1 },
|
||||
|
|
|
@ -13,7 +13,7 @@ const defaultCompositeSLOInput: CreateCompositeSLOInput = {
|
|||
name: 'some composite slo',
|
||||
timeWindow: {
|
||||
duration: '7d',
|
||||
isRolling: true,
|
||||
type: 'rolling',
|
||||
},
|
||||
budgetingMethod: 'occurrences',
|
||||
objective: {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
{ "id": "f9072790-f97c-11ed-895c-170d13e61076", "revision": 2, "weight": 1 }
|
||||
],
|
||||
"tags": [],
|
||||
"timeWindow": { "duration": "7d", "isRolling": true },
|
||||
"timeWindow": { "duration": "7d", "type": "rolling" },
|
||||
"updatedAt": "2023-05-24T21:12:37.831Z"
|
||||
},
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"tags": [],
|
||||
"timeWindow": {
|
||||
"duration": "7d",
|
||||
"isRolling": true
|
||||
"type": "rolling"
|
||||
},
|
||||
"updatedAt": "2023-05-23T15:18:31.650Z"
|
||||
},
|
||||
|
@ -70,7 +70,7 @@
|
|||
"tags": [],
|
||||
"timeWindow": {
|
||||
"duration": "7d",
|
||||
"isRolling": true
|
||||
"type": "rolling"
|
||||
},
|
||||
"updatedAt": "2023-05-23T15:18:39.734Z"
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue