diff --git a/x-pack/plugins/observability_solution/observability/common/index.ts b/x-pack/plugins/observability_solution/observability/common/index.ts index 67657657d1903..12f3f7b010a30 100644 --- a/x-pack/plugins/observability_solution/observability/common/index.ts +++ b/x-pack/plugins/observability_solution/observability/common/index.ts @@ -83,3 +83,4 @@ export const rulesLocatorID = 'RULES_LOCATOR'; import { paths } from './locators/paths'; export const observabilityPaths = paths.observability; export type { AlertsLocatorParams } from './locators/alerts'; +export { AlertsLocatorDefinition } from './locators/alerts'; diff --git a/x-pack/plugins/observability_solution/observability/kibana.jsonc b/x-pack/plugins/observability_solution/observability/kibana.jsonc index d51801cedc669..2a9a70c1b7f0a 100644 --- a/x-pack/plugins/observability_solution/observability/kibana.jsonc +++ b/x-pack/plugins/observability_solution/observability/kibana.jsonc @@ -32,7 +32,6 @@ "observabilityShared", "observabilityAIAssistant", "ruleRegistry", - "taskManager", "triggersActionsUi", "security", "share", diff --git a/x-pack/plugins/observability_solution/observability/server/domain/models/common.ts b/x-pack/plugins/observability_solution/observability/server/domain/models/common.ts new file mode 100644 index 0000000000000..6e82a9e7cbbe9 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/models/common.ts @@ -0,0 +1,23 @@ +/* + * 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 * as t from 'io-ts'; + +import { + dateRangeSchema, + historicalSummarySchema, + statusSchema, + summarySchema, + groupSummarySchema, +} from '@kbn/slo-schema'; + +type Status = t.TypeOf; +type DateRange = t.TypeOf; +type HistoricalSummary = t.TypeOf; +type Summary = t.TypeOf; +type GroupSummary = t.TypeOf; + +export type { DateRange, HistoricalSummary, Status, Summary, GroupSummary }; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/models/error_budget.ts b/x-pack/plugins/observability_solution/observability/server/domain/models/error_budget.ts new file mode 100644 index 0000000000000..50ca6e469d7dd --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/models/error_budget.ts @@ -0,0 +1,13 @@ +/* + * 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 * as t from 'io-ts'; +import { errorBudgetSchema } from '@kbn/slo-schema'; + +type ErrorBudget = t.TypeOf; + +export type { ErrorBudget }; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/models/index.ts b/x-pack/plugins/observability_solution/observability/server/domain/models/index.ts new file mode 100644 index 0000000000000..16336c40928f8 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/models/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './common'; +export { Duration, DurationUnit, toDurationUnit, toMomentUnitOfTime } from '@kbn/slo-schema'; +export * from './error_budget'; +export * from './indicators'; +export * from './slo'; +export * from './time_window'; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/models/indicators.ts b/x-pack/plugins/observability_solution/observability/server/domain/models/indicators.ts new file mode 100644 index 0000000000000..100c04dfda35b --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/models/indicators.ts @@ -0,0 +1,35 @@ +/* + * 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 * as t from 'io-ts'; +import { + apmTransactionDurationIndicatorSchema, + apmTransactionErrorRateIndicatorSchema, + indicatorDataSchema, + indicatorSchema, + indicatorTypesSchema, + kqlCustomIndicatorSchema, + metricCustomIndicatorSchema, +} from '@kbn/slo-schema'; + +type APMTransactionErrorRateIndicator = t.TypeOf; +type APMTransactionDurationIndicator = t.TypeOf; +type KQLCustomIndicator = t.TypeOf; +type MetricCustomIndicator = t.TypeOf; +type Indicator = t.TypeOf; +type IndicatorTypes = t.TypeOf; +type IndicatorData = t.TypeOf; + +export type { + Indicator, + IndicatorTypes, + APMTransactionErrorRateIndicator, + APMTransactionDurationIndicator, + KQLCustomIndicator, + MetricCustomIndicator, + IndicatorData, +}; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/models/slo.ts b/x-pack/plugins/observability_solution/observability/server/domain/models/slo.ts new file mode 100644 index 0000000000000..d17498c3dbfed --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/models/slo.ts @@ -0,0 +1,16 @@ +/* + * 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 * as t from 'io-ts'; +import { sloIdSchema, sloSchema, sloWithSummarySchema } from '@kbn/slo-schema'; + +type SLO = t.TypeOf; +type SLOId = t.TypeOf; +type SLOWithSummary = t.TypeOf; +type StoredSLO = t.OutputOf; + +export type { SLO, SLOWithSummary, SLOId, StoredSLO }; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/models/time_window.ts b/x-pack/plugins/observability_solution/observability/server/domain/models/time_window.ts new file mode 100644 index 0000000000000..aa12aa70a8ae8 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/models/time_window.ts @@ -0,0 +1,46 @@ +/* + * 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 { + calendarAlignedTimeWindowSchema, + rollingTimeWindowSchema, + timeWindowSchema, +} from '@kbn/slo-schema'; +import moment from 'moment'; +import * as t from 'io-ts'; + +type TimeWindow = t.TypeOf; +type RollingTimeWindow = t.TypeOf; +type CalendarAlignedTimeWindow = t.TypeOf; + +export type { RollingTimeWindow, TimeWindow, CalendarAlignedTimeWindow }; + +export function toCalendarAlignedTimeWindowMomentUnit( + timeWindow: CalendarAlignedTimeWindow +): moment.unitOfTime.StartOf { + const unit = timeWindow.duration.unit; + switch (unit) { + case 'w': + return 'isoWeeks'; + case 'M': + return 'months'; + default: + throw new Error(`Invalid calendar aligned time window duration unit: ${unit}`); + } +} + +export function toRollingTimeWindowMomentUnit( + timeWindow: RollingTimeWindow +): moment.unitOfTime.Diff { + const unit = timeWindow.duration.unit; + switch (unit) { + case 'd': + return 'days'; + default: + throw new Error(`Invalid rolling time window duration unit: ${unit}`); + } +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/compute_burn_rate.test.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_burn_rate.test.ts new file mode 100644 index 0000000000000..84fef850e096c --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_burn_rate.test.ts @@ -0,0 +1,63 @@ +/* + * 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 { computeBurnRate } from './compute_burn_rate'; +import { toDateRange } from './date_range'; +import { createSLO } from '../../services/slo/fixtures/slo'; +import { ninetyDaysRolling } from '../../services/slo/fixtures/time_window'; + +describe('computeBurnRate', () => { + it('computes 0 when total is 0', () => { + expect( + computeBurnRate(createSLO(), { + good: 10, + total: 0, + dateRange: toDateRange(ninetyDaysRolling()), + }) + ).toEqual(0); + }); + + it('computes 0 when good is greater than total', () => { + expect( + computeBurnRate(createSLO(), { + good: 9999, + total: 1, + dateRange: toDateRange(ninetyDaysRolling()), + }) + ).toEqual(0); + }); + + it('computes the burn rate as 1x the error budget', () => { + expect( + computeBurnRate(createSLO({ objective: { target: 0.9 } }), { + good: 90, + total: 100, + dateRange: toDateRange(ninetyDaysRolling()), + }) + ).toEqual(1); + }); + + it('computes the burn rate as 10x the error budget', () => { + expect( + computeBurnRate(createSLO({ objective: { target: 0.99 } }), { + good: 90, + total: 100, + dateRange: toDateRange(ninetyDaysRolling()), + }) + ).toEqual(10); + }); + + it('computes the burn rate as 0.5x the error budget', () => { + expect( + computeBurnRate(createSLO({ objective: { target: 0.8 } }), { + good: 90, + total: 100, + dateRange: toDateRange(ninetyDaysRolling()), + }) + ).toEqual(0.5); + }); +}); diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/compute_burn_rate.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_burn_rate.ts new file mode 100644 index 0000000000000..2cd758c4c3a74 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_burn_rate.ts @@ -0,0 +1,24 @@ +/* + * 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 { toHighPrecision } from '../../utils/number'; +import { IndicatorData, SLO } from '../models'; + +/** + * A Burn Rate is computed with the Indicator Data retrieved from a specific lookback period + * It tells how fast we are consumming our error budget during a specific period + */ +export function computeBurnRate(slo: SLO, sliData: IndicatorData): number { + const { good, total } = sliData; + if (total === 0 || good >= total) { + return 0; + } + + const errorBudget = 1 - slo.objective.target; + const errorRate = 1 - good / total; + return toHighPrecision(errorRate / errorBudget); +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/compute_sli.test.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_sli.test.ts new file mode 100644 index 0000000000000..79494de1d7cf1 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_sli.test.ts @@ -0,0 +1,26 @@ +/* + * 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 { computeSLI } from './compute_sli'; + +describe('computeSLI', () => { + it('returns -1 when no total events', () => { + expect(computeSLI(100, 0)).toEqual(-1); + }); + + it('returns the sli value', () => { + expect(computeSLI(100, 1000)).toEqual(0.1); + }); + + it('returns when good is greater than total events', () => { + expect(computeSLI(9999, 9)).toEqual(1111); + }); + + it('returns rounds the value to 6 digits', () => { + expect(computeSLI(33, 90)).toEqual(0.366667); + }); +}); diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/compute_sli.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_sli.ts new file mode 100644 index 0000000000000..bafab79104134 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_sli.ts @@ -0,0 +1,18 @@ +/* + * 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 { toHighPrecision } from '../../utils/number'; + +const NO_DATA = -1; + +export function computeSLI(good: number, total: number): number { + if (total === 0) { + return NO_DATA; + } + + return toHighPrecision(good / total); +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/compute_summary_status.test.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_summary_status.test.ts new file mode 100644 index 0000000000000..12ee6de644b4a --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_summary_status.test.ts @@ -0,0 +1,46 @@ +/* + * 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 { createErrorBudget } from '../../services/slo/fixtures/error_budget'; +import { createSLO } from '../../services/slo/fixtures/slo'; +import { computeSummaryStatus } from './compute_summary_status'; + +describe('ComputeSummaryStatus', () => { + it("returns 'NO_DATA' when sliValue is -1", () => { + expect(computeSummaryStatus(createSLO(), -1, createErrorBudget())).toBe('NO_DATA'); + }); + + it("returns 'HEALTHY' when sliValue >= target objective", () => { + expect( + computeSummaryStatus(createSLO({ objective: { target: 0.9 } }), 0.9, createErrorBudget()) + ).toBe('HEALTHY'); + + expect( + computeSummaryStatus(createSLO({ objective: { target: 0.9 } }), 0.99, createErrorBudget()) + ).toBe('HEALTHY'); + }); + + it("returns 'DEGRADING' when sliValue < target objective with some remaining error budget", () => { + expect( + computeSummaryStatus( + createSLO({ objective: { target: 0.9 } }), + 0.8, + createErrorBudget({ remaining: 0.01, consumed: 0.99 }) + ) + ).toBe('DEGRADING'); + }); + + it("returns 'VIOLATED' when sliValue < target objective and error budget is consummed", () => { + expect( + computeSummaryStatus( + createSLO({ objective: { target: 0.9 } }), + 0.8, + createErrorBudget({ remaining: 0, consumed: 1.34 }) + ) + ).toBe('VIOLATED'); + }); +}); diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/compute_summary_status.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_summary_status.ts new file mode 100644 index 0000000000000..3aaaffe180b6a --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/compute_summary_status.ts @@ -0,0 +1,20 @@ +/* + * 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 { ErrorBudget, SLO, Status } from '../models'; + +export function computeSummaryStatus(slo: SLO, sliValue: number, errorBudget: ErrorBudget): Status { + if (sliValue === -1) { + return 'NO_DATA'; + } + + if (sliValue >= slo.objective.target) { + return 'HEALTHY'; + } else { + return errorBudget.remaining > 0 ? 'DEGRADING' : 'VIOLATED'; + } +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/date_range.test.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/date_range.test.ts new file mode 100644 index 0000000000000..524aecbfab10f --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/date_range.test.ts @@ -0,0 +1,60 @@ +/* + * 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 { + monthlyCalendarAligned, + ninetyDaysRolling, + sevenDaysRolling, + thirtyDaysRolling, + weeklyCalendarAligned, +} from '../../services/slo/fixtures/time_window'; +import { toDateRange } from './date_range'; + +const NOW = new Date('2022-08-11T08:31:00.000Z'); + +describe('toDateRange', () => { + describe('for calendar aligned time window', () => { + it('computes the date range for weekly calendar', () => { + const timeWindow = weeklyCalendarAligned(); + expect(toDateRange(timeWindow, NOW)).toEqual({ + from: new Date('2022-08-08T00:00:00.000Z'), + to: new Date('2022-08-14T23:59:59.999Z'), + }); + }); + + it('computes the date range for monthly calendar', () => { + const timeWindow = monthlyCalendarAligned(); + expect(toDateRange(timeWindow, NOW)).toEqual({ + from: new Date('2022-08-01T00:00:00.000Z'), + to: new Date('2022-08-31T23:59:59.999Z'), + }); + }); + }); + + describe('for rolling time window', () => { + it("computes the date range using a '30days' rolling window", () => { + expect(toDateRange(thirtyDaysRolling(), NOW)).toEqual({ + from: new Date('2022-07-12T08:31:00.000Z'), + to: new Date('2022-08-11T08:31:00.000Z'), + }); + }); + + it("computes the date range using a '7days' rolling window", () => { + expect(toDateRange(sevenDaysRolling(), NOW)).toEqual({ + from: new Date('2022-08-04T08:31:00.000Z'), + to: new Date('2022-08-11T08:31:00.000Z'), + }); + }); + + it("computes the date range using a '90days' rolling window", () => { + expect(toDateRange(ninetyDaysRolling(), NOW)).toEqual({ + from: new Date('2022-05-13T08:31:00.000Z'), + to: new Date('2022-08-11T08:31:00.000Z'), + }); + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/date_range.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/date_range.ts new file mode 100644 index 0000000000000..9c54197aa39e3 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/date_range.ts @@ -0,0 +1,40 @@ +/* + * 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 { calendarAlignedTimeWindowSchema, rollingTimeWindowSchema } from '@kbn/slo-schema'; +import { assertNever } from '@kbn/std'; +import moment from 'moment'; +import { DateRange } from '../models'; +import { + TimeWindow, + toCalendarAlignedTimeWindowMomentUnit, + toRollingTimeWindowMomentUnit, +} from '../models/time_window'; + +export const toDateRange = (timeWindow: TimeWindow, currentDate: Date = new Date()): DateRange => { + if (calendarAlignedTimeWindowSchema.is(timeWindow)) { + const unit = toCalendarAlignedTimeWindowMomentUnit(timeWindow); + const from = moment.utc(currentDate).startOf(unit); + const to = moment.utc(currentDate).endOf(unit); + + return { from: from.toDate(), to: to.toDate() }; + } + + if (rollingTimeWindowSchema.is(timeWindow)) { + const unit = toRollingTimeWindowMomentUnit(timeWindow); + const now = moment.utc(currentDate).startOf('minute'); + const from = now.clone().subtract(timeWindow.duration.value, unit); + const to = now.clone(); + + return { + from: from.toDate(), + to: to.toDate(), + }; + } + + assertNever(timeWindow); +}; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/error_budget.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/error_budget.ts new file mode 100644 index 0000000000000..74165c5eec560 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/error_budget.ts @@ -0,0 +1,22 @@ +/* + * 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 { toHighPrecision } from '../../utils/number'; +import { ErrorBudget } from '../models'; + +export function toErrorBudget( + initial: number, + consumed: number, + isEstimated: boolean = false +): ErrorBudget { + return { + initial: toHighPrecision(initial), + consumed: toHighPrecision(consumed), + remaining: toHighPrecision(1 - consumed), + isEstimated, + }; +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/get_delay_in_seconds_from_slo.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/get_delay_in_seconds_from_slo.ts new file mode 100644 index 0000000000000..e6cef17750394 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/get_delay_in_seconds_from_slo.ts @@ -0,0 +1,18 @@ +/* + * 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 { timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; +import { SLO } from '../models'; + +export function getDelayInSecondsFromSLO(slo: SLO) { + const fixedInterval = timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) + ? slo.objective.timesliceWindow!.asSeconds() + : 60; + const syncDelay = slo.settings.syncDelay.asSeconds(); + const frequency = slo.settings.frequency.asSeconds(); + return fixedInterval + syncDelay + frequency; +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/get_lookback_date_range.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/get_lookback_date_range.ts new file mode 100644 index 0000000000000..63ed12a7244c0 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/get_lookback_date_range.ts @@ -0,0 +1,23 @@ +/* + * 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 moment from 'moment'; +import { Duration, toMomentUnitOfTime } from '../models'; +export function getLookbackDateRange( + startedAt: Date, + duration: Duration, + delayInSeconds = 0 +): { from: Date; to: Date } { + const unit = toMomentUnitOfTime(duration.unit); + const now = moment(startedAt).subtract(delayInSeconds, 'seconds').startOf('minute'); + const from = now.clone().subtract(duration.value, unit).startOf('minute'); + + return { + from: from.toDate(), + to: now.toDate(), + }; +} diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/index.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/index.ts new file mode 100644 index 0000000000000..212647f27b172 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './compute_burn_rate'; +export * from './error_budget'; +export * from './compute_sli'; +export * from './compute_summary_status'; +export * from './date_range'; +export * from './validate_slo'; diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/validate_slo.test.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/validate_slo.test.ts new file mode 100644 index 0000000000000..70cc408ceb175 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/validate_slo.test.ts @@ -0,0 +1,217 @@ +/* + * 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 { validateSLO } from '.'; +import { oneMinute, sixHours } from '../../services/slo/fixtures/duration'; +import { createSLO } from '../../services/slo/fixtures/slo'; +import { sevenDaysRolling } from '../../services/slo/fixtures/time_window'; +import { Duration, DurationUnit } from '../models'; + +describe('validateSLO', () => { + describe('any slo', () => { + it("throws when 'objective.target' is lte 0", () => { + const slo = createSLO({ objective: { target: 0 } }); + expect(() => validateSLO(slo)).toThrowError('Invalid objective.target'); + }); + + it("throws when 'objective.target' is gte 1", () => { + const slo = createSLO({ objective: { target: 1 } }); + expect(() => validateSLO(slo)).toThrowError('Invalid objective.target'); + }); + + it("throws when time window duration unit is 'm'", () => { + const slo = createSLO({ + 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), type: 'rolling' }, + }); + expect(() => validateSLO(slo)).toThrowError('Invalid time_window.duration'); + }); + + it.each([ + { duration: new Duration(1, DurationUnit.Hour), shouldThrow: true }, + { duration: new Duration(2, DurationUnit.Hour), shouldThrow: true }, + { duration: new Duration(1, DurationUnit.Day), shouldThrow: true }, + { duration: new Duration(7, DurationUnit.Day), shouldThrow: true }, + { duration: new Duration(2, DurationUnit.Week), shouldThrow: true }, + { duration: new Duration(2, DurationUnit.Month), shouldThrow: true }, + { duration: new Duration(1, DurationUnit.Week), shouldThrow: false }, + { duration: new Duration(1, DurationUnit.Month), shouldThrow: false }, + ])( + 'throws when calendar aligned time window is not 1 week or 1 month', + ({ duration, shouldThrow }) => { + if (shouldThrow) { + expect(() => + validateSLO( + createSLO({ + timeWindow: { duration, type: 'calendarAligned' }, + }) + ) + ).toThrowError('Invalid time_window.duration'); + } else { + expect(() => + validateSLO( + createSLO({ + timeWindow: { duration, type: 'calendarAligned' }, + }) + ) + ).not.toThrowError(); + } + } + ); + + it.each([ + { duration: new Duration(7, DurationUnit.Day), shouldThrow: false }, + { duration: new Duration(30, DurationUnit.Day), shouldThrow: false }, + { duration: new Duration(90, DurationUnit.Day), shouldThrow: false }, + { duration: new Duration(1, DurationUnit.Hour), shouldThrow: true }, + { duration: new Duration(1, DurationUnit.Day), shouldThrow: true }, + { duration: new Duration(1, DurationUnit.Week), shouldThrow: true }, + { duration: new Duration(1, DurationUnit.Month), shouldThrow: true }, + ])('throws when rolling time window is not 7, 30 or 90days', ({ duration, shouldThrow }) => { + if (shouldThrow) { + expect(() => + validateSLO( + createSLO({ + timeWindow: { duration, type: 'rolling' }, + }) + ) + ).toThrowError('Invalid time_window.duration'); + } else { + expect(() => + validateSLO( + createSLO({ + timeWindow: { duration, type: 'rolling' }, + }) + ) + ).not.toThrowError(); + } + }); + + describe('settings', () => { + it("throws when frequency is longer or equal than '1h'", () => { + const slo = createSLO({ + settings: { + frequency: sixHours(), + syncDelay: oneMinute(), + }, + }); + expect(() => validateSLO(slo)).toThrowError('Invalid settings.frequency'); + }); + + it("throws when sync_delay is longer or equal than '6h'", () => { + const slo = createSLO({ + settings: { + frequency: oneMinute(), + syncDelay: sixHours(), + }, + }); + expect(() => validateSLO(slo)).toThrowError('Invalid settings.sync_delay'); + }); + }); + }); + + describe('slo with timeslices budgeting method', () => { + it("throws when 'objective.timeslice_target' is not present", () => { + const slo = createSLO({ + budgetingMethod: 'timeslices', + objective: { + target: 0.95, + timesliceWindow: new Duration(1, DurationUnit.Minute), + }, + }); + expect(() => validateSLO(slo)).toThrowError('Invalid objective.timeslice_target'); + }); + + it("throws when 'objective.timeslice_target' is lte 0", () => { + const slo = createSLO({ + budgetingMethod: 'timeslices', + objective: { + target: 0.95, + timesliceTarget: 0, + timesliceWindow: new Duration(1, DurationUnit.Minute), + }, + }); + + expect(() => validateSLO(slo)).toThrowError('Invalid objective.timeslice_target'); + }); + + it("throws when 'objective.timeslice_target' is gt 1", () => { + const slo = createSLO({ + budgetingMethod: 'timeslices', + objective: { + target: 0.95, + timesliceTarget: 1.001, + timesliceWindow: new Duration(1, DurationUnit.Minute), + }, + }); + expect(() => validateSLO(slo)).toThrowError('Invalid objective.timeslice_target'); + }); + + it("throws when 'objective.timeslice_window' is not present", () => { + const slo = createSLO({ + budgetingMethod: 'timeslices', + objective: { + target: 0.95, + timesliceTarget: 0.95, + }, + }); + + expect(() => validateSLO(slo)).toThrowError('Invalid objective.timeslice_window'); + }); + + it("throws when 'objective.timeslice_window' is not in minutes or hours", () => { + const slo = createSLO({ + budgetingMethod: 'timeslices', + objective: { + target: 0.95, + timesliceTarget: 0.95, + }, + }); + + expect(() => + validateSLO({ + ...slo, + objective: { ...slo.objective, timesliceWindow: new Duration(1, DurationUnit.Day) }, + }) + ).toThrowError('Invalid objective.timeslice_window'); + + expect(() => + validateSLO({ + ...slo, + objective: { ...slo.objective, timesliceWindow: new Duration(1, DurationUnit.Week) }, + }) + ).toThrowError('Invalid objective.timeslice_window'); + + expect(() => + validateSLO({ + ...slo, + objective: { ...slo.objective, timesliceWindow: new Duration(1, DurationUnit.Month) }, + }) + ).toThrowError('Invalid objective.timeslice_window'); + }); + + it("throws when 'objective.timeslice_window' is longer than 'slo.time_window'", () => { + const slo = createSLO({ + timeWindow: sevenDaysRolling(), + budgetingMethod: 'timeslices', + objective: { + target: 0.95, + timesliceTarget: 0.95, + timesliceWindow: new Duration(169, DurationUnit.Hour), // 1 week + 1 hours = 169 hours + }, + }); + + expect(() => validateSLO(slo)).toThrowError('Invalid objective.timeslice_window'); + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/observability/server/domain/services/validate_slo.ts b/x-pack/plugins/observability_solution/observability/server/domain/services/validate_slo.ts new file mode 100644 index 0000000000000..eb253f44cdf5a --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/server/domain/services/validate_slo.ts @@ -0,0 +1,122 @@ +/* + * 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 { + timeslicesBudgetingMethodSchema, + Duration, + DurationUnit, + rollingTimeWindowSchema, + calendarAlignedTimeWindowSchema, +} from '@kbn/slo-schema'; +import { IllegalArgumentError } from '../../errors'; +import { SLO } from '../models'; + +/** + * Asserts the SLO is valid from a business invariants point of view. + * e.g. a 'target' objective requires a number between ]0, 1] + * e.g. a 'timeslices' budgeting method requires an objective's timeslice_target to be defined. + * + * @param slo {SLO} + */ +export function validateSLO(slo: SLO) { + if (!isValidId(slo.id)) { + throw new IllegalArgumentError('Invalid id'); + } + + if (!isValidTargetNumber(slo.objective.target)) { + throw new IllegalArgumentError('Invalid objective.target'); + } + + if ( + rollingTimeWindowSchema.is(slo.timeWindow) && + !isValidRollingTimeWindowDuration(slo.timeWindow.duration) + ) { + throw new IllegalArgumentError('Invalid time_window.duration'); + } + + if ( + calendarAlignedTimeWindowSchema.is(slo.timeWindow) && + !isValidCalendarAlignedTimeWindowDuration(slo.timeWindow.duration) + ) { + throw new IllegalArgumentError('Invalid time_window.duration'); + } + + if (timeslicesBudgetingMethodSchema.is(slo.budgetingMethod)) { + if ( + slo.objective.timesliceTarget === undefined || + !isValidTargetNumber(slo.objective.timesliceTarget) + ) { + throw new IllegalArgumentError('Invalid objective.timeslice_target'); + } + + if ( + slo.objective.timesliceWindow === undefined || + !isValidTimesliceWindowDuration(slo.objective.timesliceWindow, slo.timeWindow.duration) + ) { + throw new IllegalArgumentError('Invalid objective.timeslice_window'); + } + } + + validateSettings(slo); +} + +function validateSettings(slo: SLO) { + if (!isValidFrequencySettings(slo.settings.frequency)) { + throw new IllegalArgumentError('Invalid settings.frequency'); + } + + if (!isValidSyncDelaySettings(slo.settings.syncDelay)) { + throw new IllegalArgumentError('Invalid settings.sync_delay'); + } +} + +function isValidId(id: string): boolean { + const MIN_ID_LENGTH = 8; + const MAX_ID_LENGTH = 36; + return MIN_ID_LENGTH <= id.length && id.length <= MAX_ID_LENGTH; +} + +function isValidTargetNumber(value: number): boolean { + return value > 0 && value < 1; +} + +function isValidRollingTimeWindowDuration(duration: Duration): boolean { + // 7, 30 or 90days accepted + return duration.unit === DurationUnit.Day && [7, 30, 90].includes(duration.value); +} + +function isValidCalendarAlignedTimeWindowDuration(duration: Duration): boolean { + // 1 week or 1 month + return [DurationUnit.Week, DurationUnit.Month].includes(duration.unit) && duration.value === 1; +} + +function isValidTimesliceWindowDuration(timesliceWindow: Duration, timeWindow: Duration): boolean { + return ( + [DurationUnit.Minute, DurationUnit.Hour].includes(timesliceWindow.unit) && + timesliceWindow.isShorterThan(timeWindow) + ); +} + +/** + * validate that 1 minute <= frequency < 1 hour + */ +function isValidFrequencySettings(frequency: Duration): boolean { + return ( + frequency.isLongerOrEqualThan(new Duration(1, DurationUnit.Minute)) && + frequency.isShorterThan(new Duration(1, DurationUnit.Hour)) + ); +} + +/** + * validate that 1 minute <= sync_delay < 6 hour + */ +function isValidSyncDelaySettings(syncDelay: Duration): boolean { + return ( + syncDelay.isLongerOrEqualThan(new Duration(1, DurationUnit.Minute)) && + syncDelay.isShorterThan(new Duration(6, DurationUnit.Hour)) + ); +} diff --git a/x-pack/plugins/observability_solution/observability/server/index.ts b/x-pack/plugins/observability_solution/observability/server/index.ts index 07fb79a05f412..0fe5e4c63caa3 100644 --- a/x-pack/plugins/observability_solution/observability/server/index.ts +++ b/x-pack/plugins/observability_solution/observability/server/index.ts @@ -14,6 +14,7 @@ import type { ObservabilityPluginSetup } from './plugin'; import { createOrUpdateIndex, Mappings } from './utils/create_or_update_index'; import { createOrUpdateIndexTemplate } from './utils/create_or_update_index_template'; import { ScopedAnnotationsClient } from './lib/annotations/bootstrap_annotations'; +import { CustomThresholdLocators } from './lib/rules/custom_threshold/custom_threshold_executor'; import { unwrapEsResponse, WrappedElasticsearchClientError, @@ -85,7 +86,12 @@ export const plugin = async (initContext: PluginInitializerContext) => { return new ObservabilityPlugin(initContext); }; -export type { Mappings, ObservabilityPluginSetup, ScopedAnnotationsClient }; +export type { + Mappings, + ObservabilityPluginSetup, + ScopedAnnotationsClient, + CustomThresholdLocators, +}; export { createOrUpdateIndex, createOrUpdateIndexTemplate, diff --git a/x-pack/plugins/observability_solution/observability/server/plugin.ts b/x-pack/plugins/observability_solution/observability/server/plugin.ts index 70a6e97b344fe..edeb277da22c4 100644 --- a/x-pack/plugins/observability_solution/observability/server/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/server/plugin.ts @@ -18,7 +18,6 @@ import { Logger, Plugin, PluginInitializerContext, - SavedObjectsClient, } from '@kbn/core/server'; import { LogsExplorerLocatorParams, LOGS_EXPLORER_LOCATOR_ID } from '@kbn/deeplinks-observability'; import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server'; @@ -32,18 +31,12 @@ import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, } from '@kbn/rule-data-utils'; -import { - TaskManagerSetupContract, - TaskManagerStartContract, -} from '@kbn/task-manager-plugin/server'; import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; import { SharePluginSetup } from '@kbn/share-plugin/server'; import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { SloOrphanSummaryCleanupTask } from './services/slo/tasks/orphan_summary_cleanup_task'; import { ObservabilityConfig } from '.'; -import { casesFeatureId, observabilityFeatureId, sloFeatureId } from '../common'; -import { SLO_BURN_RATE_RULE_TYPE_ID } from '../common/constants'; +import { casesFeatureId, observabilityFeatureId } from '../common'; import { kubernetesGuideConfig, kubernetesGuideId, @@ -54,14 +47,10 @@ import { bootstrapAnnotations, ScopedAnnotationsClientFactory, } from './lib/annotations/bootstrap_annotations'; -import { registerSloUsageCollector } from './lib/collectors/register'; import { registerRuleTypes } from './lib/rules/register_rule_types'; import { getObservabilityServerRouteRepository } from './routes/get_global_observability_server_route_repository'; import { registerRoutes } from './routes/register_routes'; -import { slo, SO_SLO_TYPE } from './saved_objects'; import { threshold } from './saved_objects/threshold'; -import { DefaultResourceInstaller, DefaultSLOInstaller } from './services/slo'; - import { uiSettings } from './ui_settings'; export type ObservabilityPluginSetup = ReturnType; @@ -75,19 +64,14 @@ interface PluginSetup { spaces?: SpacesPluginSetup; usageCollection?: UsageCollectionSetup; cloud?: CloudSetup; - taskManager: TaskManagerSetupContract; } interface PluginStart { alerting: PluginStartContract; - taskManager: TaskManagerStartContract; spaces?: SpacesPluginStart; } -const sloRuleTypes = [SLO_BURN_RATE_RULE_TYPE_ID]; - const o11yRuleTypes = [ - SLO_BURN_RATE_RULE_TYPE_ID, OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, ES_QUERY_ID, ML_ANOMALY_DETECTION_RULE_TYPE_ID, @@ -97,7 +81,6 @@ const o11yRuleTypes = [ export class ObservabilityPlugin implements Plugin { private logger: Logger; - private sloOrphanCleanupTask?: SloOrphanSummaryCleanupTask; constructor(private readonly initContext: PluginInitializerContext) { this.initContext = initContext; @@ -290,65 +273,12 @@ export class ObservabilityPlugin implements Plugin { const { ruleDataService } = plugins.ruleRegistry; - const savedObjectTypes = [SO_SLO_TYPE]; - plugins.features.registerKibanaFeature({ - id: sloFeatureId, - name: i18n.translate('xpack.observability.featureRegistry.linkSloTitle', { - defaultMessage: 'SLOs', - }), - order: 1200, - category: DEFAULT_APP_CATEGORIES.observability, - app: [sloFeatureId, 'kibana'], - catalogue: [sloFeatureId, 'observability'], - alerting: sloRuleTypes, - privileges: { - all: { - app: [sloFeatureId, 'kibana'], - catalogue: [sloFeatureId, 'observability'], - api: ['slo_write', 'slo_read', 'rac'], - savedObject: { - all: savedObjectTypes, - read: [], - }, - alerting: { - rule: { - all: sloRuleTypes, - }, - alert: { - all: sloRuleTypes, - }, - }, - ui: ['read', 'write'], - }, - read: { - app: [sloFeatureId, 'kibana'], - catalogue: [sloFeatureId, 'observability'], - api: ['slo_read', 'rac'], - savedObject: { - all: [], - read: savedObjectTypes, - }, - alerting: { - rule: { - read: sloRuleTypes, - }, - alert: { - read: sloRuleTypes, - }, - }, - ui: ['read'], - }, - }, - }); - - core.savedObjects.registerType(slo); core.savedObjects.registerType(threshold); registerRuleTypes(plugins.alerting, core.http.basePath, config, this.logger, ruleDataService, { alertsLocator, logsExplorerLocator, }); - registerSloUsageCollector(plugins.usageCollection); core.getStartServices().then(([coreStart, pluginStart]) => { registerRoutes({ @@ -366,24 +296,12 @@ export class ObservabilityPlugin implements Plugin { logger: this.logger, repository: getObservabilityServerRouteRepository(config), }); - - const esInternalClient = coreStart.elasticsearch.client.asInternalUser; - - const sloResourceInstaller = new DefaultResourceInstaller(esInternalClient, this.logger); - const sloInstaller = new DefaultSLOInstaller(sloResourceInstaller, this.logger); - sloInstaller.install(); }); /** * Register a config for the observability guide */ plugins.guidedOnboarding?.registerGuideConfig(kubernetesGuideId, kubernetesGuideConfig); - this.sloOrphanCleanupTask = new SloOrphanSummaryCleanupTask( - plugins.taskManager, - this.logger, - config - ); - return { getAlertDetailsConfig() { return config.unsafe.alertDetails; @@ -396,12 +314,7 @@ export class ObservabilityPlugin implements Plugin { }; } - public start(core: CoreStart, plugins: PluginStart) { - const internalSoClient = new SavedObjectsClient(core.savedObjects.createInternalRepository()); - const internalEsClient = core.elasticsearch.client.asInternalUser; - - this.sloOrphanCleanupTask?.start(plugins.taskManager, internalSoClient, internalEsClient); - } + public start(core: CoreStart, plugins: PluginStart) {} public stop() {} } diff --git a/x-pack/plugins/observability_solution/slo/common/index.ts b/x-pack/plugins/observability_solution/slo/common/index.ts index a55f3bb3d4c7d..5df6f7b1a996e 100644 --- a/x-pack/plugins/observability_solution/slo/common/index.ts +++ b/x-pack/plugins/observability_solution/slo/common/index.ts @@ -15,4 +15,4 @@ export const sloEditLocatorID = 'SLO_EDIT_LOCATOR'; export const sloListLocatorID = 'SLO_LIST_LOCATOR'; import { paths } from './locators/paths'; -export const sloPaths = paths; \ No newline at end of file +export const sloPaths = paths; diff --git a/x-pack/plugins/observability_solution/slo/kibana.jsonc b/x-pack/plugins/observability_solution/slo/kibana.jsonc index f01942d801e04..55514804fd062 100644 --- a/x-pack/plugins/observability_solution/slo/kibana.jsonc +++ b/x-pack/plugins/observability_solution/slo/kibana.jsonc @@ -11,10 +11,13 @@ "slo" ], "requiredPlugins": [ + "alerting", "observability", "observabilityShared", "ruleRegistry", + "taskManager", "triggersActionsUi", + "share", "unifiedSearch", "uiActions", "lens", @@ -23,6 +26,7 @@ "dataViews", "dataViewEditor", "presentationUtil", + "features", "licensing" ] } diff --git a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_mappings_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_mappings_template.ts index dfb98fcb42206..c1d143e41c11b 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_mappings_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_mappings_template.ts @@ -5,7 +5,7 @@ * 2.0. */ import type { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOMappingsTemplate = (name: string): ClusterPutComponentTemplateRequest => ({ name, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_settings_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_settings_template.ts index 37abff5bdc46d..5e8845a050688 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_settings_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_settings_template.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOSettingsTemplate = (name: string) => ({ name, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts index 15632ea033252..2698a39f7a6b3 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts @@ -5,7 +5,7 @@ * 2.0. */ import type { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOSummaryMappingsTemplate = ( name: string diff --git a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_settings_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_settings_template.ts index 9995e2239d07f..f9b18c7f62555 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_settings_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_settings_template.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOSummarySettingsTemplate = (name: string) => ({ name, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_index_templates.ts b/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_index_templates.ts index ae6f179476b22..6524d6e7d49cf 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_index_templates.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_index_templates.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOIndexTemplate = (name: string, indexPattern: string, composedOf: string[]) => ({ name, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_summary_index_templates.ts b/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_summary_index_templates.ts index 2e613c4273bab..3986273ca99ce 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_summary_index_templates.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/index_templates/slo_summary_index_templates.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOSummaryIndexTemplate = ( name: string, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts index 6a3a6684ab191..bceb324dd21fd 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export const getSLOPipelineTemplate = (id: string, indexNamePrefix: string) => ({ id, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts index d279c925f86bf..59cfceedd5aff 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts @@ -6,7 +6,7 @@ */ import { timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; -import { getSLOSummaryPipelineId, SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { getSLOSummaryPipelineId, SLO_RESOURCES_VERSION } from '../../../common/constants'; import { SLO } from '../../domain/models'; export const getSLOSummaryPipelineTemplate = (slo: SLO, spaceId: string) => { diff --git a/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.ts index 152517d7aa775..17c48bb8414a9 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.ts @@ -12,7 +12,7 @@ import { TransformSource, TransformTimeSync, } from '@elastic/elasticsearch/lib/api/types'; -import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants'; +import { SLO_RESOURCES_VERSION } from '../../../common/constants'; export interface TransformSettings { frequency: TransformPutTransformRequest['frequency']; diff --git a/x-pack/plugins/observability_solution/slo/server/errors/errors.ts b/x-pack/plugins/observability_solution/slo/server/errors/errors.ts new file mode 100644 index 0000000000000..eaec36e66d08b --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/errors/errors.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/* eslint-disable max-classes-per-file */ + +export class ObservabilityError extends Error { + constructor(message?: string) { + super(message); + this.name = this.constructor.name; + } +} + +export class SLONotFound extends ObservabilityError {} +export class SLOIdConflict extends ObservabilityError {} + +export class InvalidQueryError extends ObservabilityError {} +export class InternalQueryError extends ObservabilityError {} +export class NotSupportedError extends ObservabilityError {} +export class IllegalArgumentError extends ObservabilityError {} +export class InvalidTransformError extends ObservabilityError {} + +export class SecurityException extends ObservabilityError {} diff --git a/x-pack/plugins/observability_solution/slo/server/errors/handler.ts b/x-pack/plugins/observability_solution/slo/server/errors/handler.ts new file mode 100644 index 0000000000000..c10f1d98c083e --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/errors/handler.ts @@ -0,0 +1,24 @@ +/* + * 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 { ObservabilityError, SecurityException, SLOIdConflict, SLONotFound } from './errors'; + +export function getHTTPResponseCode(error: ObservabilityError): number { + if (error instanceof SLONotFound) { + return 404; + } + + if (error instanceof SLOIdConflict) { + return 409; + } + + if (error instanceof SecurityException) { + return 403; + } + + return 400; +} diff --git a/x-pack/plugins/observability_solution/slo/server/errors/index.ts b/x-pack/plugins/observability_solution/slo/server/errors/index.ts new file mode 100644 index 0000000000000..e466d5b8ae4a1 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/errors/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export * from './errors'; +export * from './handler'; diff --git a/x-pack/plugins/observability_solution/slo/server/index.ts b/x-pack/plugins/observability_solution/slo/server/index.ts index 5d79cec7fa115..b23baf394d5f2 100644 --- a/x-pack/plugins/observability_solution/slo/server/index.ts +++ b/x-pack/plugins/observability_solution/slo/server/index.ts @@ -1,4 +1,12 @@ -import { PluginInitializerContext } from '../../../src/core/server'; +/* + * 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 { PluginInitializerContext } from '@kbn/core/server'; +import { schema, TypeOf } from '@kbn/config-schema'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. @@ -9,3 +17,12 @@ export async function plugin(initializerContext: PluginInitializerContext) { } export type { SlosPluginSetup, SlosPluginStart } from './types'; + +const configSchema = schema.object({ + sloOrphanSummaryCleanUpTaskEnabled: schema.boolean({ defaultValue: true }), +}); + +export const config = { + schema: configSchema, +}; +export type SloConfig = TypeOf; diff --git a/x-pack/plugins/observability_solution/observability/server/lib/collectors/fetcher.test.ts b/x-pack/plugins/observability_solution/slo/server/lib/collectors/fetcher.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/observability/server/lib/collectors/fetcher.test.ts rename to x-pack/plugins/observability_solution/slo/server/lib/collectors/fetcher.test.ts diff --git a/x-pack/plugins/observability_solution/observability/server/lib/collectors/fetcher.ts b/x-pack/plugins/observability_solution/slo/server/lib/collectors/fetcher.ts similarity index 99% rename from x-pack/plugins/observability_solution/observability/server/lib/collectors/fetcher.ts rename to x-pack/plugins/observability_solution/slo/server/lib/collectors/fetcher.ts index f8657b71d410c..566a5e88a5cfe 100644 --- a/x-pack/plugins/observability_solution/observability/server/lib/collectors/fetcher.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/collectors/fetcher.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { CollectorFetchContext } from '@kbn/usage-collection-plugin/server'; import { StoredSLO } from '../../domain/models'; import { SO_SLO_TYPE } from '../../saved_objects'; diff --git a/x-pack/plugins/observability_solution/observability/server/lib/collectors/register.ts b/x-pack/plugins/observability_solution/slo/server/lib/collectors/register.ts similarity index 100% rename from x-pack/plugins/observability_solution/observability/server/lib/collectors/register.ts rename to x-pack/plugins/observability_solution/slo/server/lib/collectors/register.ts diff --git a/x-pack/plugins/observability_solution/observability/server/lib/collectors/type.ts b/x-pack/plugins/observability_solution/slo/server/lib/collectors/type.ts similarity index 100% rename from x-pack/plugins/observability_solution/observability/server/lib/collectors/type.ts rename to x-pack/plugins/observability_solution/slo/server/lib/collectors/type.ts diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/register_rule_types.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/register_rule_types.ts index de0d07085dbfc..3df263fcff0bf 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/register_rule_types.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/register_rule_types.ts @@ -14,6 +14,7 @@ import { } from '@kbn/rule-registry-plugin/server'; import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils'; +import { CustomThresholdLocators } from '@kbn/observability-plugin/server'; import { sloFeatureId } from '../../../common'; import { SLO_RULE_REGISTRATION_CONTEXT } from '../../common/constants'; import { sloBurnRateRuleType } from './slo_burn_rate'; @@ -23,7 +24,8 @@ export function registerRuleTypes( alertingPlugin: PluginSetupContract, basePath: IBasePath, logger: Logger, - ruleDataService: IRuleDataService + ruleDataService: IRuleDataService, + locators: CustomThresholdLocators // TODO move this somewhere else ) { // SLO RULE const ruleDataClientSLO = ruleDataService.initializeIndex({ diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts index 3454406f5619c..6fdddfca98453 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts @@ -27,7 +27,7 @@ import { SLO_REVISION_FIELD, } from '../../../../common/field_names/slo'; import { Duration } from '../../../domain/models'; -import { KibanaSavedObjectsSLORepository } from '../../../services/slo'; +import { KibanaSavedObjectsSLORepository } from '../../../services'; import { AlertStates, BurnRateAlertContext, diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts index 45ebba7bb2693..ef13974c6a771 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts @@ -9,7 +9,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { get } from 'lodash'; import { Duration, SLO, toDurationUnit } from '../../../../domain/models'; import { BurnRateRuleParams } from '../types'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../../../common/slo/constants'; +import { SLO_DESTINATION_INDEX_PATTERN } from '../../../../../common/constants'; import { buildQuery, EvaluationAfterKey, diff --git a/x-pack/plugins/observability_solution/slo/server/plugin.ts b/x-pack/plugins/observability_solution/slo/server/plugin.ts index 1d1df3919504f..900a6bbca4c31 100644 --- a/x-pack/plugins/observability_solution/slo/server/plugin.ts +++ b/x-pack/plugins/observability_solution/slo/server/plugin.ts @@ -1,33 +1,181 @@ +/* + * 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 { i18n } from '@kbn/i18n'; import { PluginInitializerContext, CoreSetup, CoreStart, + DEFAULT_APP_CATEGORIES, Plugin, Logger, -} from '../../../src/core/server'; + SavedObjectsClient, +} from '@kbn/core/server'; +import { PluginSetupContract, PluginStartContract } from '@kbn/alerting-plugin/server'; +import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server'; +import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; +import { + TaskManagerSetupContract, + TaskManagerStartContract, +} from '@kbn/task-manager-plugin/server'; +import { SharePluginSetup } from '@kbn/share-plugin/server'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import { AlertsLocatorDefinition } from '@kbn/observability-plugin/common'; +import { registerSloUsageCollector } from './lib/collectors/register'; + +import { SloOrphanSummaryCleanupTask } from './services/tasks/orphan_summary_cleanup_task'; +import { sloFeatureId } from '../common'; +import { SLO_BURN_RATE_RULE_TYPE_ID } from '../common/constants'; +import { slo, SO_SLO_TYPE } from './saved_objects'; +import { DefaultResourceInstaller, DefaultSLOInstaller } from './services'; +import { registerRuleTypes } from './lib/rules/register_rule_types'; +import { SloConfig } from '.'; +import { registerRoutes } from './routes/register_routes'; +import { getSloServerRouteRepository } from './routes/get_slo_server_route_repository'; + +// TODO think about renaming to singular +interface SlosPluginSetup { + alerting: PluginSetupContract; + ruleRegistry: RuleRegistryPluginSetupContract; + share: SharePluginSetup; + features: FeaturesSetup; + taskManager: TaskManagerSetupContract; + spaces?: SpacesPluginSetup; + usageCollection?: UsageCollectionSetup; +} -import { SlosPluginSetup, SlosPluginStart } from './types'; -import { defineRoutes } from './routes'; +interface SlosPluginStart { + alerting: PluginStartContract; + taskManager: TaskManagerStartContract; + spaces?: SpacesPluginStart; +} + +const sloRuleTypes = [SLO_BURN_RATE_RULE_TYPE_ID]; +// TODO think about renaning SlosPlugin to SloPlugin export class SlosPlugin implements Plugin { private readonly logger: Logger; + private sloOrphanCleanupTask?: SloOrphanSummaryCleanupTask; - constructor(initializerContext: PluginInitializerContext) { - this.logger = initializerContext.logger.get(); + constructor(private readonly initContext: PluginInitializerContext) { + this.initContext = initContext; + this.logger = initContext.logger.get(); } - public setup(core: CoreSetup) { - this.logger.debug('slos: Setup'); + public setup(core: CoreSetup, plugins: SlosPluginSetup) { + const config = this.initContext.config.get(); + const alertsLocator = plugins.share.url.locators.create(new AlertsLocatorDefinition()); + const router = core.http.createRouter(); // Register server side APIs - defineRoutes(router); + // defineRoutes(router); - return {}; + const savedObjectTypes = [SO_SLO_TYPE]; + + plugins.features.registerKibanaFeature({ + id: sloFeatureId, + name: i18n.translate('xpack.observability.featureRegistry.linkSloTitle', { + defaultMessage: 'SLOs', + }), + order: 1200, + category: DEFAULT_APP_CATEGORIES.observability, + app: [sloFeatureId, 'kibana'], + catalogue: [sloFeatureId, 'observability'], + alerting: sloRuleTypes, + privileges: { + all: { + app: [sloFeatureId, 'kibana'], + catalogue: [sloFeatureId, 'observability'], + api: ['slo_write', 'slo_read', 'rac'], + savedObject: { + all: savedObjectTypes, + read: [], + }, + alerting: { + rule: { + all: sloRuleTypes, + }, + alert: { + all: sloRuleTypes, + }, + }, + ui: ['read', 'write'], + }, + read: { + app: [sloFeatureId, 'kibana'], + catalogue: [sloFeatureId, 'observability'], + api: ['slo_read', 'rac'], + savedObject: { + all: [], + read: savedObjectTypes, + }, + alerting: { + rule: { + read: sloRuleTypes, + }, + alert: { + read: sloRuleTypes, + }, + }, + ui: ['read'], + }, + }, + }); + + const { ruleDataService } = plugins.ruleRegistry; + + core.savedObjects.registerType(slo); + + registerRuleTypes(plugins.alerting, core.http.basePath, this.logger, ruleDataService, { + alertsLocator, + }); + + registerSloUsageCollector(plugins.usageCollection); + + core.getStartServices().then(([coreStart, pluginStart]) => { + registerRoutes({ + core, + config, + dependencies: { + pluginsSetup: { + ...plugins, + core, + }, + spaces: pluginStart.spaces, + ruleDataService, + getRulesClientWithRequest: pluginStart.alerting.getRulesClientWithRequest, + }, + logger: this.logger, + repository: getSloServerRouteRepository(config), + }); + + const esInternalClient = coreStart.elasticsearch.client.asInternalUser; + + const sloResourceInstaller = new DefaultResourceInstaller(esInternalClient, this.logger); + const sloInstaller = new DefaultSLOInstaller(sloResourceInstaller, this.logger); + sloInstaller.install(); + }); + + this.sloOrphanCleanupTask = new SloOrphanSummaryCleanupTask( + plugins.taskManager, + this.logger, + config + ); } - public start(core: CoreStart) { + public start(core: CoreStart, plugins: SlosPluginStart) { this.logger.debug('slos: Started'); + const internalSoClient = new SavedObjectsClient(core.savedObjects.createInternalRepository()); + const internalEsClient = core.elasticsearch.client.asInternalUser; + + this.sloOrphanCleanupTask?.start(plugins.taskManager, internalSoClient, internalEsClient); + return {}; } diff --git a/x-pack/plugins/observability_solution/slo/server/routes/create_slo_server_route.ts b/x-pack/plugins/observability_solution/slo/server/routes/create_slo_server_route.ts new file mode 100644 index 0000000000000..762b5b369f6e6 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/routes/create_slo_server_route.ts @@ -0,0 +1,13 @@ +/* + * 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 { createServerRouteFactory } from '@kbn/server-route-repository'; +import { SloRouteCreateOptions, SloRouteHandlerResources } from './types'; + +export const createSloServerRoute = createServerRouteFactory< + SloRouteHandlerResources, + SloRouteCreateOptions +>(); diff --git a/x-pack/plugins/observability_solution/slo/server/routes/get_global_observability_server_route_repository.ts b/x-pack/plugins/observability_solution/slo/server/routes/get_slo_server_route_repository.ts similarity index 54% rename from x-pack/plugins/observability_solution/slo/server/routes/get_global_observability_server_route_repository.ts rename to x-pack/plugins/observability_solution/slo/server/routes/get_slo_server_route_repository.ts index d6a71120bb37b..bd062771017fd 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/get_global_observability_server_route_repository.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/get_slo_server_route_repository.ts @@ -5,18 +5,14 @@ * 2.0. */ -import { ObservabilityConfig } from '..'; -import { rulesRouteRepository } from './rules/route'; +import { SloConfig } from '..'; import { sloRouteRepository } from './slo/route'; -export function getObservabilityServerRouteRepository(config: ObservabilityConfig) { +export function getSloServerRouteRepository(config: SloConfig) { const repository = { - ...rulesRouteRepository, ...sloRouteRepository, }; return repository; } -export type ObservabilityServerRouteRepository = ReturnType< - typeof getObservabilityServerRouteRepository ->; +export type SloServerRouteRepository = ReturnType; diff --git a/x-pack/plugins/observability_solution/slo/server/routes/register_routes.ts b/x-pack/plugins/observability_solution/slo/server/routes/register_routes.ts index 92980f20c4646..000a4cc19611d 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/register_routes.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/register_routes.ts @@ -17,13 +17,13 @@ import { import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import axios from 'axios'; import * as t from 'io-ts'; -import { ObservabilityConfig } from '..'; +import { SloConfig } from '..'; import { getHTTPResponseCode, ObservabilityError } from '../errors'; import { ObservabilityRequestHandlerContext } from '../types'; import { AbstractObservabilityServerRouteRepository } from './types'; interface RegisterRoutes { - config: ObservabilityConfig; + config: SloConfig; core: CoreSetup; repository: AbstractObservabilityServerRouteRepository; logger: Logger; diff --git a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts index 2ec1f37e7ac27..de8a901b29687 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts @@ -36,18 +36,18 @@ import { KibanaSavedObjectsSLORepository, UpdateSLO, FindSLOGroups, -} from '../../services/slo'; -import { FetchHistoricalSummary } from '../../services/slo/fetch_historical_summary'; -import { FindSLODefinitions } from '../../services/slo/find_slo_definitions'; -import { getBurnRates } from '../../services/slo/get_burn_rates'; -import { getGlobalDiagnosis } from '../../services/slo/get_diagnosis'; -import { GetPreviewData } from '../../services/slo/get_preview_data'; -import { GetSLOInstances } from '../../services/slo/get_slo_instances'; -import { DefaultHistoricalSummaryClient } from '../../services/slo/historical_summary_client'; -import { ManageSLO } from '../../services/slo/manage_slo'; -import { ResetSLO } from '../../services/slo/reset_slo'; -import { DefaultSummarySearchClient } from '../../services/slo/summary_search_client'; -import { DefaultSummaryTransformGenerator } from '../../services/slo/summary_transform_generator/summary_transform_generator'; +} from '../../services'; +import { FetchHistoricalSummary } from '../../services/fetch_historical_summary'; +import { FindSLODefinitions } from '../../services/find_slo_definitions'; +import { getBurnRates } from '../../services/get_burn_rates'; +import { getGlobalDiagnosis } from '../../services/get_diagnosis'; +import { GetPreviewData } from '../../services/get_preview_data'; +import { GetSLOInstances } from '../../services/get_slo_instances'; +import { DefaultHistoricalSummaryClient } from '../../services/historical_summary_client'; +import { ManageSLO } from '../../services/manage_slo'; +import { ResetSLO } from '../../services/reset_slo'; +import { DefaultSummarySearchClient } from '../../services/summary_search_client'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; import { ApmTransactionDurationTransformGenerator, ApmTransactionErrorRateTransformGenerator, @@ -56,9 +56,9 @@ import { MetricCustomTransformGenerator, TimesliceMetricTransformGenerator, TransformGenerator, -} from '../../services/slo/transform_generators'; -import type { ObservabilityRequestHandlerContext } from '../../types'; -import { createObservabilityServerRoute } from '../create_observability_server_route'; +} from '../../services/transform_generators'; +import type { SloRequestHandlerContext } from '../../types'; +import { createSloServerRoute } from '../create_slo_server_route'; const transformGenerators: Record = { 'sli.apm.transactionDuration': new ApmTransactionDurationTransformGenerator(), @@ -69,7 +69,7 @@ const transformGenerators: Record = { 'sli.metric.timeslice': new TimesliceMetricTransformGenerator(), }; -const assertPlatinumLicense = async (context: ObservabilityRequestHandlerContext) => { +const assertPlatinumLicense = async (context: SloRequestHandlerContext) => { const licensing = await context.licensing; const hasCorrectLicense = licensing.license.hasAtLeast('platinum'); @@ -78,7 +78,7 @@ const assertPlatinumLicense = async (context: ObservabilityRequestHandlerContext } }; -const createSLORoute = createObservabilityServerRoute({ +const createSLORoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos 2023-10-31', options: { tags: ['access:slo_write'], @@ -116,7 +116,7 @@ const createSLORoute = createObservabilityServerRoute({ }, }); -const inspectSLORoute = createObservabilityServerRoute({ +const inspectSLORoute = createSloServerRoute({ endpoint: 'POST /internal/api/observability/slos/_inspect 2023-10-31', options: { tags: ['access:slo_write'], @@ -152,7 +152,7 @@ const inspectSLORoute = createObservabilityServerRoute({ }, }); -const updateSLORoute = createObservabilityServerRoute({ +const updateSLORoute = createSloServerRoute({ endpoint: 'PUT /api/observability/slos/{id} 2023-10-31', options: { tags: ['access:slo_write'], @@ -190,7 +190,7 @@ const updateSLORoute = createObservabilityServerRoute({ }, }); -const deleteSLORoute = createObservabilityServerRoute({ +const deleteSLORoute = createSloServerRoute({ endpoint: 'DELETE /api/observability/slos/{id} 2023-10-31', options: { tags: ['access:slo_write'], @@ -231,7 +231,7 @@ const deleteSLORoute = createObservabilityServerRoute({ }, }); -const getSLORoute = createObservabilityServerRoute({ +const getSLORoute = createSloServerRoute({ endpoint: 'GET /api/observability/slos/{id} 2023-10-31', options: { tags: ['access:slo_read'], @@ -253,7 +253,7 @@ const getSLORoute = createObservabilityServerRoute({ }, }); -const enableSLORoute = createObservabilityServerRoute({ +const enableSLORoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos/{id}/enable 2023-10-31', options: { tags: ['access:slo_write'], @@ -282,7 +282,7 @@ const enableSLORoute = createObservabilityServerRoute({ }, }); -const disableSLORoute = createObservabilityServerRoute({ +const disableSLORoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos/{id}/disable 2023-10-31', options: { tags: ['access:slo_write'], @@ -311,7 +311,7 @@ const disableSLORoute = createObservabilityServerRoute({ }, }); -const resetSLORoute = createObservabilityServerRoute({ +const resetSLORoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos/{id}/_reset 2023-10-31', options: { tags: ['access:slo_write'], @@ -349,7 +349,7 @@ const resetSLORoute = createObservabilityServerRoute({ }, }); -const findSLORoute = createObservabilityServerRoute({ +const findSLORoute = createSloServerRoute({ endpoint: 'GET /api/observability/slos 2023-10-31', options: { tags: ['access:slo_read'], @@ -373,7 +373,7 @@ const findSLORoute = createObservabilityServerRoute({ }, }); -const findSLOGroupsRoute = createObservabilityServerRoute({ +const findSLOGroupsRoute = createSloServerRoute({ endpoint: 'GET /internal/api/observability/slos/_groups', options: { tags: ['access:slo_read'], @@ -392,7 +392,7 @@ const findSLOGroupsRoute = createObservabilityServerRoute({ }, }); -const deleteSloInstancesRoute = createObservabilityServerRoute({ +const deleteSloInstancesRoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos/_delete_instances 2023-10-31', options: { tags: ['access:slo_write'], @@ -408,7 +408,7 @@ const deleteSloInstancesRoute = createObservabilityServerRoute({ }, }); -const findSloDefinitionsRoute = createObservabilityServerRoute({ +const findSloDefinitionsRoute = createSloServerRoute({ endpoint: 'GET /api/observability/slos/_definitions 2023-10-31', options: { tags: ['access:slo_read'], @@ -427,7 +427,7 @@ const findSloDefinitionsRoute = createObservabilityServerRoute({ }, }); -const fetchHistoricalSummary = createObservabilityServerRoute({ +const fetchHistoricalSummary = createSloServerRoute({ endpoint: 'POST /internal/observability/slos/_historical_summary', options: { tags: ['access:slo_read'], @@ -449,7 +449,7 @@ const fetchHistoricalSummary = createObservabilityServerRoute({ }, }); -const getSLOInstancesRoute = createObservabilityServerRoute({ +const getSLOInstancesRoute = createSloServerRoute({ endpoint: 'GET /internal/observability/slos/{id}/_instances', options: { tags: ['access:slo_read'], @@ -471,7 +471,7 @@ const getSLOInstancesRoute = createObservabilityServerRoute({ }, }); -const getDiagnosisRoute = createObservabilityServerRoute({ +const getDiagnosisRoute = createSloServerRoute({ endpoint: 'GET /internal/observability/slos/_diagnosis', options: { tags: [], @@ -494,7 +494,7 @@ const getDiagnosisRoute = createObservabilityServerRoute({ }, }); -const getSloBurnRates = createObservabilityServerRoute({ +const getSloBurnRates = createSloServerRoute({ endpoint: 'POST /internal/observability/slos/{id}/_burn_rates', options: { tags: ['access:slo_read'], @@ -520,7 +520,7 @@ const getSloBurnRates = createObservabilityServerRoute({ }, }); -const getPreviewData = createObservabilityServerRoute({ +const getPreviewData = createSloServerRoute({ endpoint: 'POST /internal/observability/slos/_preview', options: { tags: ['access:slo_read'], diff --git a/x-pack/plugins/observability_solution/slo/server/routes/types.ts b/x-pack/plugins/observability_solution/slo/server/routes/types.ts new file mode 100644 index 0000000000000..f00a027e98d4d --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/routes/types.ts @@ -0,0 +1,36 @@ +/* + * 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 { EndpointOf, ReturnOf, ServerRouteRepository } from '@kbn/server-route-repository'; +import { KibanaRequest, Logger } from '@kbn/core/server'; + +import { SloServerRouteRepository } from './get_slo_server_route_repository'; +import { SloRequestHandlerContext } from '../types'; +import { RegisterRoutesDependencies } from './register_routes'; +import { SloConfig } from '..'; + +export type { SloServerRouteRepository }; + +export interface SloRouteHandlerResources { + context: SloRequestHandlerContext; + dependencies: RegisterRoutesDependencies; + logger: Logger; + request: KibanaRequest; + config: SloConfig; +} + +export interface SloRouteCreateOptions { + options: { + tags: string[]; + access?: 'public' | 'internal'; + }; +} + +// export type AbstractObservabilityServerRouteRepository = ServerRouteRepository; + +// export type ObservabilityAPIReturnType< +// TEndpoint extends EndpointOf +// > = ReturnOf; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/create_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/create_slo.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/delete_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/delete_slo.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/delete_slo.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/delete_slo.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/get_slo_instances.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/get_slo_instances.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/get_slo_instances.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/get_slo_instances.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/historical_summary_client.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/historical_summary_client.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/historical_summary_client.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/historical_summary_client.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/manage_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/manage_slo.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/manage_slo.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/manage_slo.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/reset_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/reset_slo.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/summary_client.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_client.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/summary_client.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_client.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/summary_search_client.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_search_client.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/summary_search_client.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_search_client.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/update_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/update_slo.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/__snapshots__/update_slo.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/__snapshots__/update_slo.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/__snapshots__/get_custom_metric_indicator_aggregation.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/aggregations/__snapshots__/get_custom_metric_indicator_aggregation.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/__snapshots__/get_custom_metric_indicator_aggregation.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/__snapshots__/get_custom_metric_indicator_aggregation.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/__snapshots__/get_histogram_indicator_aggregation.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/aggregations/__snapshots__/get_histogram_indicator_aggregation.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/__snapshots__/get_histogram_indicator_aggregation.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/__snapshots__/get_histogram_indicator_aggregation.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.test.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_histogram_indicator_aggregation.test.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/get_histogram_indicator_aggregation.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_histogram_indicator_aggregation.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/get_histogram_indicator_aggregation.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_histogram_indicator_aggregation.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/get_histogram_indicator_aggregation.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_histogram_indicator_aggregation.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/get_histogram_indicator_aggregation.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.test.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/index.ts b/x-pack/plugins/observability_solution/slo/server/services/aggregations/index.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/aggregations/index.ts rename to x-pack/plugins/observability_solution/slo/server/services/aggregations/index.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/create_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/create_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/create_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts similarity index 92% rename from x-pack/plugins/observability_solution/slo/server/services/slo/create_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/create_slo.ts index 89e8c7165f395..d83f1e1253a52 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/create_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts @@ -15,11 +15,11 @@ import { getSLOTransformId, SLO_MODEL_VERSION, SLO_SUMMARY_TEMP_INDEX_NAME, -} from '../../../common/slo/constants'; -import { getSLOSummaryPipelineTemplate } from '../../assets/ingest_templates/slo_summary_pipeline_template'; -import { Duration, DurationUnit, SLO } from '../../domain/models'; -import { validateSLO } from '../../domain/services'; -import { retryTransientEsErrors } from '../../utils/retry'; +} from '../../common/constants'; +import { getSLOSummaryPipelineTemplate } from '../assets/ingest_templates/slo_summary_pipeline_template'; +import { Duration, DurationUnit, SLO } from '../domain/models'; +import { validateSLO } from '../domain/services'; +import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; import { TransformManager } from './transform_manager'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts similarity index 96% rename from x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts index e3d6663860222..fa6652dbb30cf 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts @@ -13,8 +13,8 @@ import { getSLOTransformId, SLO_DESTINATION_INDEX_PATTERN, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, -} from '../../../common/slo/constants'; -import { retryTransientEsErrors } from '../../utils/retry'; +} from '../../common/constants'; +import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; import { TransformManager } from './transform_manager'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo_instances.test.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo_instances.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo_instances.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/delete_slo_instances.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo_instances.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo_instances.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo_instances.ts rename to x-pack/plugins/observability_solution/slo/server/services/delete_slo_instances.ts index 97c622f354564..353983d76a90b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/delete_slo_instances.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/delete_slo_instances.ts @@ -10,8 +10,8 @@ import { ALL_VALUE, DeleteSLOInstancesParams } from '@kbn/slo-schema'; import { SLO_DESTINATION_INDEX_PATTERN, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, -} from '../../../common/slo/constants'; -import { IllegalArgumentError } from '../../errors'; +} from '../../common/constants'; +import { IllegalArgumentError } from '../errors'; interface SloInstanceTuple { sloId: string; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fetch_historical_summary.ts b/x-pack/plugins/observability_solution/slo/server/services/fetch_historical_summary.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fetch_historical_summary.ts rename to x-pack/plugins/observability_solution/slo/server/services/fetch_historical_summary.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts similarity index 98% rename from x-pack/plugins/observability_solution/slo/server/services/slo/find_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts index 396f026b936b3..e1dbc7a606891 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts @@ -6,8 +6,8 @@ */ import { ALL_VALUE, Paginated } from '@kbn/slo-schema'; -import { SLO_MODEL_VERSION } from '../../../common/slo/constants'; -import { SLO } from '../../domain/models'; +import { SLO_MODEL_VERSION } from '../../common/constants'; +import { SLO } from '../domain/models'; import { FindSLO } from './find_slo'; import { createSLO } from './fixtures/slo'; import { createSLORepositoryMock, createSummarySearchClientMock } from './mocks'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/find_slo.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/find_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/find_slo.ts index b92e53bd5cd5b..ef766a72886c4 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/find_slo.ts @@ -6,8 +6,8 @@ */ import { FindSLOParams, FindSLOResponse, findSLOResponseSchema, Pagination } from '@kbn/slo-schema'; -import { SLO, SLOWithSummary } from '../../domain/models'; -import { IllegalArgumentError } from '../../errors'; +import { SLO, SLOWithSummary } from '../domain/models'; +import { IllegalArgumentError } from '../errors'; import { SLORepository } from './slo_repository'; import { SLOSummary, Sort, SummarySearchClient } from './summary_search_client'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo_definitions.ts b/x-pack/plugins/observability_solution/slo/server/services/find_slo_definitions.ts similarity index 96% rename from x-pack/plugins/observability_solution/slo/server/services/slo/find_slo_definitions.ts rename to x-pack/plugins/observability_solution/slo/server/services/find_slo_definitions.ts index 38076d67202d5..221a4d0ca65be 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo_definitions.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/find_slo_definitions.ts @@ -11,7 +11,7 @@ import { findSloDefinitionsResponseSchema, Pagination, } from '@kbn/slo-schema'; -import { IllegalArgumentError } from '../../errors'; +import { IllegalArgumentError } from '../errors'; import { SLORepository } from './slo_repository'; const MAX_PER_PAGE = 1000; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo_groups.ts b/x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts similarity index 96% rename from x-pack/plugins/observability_solution/slo/server/services/slo/find_slo_groups.ts rename to x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts index 5c0cfbe178367..a603de597ae65 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/find_slo_groups.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts @@ -8,13 +8,13 @@ import { FindSLOGroupsParams, FindSLOGroupsResponse, Pagination } from '@kbn/slo import { ElasticsearchClient } from '@kbn/core/server'; import { findSLOGroupsResponseSchema } from '@kbn/slo-schema'; import { Logger } from '@kbn/core/server'; -import { typedSearch } from '../../utils/queries'; -import { IllegalArgumentError } from '../../errors'; +import { typedSearch } from '../utils/queries'; +import { IllegalArgumentError } from '../errors'; import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN, DEFAULT_SLO_GROUPS_PAGE_SIZE, -} from '../../../common/slo/constants'; -import { Status } from '../../domain/models'; +} from '../../common/constants'; +import { Status } from '../domain/models'; import { getElasticsearchQueryOrThrow } from './transform_generators'; const DEFAULT_PAGE = 1; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/date.ts b/x-pack/plugins/observability_solution/slo/server/services/fixtures/date.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/date.ts rename to x-pack/plugins/observability_solution/slo/server/services/fixtures/date.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/duration.ts b/x-pack/plugins/observability_solution/slo/server/services/fixtures/duration.ts similarity index 94% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/duration.ts rename to x-pack/plugins/observability_solution/slo/server/services/fixtures/duration.ts index 26690b6680f18..c4bba6eae797b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/duration.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/fixtures/duration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Duration, DurationUnit } from '../../../domain/models'; +import { Duration, DurationUnit } from '../../domain/models'; export function thirtyDays(): Duration { return new Duration(30, DurationUnit.Day); diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/error_budget.ts b/x-pack/plugins/observability_solution/slo/server/services/fixtures/error_budget.ts similarity index 89% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/error_budget.ts rename to x-pack/plugins/observability_solution/slo/server/services/fixtures/error_budget.ts index 5b7f82af16ef9..dc5dcb0a07812 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/error_budget.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/fixtures/error_budget.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ErrorBudget } from '../../../domain/models'; +import { ErrorBudget } from '../../domain/models'; export function createErrorBudget(params: Partial = {}): ErrorBudget { return { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/slo.ts b/x-pack/plugins/observability_solution/slo/server/services/fixtures/slo.ts similarity index 98% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/fixtures/slo.ts index 0f75c83775489..ee2c0630e58dc 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/fixtures/slo.ts @@ -15,7 +15,7 @@ import { } from '@kbn/slo-schema'; import { cloneDeep } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; -import { SLO_MODEL_VERSION } from '../../../../common/slo/constants'; +import { SLO_MODEL_VERSION } from '../../../common/constants'; import { APMTransactionDurationIndicator, APMTransactionErrorRateIndicator, diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/summary_search_document.ts b/x-pack/plugins/observability_solution/slo/server/services/fixtures/summary_search_document.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/summary_search_document.ts rename to x-pack/plugins/observability_solution/slo/server/services/fixtures/summary_search_document.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/time_window.ts b/x-pack/plugins/observability_solution/slo/server/services/fixtures/time_window.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/fixtures/time_window.ts rename to x-pack/plugins/observability_solution/slo/server/services/fixtures/time_window.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_burn_rates.ts b/x-pack/plugins/observability_solution/slo/server/services/get_burn_rates.ts similarity index 92% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_burn_rates.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_burn_rates.ts index ee540bdd7cb23..9ce58767a868e 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/get_burn_rates.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_burn_rates.ts @@ -8,8 +8,8 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { Logger } from '@kbn/core/server'; -import { Duration } from '../../domain/models'; -import { computeBurnRate, computeSLI } from '../../domain/services'; +import { Duration } from '../domain/models'; +import { computeBurnRate, computeSLI } from '../domain/services'; import { DefaultSLIClient } from './sli_client'; import { KibanaSavedObjectsSLORepository } from './slo_repository'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_diagnosis.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_preview_data.ts b/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts similarity index 98% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_preview_data.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts index 33a860ffb932c..ffa686500e341 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/get_preview_data.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts @@ -21,9 +21,9 @@ import moment from 'moment'; import { ElasticsearchClient } from '@kbn/core/server'; import { estypes } from '@elastic/elasticsearch'; import { getElasticsearchQueryOrThrow } from './transform_generators'; -import { typedSearch } from '../../utils/queries'; -import { APMTransactionDurationIndicator } from '../../domain/models'; -import { computeSLI } from '../../domain/services'; +import { typedSearch } from '../utils/queries'; +import { APMTransactionDurationIndicator } from '../domain/models'; +import { computeSLI } from '../domain/services'; import { GetCustomMetricIndicatorAggregation, GetHistogramIndicatorAggregation, diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts index 18fe85cdfb0b1..1c74160547c23 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts @@ -6,7 +6,7 @@ */ import { ALL_VALUE } from '@kbn/slo-schema'; -import { SLO_MODEL_VERSION } from '../../../common/slo/constants'; +import { SLO_MODEL_VERSION } from '../../common/constants'; import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; import { GetSLO } from './get_slo'; import { createSummaryClientMock, createSLORepositoryMock } from './mocks'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_slo.ts index cc5df5f8b5966..5a1a63f7c2862 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo.ts @@ -6,7 +6,7 @@ */ import { ALL_VALUE, GetSLOParams, GetSLOResponse, getSLOResponseSchema } from '@kbn/slo-schema'; -import { SLO, Summary } from '../../domain/models'; +import { SLO, Summary } from '../domain/models'; import { SLORepository } from './slo_repository'; import { SummaryClient } from './summary_client'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo_instances.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_instances.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_slo_instances.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_slo_instances.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo_instances.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_instances.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/get_slo_instances.ts rename to x-pack/plugins/observability_solution/slo/server/services/get_slo_instances.ts index 405f355777c23..b9cc7aaf12492 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/get_slo_instances.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_instances.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { ALL_VALUE, GetSLOInstancesResponse } from '@kbn/slo-schema'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants'; +import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { SLORepository } from './slo_repository'; export class GetSLOInstances { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/historical_summary_client.test.ts b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/historical_summary_client.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/historical_summary_client.ts b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/historical_summary_client.ts rename to x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts index e1f979da5fa83..545c49ad850a3 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/historical_summary_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts @@ -20,14 +20,9 @@ import { import { assertNever } from '@kbn/std'; import * as t from 'io-ts'; import moment from 'moment'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants'; -import { DateRange, HistoricalSummary, SLO, SLOId } from '../../domain/models'; -import { - computeSLI, - computeSummaryStatus, - toDateRange, - toErrorBudget, -} from '../../domain/services'; +import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { DateRange, HistoricalSummary, SLO, SLOId } from '../domain/models'; +import { computeSLI, computeSummaryStatus, toDateRange, toErrorBudget } from '../domain/services'; interface DailyAggBucket { key_as_string: string; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/index.ts b/x-pack/plugins/observability_solution/slo/server/services/index.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/index.ts rename to x-pack/plugins/observability_solution/slo/server/services/index.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/manage_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/manage_slo.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/manage_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/manage_slo.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/manage_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/manage_slo.ts similarity index 98% rename from x-pack/plugins/observability_solution/slo/server/services/slo/manage_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/manage_slo.ts index 9d9fd6eb1705c..84e8e3798598b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/manage_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/manage_slo.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { getSLOSummaryTransformId, getSLOTransformId } from '../../../common/slo/constants'; +import { getSLOSummaryTransformId, getSLOTransformId } from '../../common/constants'; import { SLORepository } from './slo_repository'; import { TransformManager } from './transform_manager'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/mocks/index.ts b/x-pack/plugins/observability_solution/slo/server/services/mocks/index.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/mocks/index.ts rename to x-pack/plugins/observability_solution/slo/server/services/mocks/index.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/reset_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/reset_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts index feae6695fbd33..1410ffc2b6863 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/reset_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts @@ -9,7 +9,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; -import { SLO_MODEL_VERSION } from '../../../common/slo/constants'; +import { SLO_MODEL_VERSION } from '../../common/constants'; import { createSLO } from './fixtures/slo'; import { createSLORepositoryMock, diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/reset_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/reset_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts index 8c4a374761979..9ab931a98caa5 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/reset_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts @@ -15,9 +15,9 @@ import { SLO_MODEL_VERSION, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, SLO_SUMMARY_TEMP_INDEX_NAME, -} from '../../../common/slo/constants'; -import { getSLOSummaryPipelineTemplate } from '../../assets/ingest_templates/slo_summary_pipeline_template'; -import { retryTransientEsErrors } from '../../utils/retry'; +} from '../../common/constants'; +import { getSLOSummaryPipelineTemplate } from '../assets/ingest_templates/slo_summary_pipeline_template'; +import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; import { TransformManager } from './transform_manager'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/resource_installer.test.ts b/x-pack/plugins/observability_solution/slo/server/services/resource_installer.test.ts similarity index 99% rename from x-pack/plugins/observability_solution/slo/server/services/slo/resource_installer.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/resource_installer.test.ts index b84e7e95146e8..55f5db79680ba 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/resource_installer.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/resource_installer.test.ts @@ -17,7 +17,7 @@ import { SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, SLO_SUMMARY_INDEX_TEMPLATE_NAME, SLO_RESOURCES_VERSION, -} from '../../../common/slo/constants'; +} from '../../common/constants'; import { DefaultResourceInstaller } from './resource_installer'; describe('resourceInstaller', () => { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/resource_installer.ts b/x-pack/plugins/observability_solution/slo/server/services/resource_installer.ts similarity index 89% rename from x-pack/plugins/observability_solution/slo/server/services/slo/resource_installer.ts rename to x-pack/plugins/observability_solution/slo/server/services/resource_installer.ts index 0eeaae913b8c4..c7ae180100dce 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/resource_installer.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/resource_installer.ts @@ -13,10 +13,10 @@ import type { Metadata, } from '@elastic/elasticsearch/lib/api/types'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { getSLOMappingsTemplate } from '../../assets/component_templates/slo_mappings_template'; -import { getSLOSettingsTemplate } from '../../assets/component_templates/slo_settings_template'; -import { getSLOSummaryMappingsTemplate } from '../../assets/component_templates/slo_summary_mappings_template'; -import { getSLOSummarySettingsTemplate } from '../../assets/component_templates/slo_summary_settings_template'; +import { getSLOMappingsTemplate } from '../assets/component_templates/slo_mappings_template'; +import { getSLOSettingsTemplate } from '../assets/component_templates/slo_settings_template'; +import { getSLOSummaryMappingsTemplate } from '../assets/component_templates/slo_summary_mappings_template'; +import { getSLOSummarySettingsTemplate } from '../assets/component_templates/slo_summary_settings_template'; import { SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, @@ -31,11 +31,11 @@ import { SLO_SUMMARY_INDEX_TEMPLATE_NAME, SLO_SUMMARY_INDEX_TEMPLATE_PATTERN, SLO_SUMMARY_TEMP_INDEX_NAME, -} from '../../../common/slo/constants'; -import { getSLOIndexTemplate } from '../../assets/index_templates/slo_index_templates'; -import { getSLOSummaryIndexTemplate } from '../../assets/index_templates/slo_summary_index_templates'; -import { getSLOPipelineTemplate } from '../../assets/ingest_templates/slo_pipeline_template'; -import { retryTransientEsErrors } from '../../utils/retry'; +} from '../../common/constants'; +import { getSLOIndexTemplate } from '../assets/index_templates/slo_index_templates'; +import { getSLOSummaryIndexTemplate } from '../assets/index_templates/slo_summary_index_templates'; +import { getSLOPipelineTemplate } from '../assets/ingest_templates/slo_pipeline_template'; +import { retryTransientEsErrors } from '../utils/retry'; export interface ResourceInstaller { ensureCommonResourcesInstalled(): Promise; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/sli_client.test.ts b/x-pack/plugins/observability_solution/slo/server/services/sli_client.test.ts similarity index 99% rename from x-pack/plugins/observability_solution/slo/server/services/slo/sli_client.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/sli_client.test.ts index 1160448854c95..45e2683a00a35 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/sli_client.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/sli_client.test.ts @@ -9,7 +9,7 @@ import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/ser import moment from 'moment'; import { ALL_VALUE } from '@kbn/slo-schema'; -import { Duration, DurationUnit } from '../../domain/models'; +import { Duration, DurationUnit } from '../domain/models'; import { createSLO } from './fixtures/slo'; import { DefaultSLIClient } from './sli_client'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/sli_client.ts b/x-pack/plugins/observability_solution/slo/server/services/sli_client.ts similarity index 94% rename from x-pack/plugins/observability_solution/slo/server/services/slo/sli_client.ts rename to x-pack/plugins/observability_solution/slo/server/services/sli_client.ts index 1eab9181e8b0f..ed645e8da7384 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/sli_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/sli_client.ts @@ -20,11 +20,11 @@ import { timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; import { assertNever } from '@kbn/std'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants'; -import { DateRange, Duration, IndicatorData, SLO } from '../../domain/models'; -import { InternalQueryError } from '../../errors'; -import { getDelayInSecondsFromSLO } from '../../domain/services/get_delay_in_seconds_from_slo'; -import { getLookbackDateRange } from '../../domain/services/get_lookback_date_range'; +import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { DateRange, Duration, IndicatorData, SLO } from '../domain/models'; +import { InternalQueryError } from '../errors'; +import { getDelayInSecondsFromSLO } from '../domain/services/get_delay_in_seconds_from_slo'; +import { getLookbackDateRange } from '../domain/services/get_lookback_date_range'; export interface SLIClient { fetchSLIDataFrom( diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/slo_installer.test.ts b/x-pack/plugins/observability_solution/slo/server/services/slo_installer.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/slo_installer.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/slo_installer.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/slo_installer.ts b/x-pack/plugins/observability_solution/slo/server/services/slo_installer.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/slo_installer.ts rename to x-pack/plugins/observability_solution/slo/server/services/slo_installer.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/slo_repository.test.ts b/x-pack/plugins/observability_solution/slo/server/services/slo_repository.test.ts similarity index 98% rename from x-pack/plugins/observability_solution/slo/server/services/slo/slo_repository.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/slo_repository.test.ts index 7259f00aec05c..424a2cd03cb65 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/slo_repository.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/slo_repository.test.ts @@ -9,10 +9,10 @@ import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/ import { loggingSystemMock, savedObjectsClientMock } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; import { sloSchema } from '@kbn/slo-schema'; -import { SLO_MODEL_VERSION } from '../../../common/slo/constants'; -import { SLO, StoredSLO } from '../../domain/models'; +import { SLO_MODEL_VERSION } from '../../common/constants'; +import { SLO, StoredSLO } from '../domain/models'; import { SLOIdConflict, SLONotFound } from '../../errors'; -import { SO_SLO_TYPE } from '../../saved_objects'; +import { SO_SLO_TYPE } from '../saved_objects'; import { aStoredSLO, createAPMTransactionDurationIndicator, createSLO } from './fixtures/slo'; import { KibanaSavedObjectsSLORepository } from './slo_repository'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/slo_repository.ts b/x-pack/plugins/observability_solution/slo/server/services/slo_repository.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/slo_repository.ts rename to x-pack/plugins/observability_solution/slo/server/services/slo_repository.ts index bfbd7be738450..05d690242f0cf 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/slo_repository.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/slo_repository.ts @@ -9,10 +9,10 @@ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { Logger } from '@kbn/core/server'; import { ALL_VALUE, Paginated, Pagination, sloSchema } from '@kbn/slo-schema'; import { isLeft } from 'fp-ts/lib/Either'; -import { SLO_MODEL_VERSION } from '../../../common/slo/constants'; -import { SLO, StoredSLO } from '../../domain/models'; -import { SLOIdConflict, SLONotFound } from '../../errors'; -import { SO_SLO_TYPE } from '../../saved_objects'; +import { SLO_MODEL_VERSION } from '../../common/constants'; +import { SLO, StoredSLO } from '../domain/models'; +import { SLOIdConflict, SLONotFound } from '../errors'; +import { SO_SLO_TYPE } from '../saved_objects'; export interface SLORepository { save(slo: SLO, options?: { throwOnConflict: boolean }): Promise; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_client.test.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts similarity index 98% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_client.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts index f6850e73575ee..15388b221cc74 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_client.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts @@ -7,8 +7,8 @@ import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import moment from 'moment'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants'; -import { Duration, DurationUnit } from '../../domain/models'; +import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { Duration, DurationUnit } from '../domain/models'; import { createSLO } from './fixtures/slo'; import { sevenDaysRolling, weeklyCalendarAligned } from './fixtures/time_window'; import { DefaultSummaryClient } from './summary_client'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_client.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts similarity index 94% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_client.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_client.ts index d5ec52b226e9d..f362bf771b3c0 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts @@ -15,10 +15,10 @@ import { toMomentUnitOfTime, } from '@kbn/slo-schema'; import moment from 'moment'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants'; -import { DateRange, SLO, Summary } from '../../domain/models'; -import { computeSLI, computeSummaryStatus, toErrorBudget } from '../../domain/services'; -import { toDateRange } from '../../domain/services/date_range'; +import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { DateRange, SLO, Summary } from '../domain/models'; +import { computeSLI, computeSummaryStatus, toErrorBudget } from '../domain/services'; +import { toDateRange } from '../domain/services/date_range'; export interface SummaryClient { computeSummary(slo: SLO, instanceId?: string): Promise; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_search_client.test.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_search_client.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_search_client.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_search_client.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts similarity index 96% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_search_client.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts index 55ccb2ad7df61..e1c26d05069a5 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_search_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts @@ -10,9 +10,9 @@ import { ALL_VALUE, Paginated, Pagination } from '@kbn/slo-schema'; import { assertNever } from '@kbn/std'; import _ from 'lodash'; import { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants'; -import { SLOId, Status, Summary } from '../../domain/models'; -import { toHighPrecision } from '../../utils/number'; +import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { SLOId, Status, Summary } from '../domain/models'; +import { toHighPrecision } from '../utils/number'; import { getElasticsearchQueryOrThrow } from './transform_generators'; interface EsSummaryDocument { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/common.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/common.ts similarity index 96% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/common.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/common.ts index 743ba333c8f98..56d7c1d6876a7 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/common.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/common.ts @@ -6,7 +6,7 @@ */ import { ALL_VALUE } from '@kbn/slo-schema'; -import { SLO } from '../../../../domain/models/slo'; +import { SLO } from '../../../domain/models/slo'; export const getGroupBy = (slo: SLO) => { const groupings = diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/occurrences.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/occurrences.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts index 3cae531cfeb98..0c2b29f6fa7ef 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/occurrences.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts @@ -6,14 +6,14 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO } from '../../../../domain/models'; +import { SLO } from '../../../domain/models'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, SLO_DESTINATION_INDEX_PATTERN, SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_NAME, -} from '../../../../../common/slo/constants'; +} from '../../../../common/constants'; import { getGroupBy } from './common'; export function generateSummaryTransformForOccurrences(slo: SLO): TransformPutTransformRequest { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/timeslices_calendar_aligned.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/timeslices_calendar_aligned.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts index 7fc5d98a94603..4fa19ea448828 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/timeslices_calendar_aligned.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts @@ -6,14 +6,14 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { DurationUnit, SLO } from '../../../../domain/models'; +import { DurationUnit, SLO } from '../../../domain/models'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, SLO_DESTINATION_INDEX_PATTERN, SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_NAME, -} from '../../../../../common/slo/constants'; +} from '../../../../common/constants'; import { getGroupBy } from './common'; export function generateSummaryTransformForTimeslicesAndCalendarAligned( diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/timeslices_rolling.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/timeslices_rolling.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts index 113df2c4ce72f..3b3abb474476b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/generators/timeslices_rolling.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts @@ -6,14 +6,14 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO } from '../../../../domain/models'; +import { SLO } from '../../../domain/models'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, SLO_DESTINATION_INDEX_PATTERN, SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_NAME, -} from '../../../../../common/slo/constants'; +} from '../../../../common/constants'; import { getGroupBy } from './common'; export function generateSummaryTransformForTimeslicesAndRolling( diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/helpers/create_temp_summary.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/helpers/create_temp_summary.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts index 8e1939647bac8..635577166466f 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/helpers/create_temp_summary.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts @@ -6,7 +6,7 @@ */ import { ALL_VALUE } from '@kbn/slo-schema'; -import { SLO } from '../../../../domain/models'; +import { SLO } from '../../../domain/models'; export function createTempSummaryDocument(slo: SLO, spaceId: string) { const apmParams = 'environment' in slo.indicator.params ? slo.indicator.params : null; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/summary_transform_generator.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/summary_transform_generator.ts similarity index 96% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/summary_transform_generator.ts rename to x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/summary_transform_generator.ts index 7710515f6538a..7eb63e59718c5 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summary_transform_generator/summary_transform_generator.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/summary_transform_generator.ts @@ -6,7 +6,7 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO } from '../../../domain/models'; +import { SLO } from '../../domain/models'; import { generateSummaryTransformForOccurrences } from './generators/occurrences'; import { generateSummaryTransformForTimeslicesAndRolling } from './generators/timeslices_rolling'; import { generateSummaryTransformForTimeslicesAndCalendarAligned } from './generators/timeslices_calendar_aligned'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/summay_transform_manager.ts b/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/summay_transform_manager.ts rename to x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts index 57349105e020a..c9590e5cc90ca 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/summay_transform_manager.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts @@ -8,9 +8,9 @@ import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO } from '../../domain/models'; -import { SecurityException } from '../../errors'; -import { retryTransientEsErrors } from '../../utils/retry'; +import { SLO } from '../domain/models'; +import { SecurityException } from '../errors'; +import { retryTransientEsErrors } from '../utils/retry'; import { SummaryTransformGenerator } from './summary_transform_generator/summary_transform_generator'; import { TransformManager } from './transform_manager'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/tasks/orphan_summary_cleanup_task.test.ts b/x-pack/plugins/observability_solution/slo/server/services/tasks/orphan_summary_cleanup_task.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/tasks/orphan_summary_cleanup_task.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/tasks/orphan_summary_cleanup_task.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/tasks/orphan_summary_cleanup_task.ts b/x-pack/plugins/observability_solution/slo/server/services/tasks/orphan_summary_cleanup_task.ts similarity index 97% rename from x-pack/plugins/observability_solution/slo/server/services/slo/tasks/orphan_summary_cleanup_task.ts rename to x-pack/plugins/observability_solution/slo/server/services/tasks/orphan_summary_cleanup_task.ts index c863dadfe859c..87e93de96667d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/tasks/orphan_summary_cleanup_task.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/tasks/orphan_summary_cleanup_task.ts @@ -13,10 +13,10 @@ import { } from '@kbn/task-manager-plugin/server'; import { AggregationsCompositeAggregateKey } from '@elastic/elasticsearch/lib/api/types'; import { ALL_SPACES_ID } from '@kbn/spaces-plugin/common/constants'; -import { StoredSLO } from '../../../domain/models'; -import { SO_SLO_TYPE } from '../../../saved_objects'; -import { ObservabilityConfig } from '../../..'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../common/slo/constants'; +import { StoredSLO } from '../../domain/models'; +import { SO_SLO_TYPE } from '../../saved_objects'; +import { ObservabilityConfig } from '../..'; +import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; export const TASK_TYPE = 'SLO:ORPHAN_SUMMARIES-CLEANUP-TASK'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/histogram.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/histogram.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/kql_custom.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/kql_custom.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/metric_custom.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/metric_custom.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/timeslice_metric.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/__snapshots__/timeslice_metric.test.ts.snap rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_duration.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_duration.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_duration.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_duration.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_duration.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_duration.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_duration.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_duration.ts index 9559936dff321..2b723e43763b7 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_duration.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_duration.ts @@ -18,10 +18,10 @@ import { getSLOTransformId, SLO_DESTINATION_INDEX_NAME, SLO_INGEST_PIPELINE_NAME, -} from '../../../../common/slo/constants'; -import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; -import { APMTransactionDurationIndicator, SLO } from '../../../domain/models'; -import { InvalidTransformError } from '../../../errors'; +} from '../../../common/constants'; +import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; +import { APMTransactionDurationIndicator, SLO } from '../../domain/models'; +import { InvalidTransformError } from '../../errors'; import { parseIndex } from './common'; export class ApmTransactionDurationTransformGenerator extends TransformGenerator { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_error_rate.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_error_rate.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_error_rate.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_error_rate.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_error_rate.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_error_rate.ts similarity index 94% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_error_rate.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_error_rate.ts index 8fcdd45b26570..c80a962a58146 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/apm_transaction_error_rate.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/apm_transaction_error_rate.ts @@ -17,10 +17,10 @@ import { getSLOTransformId, SLO_DESTINATION_INDEX_NAME, SLO_INGEST_PIPELINE_NAME, -} from '../../../../common/slo/constants'; -import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; -import { APMTransactionErrorRateIndicator, SLO } from '../../../domain/models'; -import { InvalidTransformError } from '../../../errors'; +} from '../../../common/constants'; +import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; +import { APMTransactionErrorRateIndicator, SLO } from '../../domain/models'; +import { InvalidTransformError } from '../../errors'; import { parseIndex } from './common'; export class ApmTransactionErrorRateTransformGenerator extends TransformGenerator { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/common.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/common.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/common.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/common.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/common.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/common.ts similarity index 94% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/common.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/common.ts index 8af0952a5e5b7..e173aa24ce818 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/common.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/common.ts @@ -7,7 +7,7 @@ import { buildEsQuery, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { QuerySchema, kqlQuerySchema } from '@kbn/slo-schema'; -import { InvalidTransformError } from '../../../errors'; +import { InvalidTransformError } from '../../errors'; export function getElasticsearchQueryOrThrow(kuery: QuerySchema = '') { try { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/histogram.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/histogram.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/histogram.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/histogram.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/histogram.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/histogram.ts similarity index 92% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/histogram.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/histogram.ts index d493ea3c8b544..6c151bd9626ff 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/histogram.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/histogram.ts @@ -12,15 +12,15 @@ import { timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; -import { InvalidTransformError } from '../../../errors'; -import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { InvalidTransformError } from '../../errors'; +import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.'; import { SLO_DESTINATION_INDEX_NAME, SLO_INGEST_PIPELINE_NAME, getSLOTransformId, -} from '../../../../common/slo/constants'; -import { SLO } from '../../../domain/models'; +} from '../../../common/constants'; +import { SLO } from '../../domain/models'; import { GetHistogramIndicatorAggregation } from '../aggregations'; export class HistogramTransformGenerator extends TransformGenerator { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/index.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/index.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/index.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/index.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/kql_custom.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/kql_custom.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/kql_custom.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/kql_custom.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/kql_custom.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/kql_custom.ts similarity index 91% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/kql_custom.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/kql_custom.ts index 3fecd8b1cdd6d..5f5c0a3abcbec 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/kql_custom.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/kql_custom.ts @@ -8,15 +8,15 @@ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; import { kqlCustomIndicatorSchema, timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; -import { InvalidTransformError } from '../../../errors'; -import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { InvalidTransformError } from '../../errors'; +import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.'; import { SLO_DESTINATION_INDEX_NAME, SLO_INGEST_PIPELINE_NAME, getSLOTransformId, -} from '../../../../common/slo/constants'; -import { KQLCustomIndicator, SLO } from '../../../domain/models'; +} from '../../../common/constants'; +import { KQLCustomIndicator, SLO } from '../../domain/models'; export class KQLCustomTransformGenerator extends TransformGenerator { public getTransformParams(slo: SLO): TransformPutTransformRequest { diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/metric_custom.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/metric_custom.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/metric_custom.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/metric_custom.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/metric_custom.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/metric_custom.ts similarity index 92% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/metric_custom.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/metric_custom.ts index 6e2bd80350cb9..660673944fe60 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/metric_custom.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/metric_custom.ts @@ -8,15 +8,15 @@ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; import { metricCustomIndicatorSchema, timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; -import { InvalidTransformError } from '../../../errors'; -import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { InvalidTransformError } from '../../errors'; +import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.'; import { SLO_DESTINATION_INDEX_NAME, SLO_INGEST_PIPELINE_NAME, getSLOTransformId, -} from '../../../../common/slo/constants'; -import { MetricCustomIndicator, SLO } from '../../../domain/models'; +} from '../../../common/constants'; +import { MetricCustomIndicator, SLO } from '../../domain/models'; import { GetCustomMetricIndicatorAggregation } from '../aggregations'; export const INVALID_EQUATION_REGEX = /[^A-Z|+|\-|\s|\d+|\.|\(|\)|\/|\*|>|<|=|\?|\:|&|\!|\|]+/g; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/timeslice_metric.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/timeslice_metric.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/timeslice_metric.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/timeslice_metric.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/timeslice_metric.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/timeslice_metric.ts similarity index 93% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/timeslice_metric.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/timeslice_metric.ts index 8e59a03d04d9f..649ffe609559d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/timeslice_metric.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/timeslice_metric.ts @@ -13,15 +13,15 @@ import { timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; -import { InvalidTransformError } from '../../../errors'; -import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { InvalidTransformError } from '../../errors'; +import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.'; import { SLO_DESTINATION_INDEX_NAME, SLO_INGEST_PIPELINE_NAME, getSLOTransformId, -} from '../../../../common/slo/constants'; -import { SLO } from '../../../domain/models'; +} from '../../../common/constants'; +import { SLO } from '../../domain/models'; import { GetTimesliceMetricIndicatorAggregation } from '../aggregations'; const INVALID_EQUATION_REGEX = /[^A-Z|+|\-|\s|\d+|\.|\(|\)|\/|\*|>|<|=|\?|\:|&|\!|\|]+/g; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/transform_generator.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/transform_generator.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/transform_generator.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/transform_generator.ts index 7085f69b76422..3b96431231d42 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/transform_generator.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/transform_generator.ts @@ -10,8 +10,8 @@ import { TransformPutTransformRequest, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ALL_VALUE, timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; -import { TransformSettings } from '../../../assets/transform_templates/slo_transform_template'; -import { SLO } from '../../../domain/models'; +import { TransformSettings } from '../../assets/transform_templates/slo_transform_template'; +import { SLO } from '../../domain/models'; export abstract class TransformGenerator { public abstract getTransformParams(slo: SLO): TransformPutTransformRequest; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/types.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/types.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_generators/types.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_generators/types.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_manager.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts similarity index 99% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_manager.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts index b05feb8d9e8f4..519a7140e785b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_manager.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts @@ -20,7 +20,7 @@ import { ApmTransactionErrorRateTransformGenerator, TransformGenerator, } from './transform_generators'; -import { SLO, IndicatorTypes } from '../../domain/models'; +import { SLO, IndicatorTypes } from '../domain/models'; import { createAPMTransactionDurationIndicator, createAPMTransactionErrorRateIndicator, diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_manager.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/transform_manager.ts rename to x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts index 954c7f7d95912..f59338078bc2e 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/transform_manager.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts @@ -8,9 +8,9 @@ import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { SLO, IndicatorTypes } from '../../domain/models'; -import { SecurityException } from '../../errors'; -import { retryTransientEsErrors } from '../../utils/retry'; +import { SLO, IndicatorTypes } from '../domain/models'; +import { SecurityException } from '../errors'; +import { retryTransientEsErrors } from '../utils/retry'; import { TransformGenerator } from './transform_generators'; type TransformId = string; diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/update_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/slo/server/services/slo/update_slo.test.ts rename to x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts diff --git a/x-pack/plugins/observability_solution/slo/server/services/slo/update_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts similarity index 95% rename from x-pack/plugins/observability_solution/slo/server/services/slo/update_slo.ts rename to x-pack/plugins/observability_solution/slo/server/services/update_slo.ts index 1a73d54decbee..dbe63c61423fd 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/slo/update_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts @@ -15,11 +15,11 @@ import { SLO_DESTINATION_INDEX_PATTERN, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, SLO_SUMMARY_TEMP_INDEX_NAME, -} from '../../../common/slo/constants'; -import { getSLOSummaryPipelineTemplate } from '../../assets/ingest_templates/slo_summary_pipeline_template'; -import { SLO } from '../../domain/models'; -import { validateSLO } from '../../domain/services'; -import { retryTransientEsErrors } from '../../utils/retry'; +} from '../../common/constants'; +import { getSLOSummaryPipelineTemplate } from '../assets/ingest_templates/slo_summary_pipeline_template'; +import { SLO } from '../domain/models'; +import { validateSLO } from '../domain/services'; +import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; import { TransformManager } from './transform_manager'; diff --git a/x-pack/plugins/observability_solution/slo/server/types.ts b/x-pack/plugins/observability_solution/slo/server/types.ts index d2ba45cddc097..c0a87f08be36a 100644 --- a/x-pack/plugins/observability_solution/slo/server/types.ts +++ b/x-pack/plugins/observability_solution/slo/server/types.ts @@ -1,3 +1,23 @@ +/* + * 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 { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server'; +import type { AlertingApiRequestHandlerContext } from '@kbn/alerting-plugin/server'; +import type { CustomRequestHandlerContext, CoreRequestHandlerContext } from '@kbn/core/server'; + +/** + * @internal + */ +export type SloRequestHandlerContext = CustomRequestHandlerContext<{ + licensing: LicensingApiRequestHandlerContext; + alerting: AlertingApiRequestHandlerContext; + core: Promise; +}>; + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SlosPluginSetup {} // eslint-disable-next-line @typescript-eslint/no-empty-interface diff --git a/x-pack/plugins/observability_solution/slo/server/utils/number.ts b/x-pack/plugins/observability_solution/slo/server/utils/number.ts new file mode 100644 index 0000000000000..bfec2d6200f19 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/utils/number.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +const SIX_DIGITS = 1000000; + +export function toHighPrecision(value: number): number { + return Math.round(value * SIX_DIGITS) / SIX_DIGITS; +} diff --git a/x-pack/plugins/observability_solution/slo/server/utils/queries.test.ts b/x-pack/plugins/observability_solution/slo/server/utils/queries.test.ts new file mode 100644 index 0000000000000..0e34f84050386 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/utils/queries.test.ts @@ -0,0 +1,42 @@ +/* + * 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 { wildcardQuery } from './queries'; // Replace 'your-module' with the actual module path + +describe('wildcardQuery', () => { + it('generates wildcard query with leading wildcard by default', () => { + const result = wildcardQuery('fieldName', 'value'); + expect(result).toEqual([ + { + wildcard: { + fieldName: { + value: '*value*', + case_insensitive: true, + }, + }, + }, + ]); + }); + + it('generates wildcard query without leading wildcard if specified in options', () => { + const result = wildcardQuery('fieldName', 'value', { leadingWildcard: false }); + expect(result).toEqual([ + { + wildcard: { + fieldName: { + value: 'value*', + case_insensitive: true, + }, + }, + }, + ]); + }); + + it('returns an empty array if value is undefined', () => { + const result = wildcardQuery('fieldName', undefined); + expect(result).toEqual([]); + }); +}); diff --git a/x-pack/plugins/observability_solution/slo/server/utils/queries.ts b/x-pack/plugins/observability_solution/slo/server/utils/queries.ts new file mode 100644 index 0000000000000..bdacad577838c --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/utils/queries.ts @@ -0,0 +1,103 @@ +/* + * 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 { reject } from 'lodash'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { ESSearchResponse } from '@kbn/es-types'; +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; + +export function isUndefinedOrNull(value: any): value is undefined | null { + return value === undefined || value === null; +} + +interface TermQueryOpts { + queryEmptyString: boolean; +} + +export function termQuery( + field: T, + value: string | boolean | number | undefined | null, + opts: TermQueryOpts = { queryEmptyString: true } +): QueryDslQueryContainer[] { + if (isUndefinedOrNull(value) || (!opts.queryEmptyString && value === '')) { + return []; + } + + return [{ term: { [field]: value } }]; +} + +export function wildcardQuery( + field: T, + value: string | undefined, + opts = { leadingWildcard: true } +): QueryDslQueryContainer[] { + if (isUndefinedOrNull(value)) { + return []; + } + + return [ + { + wildcard: { + [field]: { + value: opts.leadingWildcard ? `*${value}*` : `${value}*`, + case_insensitive: true, + }, + }, + }, + ]; +} + +export function termsQuery( + field: string, + ...values: Array +): QueryDslQueryContainer[] { + const filtered = reject(values, isUndefinedOrNull); + + if (!filtered.length) { + return []; + } + + return [{ terms: { [field]: filtered } }]; +} + +export function rangeQuery( + start?: number, + end?: number, + field = '@timestamp' +): estypes.QueryDslQueryContainer[] { + return [ + { + range: { + [field]: { + gte: start, + lte: end, + format: 'epoch_millis', + }, + }, + }, + ]; +} + +export function kqlQuery(kql?: string): estypes.QueryDslQueryContainer[] { + if (!kql) { + return []; + } + + const ast = fromKueryExpression(kql); + return [toElasticsearchQuery(ast)]; +} + +export async function typedSearch< + DocumentSource extends unknown, + TParams extends estypes.SearchRequest +>( + esClient: ElasticsearchClient, + params: TParams +): Promise> { + return (await esClient.search(params)) as unknown as ESSearchResponse; +} diff --git a/x-pack/plugins/observability_solution/slo/server/utils/retry.test.ts b/x-pack/plugins/observability_solution/slo/server/utils/retry.test.ts new file mode 100644 index 0000000000000..25870fd24aa73 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/utils/retry.test.ts @@ -0,0 +1,87 @@ +/* + * 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. + */ + +jest.mock('timers/promises'); +import { setTimeout } from 'timers/promises'; +import { loggerMock } from '@kbn/logging-mocks'; +import { errors as EsErrors } from '@elastic/elasticsearch'; + +import { retryTransientEsErrors } from './retry'; + +const setTimeoutMock = setTimeout as jest.Mock< + ReturnType, + Parameters +>; + +describe('retryTransientErrors', () => { + beforeEach(() => { + setTimeoutMock.mockClear(); + }); + + it("doesn't retry if operation is successful", async () => { + const esCallMock = jest.fn().mockResolvedValue('success'); + expect(await retryTransientEsErrors(esCallMock)).toEqual('success'); + expect(esCallMock).toHaveBeenCalledTimes(1); + }); + + it('logs an warning message on retry', async () => { + const logger = loggerMock.create(); + const esCallMock = jest + .fn() + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockResolvedValue('success'); + + await retryTransientEsErrors(esCallMock, { logger }); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn.mock.calls[0][0]).toMatch( + `Retrying Elasticsearch operation after [2s] due to error: ConnectionError: foo ConnectionError: foo` + ); + }); + + it('retries with an exponential backoff', async () => { + let attempt = 0; + const esCallMock = jest.fn(async () => { + attempt++; + if (attempt < 5) { + throw new EsErrors.ConnectionError('foo'); + } else { + return 'success'; + } + }); + + expect(await retryTransientEsErrors(esCallMock)).toEqual('success'); + expect(setTimeoutMock.mock.calls).toEqual([[2000], [4000], [8000], [16000]]); + expect(esCallMock).toHaveBeenCalledTimes(5); + }); + + it('retries each supported error type', async () => { + const errors = [ + new EsErrors.NoLivingConnectionsError('no living connection', { + warnings: [], + meta: {} as any, + }), + new EsErrors.ConnectionError('no connection'), + new EsErrors.TimeoutError('timeout'), + new EsErrors.ResponseError({ statusCode: 503, meta: {} as any, warnings: [] }), + new EsErrors.ResponseError({ statusCode: 408, meta: {} as any, warnings: [] }), + new EsErrors.ResponseError({ statusCode: 410, meta: {} as any, warnings: [] }), + ]; + + for (const error of errors) { + const esCallMock = jest.fn().mockRejectedValueOnce(error).mockResolvedValue('success'); + expect(await retryTransientEsErrors(esCallMock)).toEqual('success'); + expect(esCallMock).toHaveBeenCalledTimes(2); + } + }); + + it('does not retry unsupported errors', async () => { + const error = new Error('foo!'); + const esCallMock = jest.fn().mockRejectedValueOnce(error).mockResolvedValue('success'); + await expect(retryTransientEsErrors(esCallMock)).rejects.toThrow(error); + expect(esCallMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/observability_solution/slo/server/utils/retry.ts b/x-pack/plugins/observability_solution/slo/server/utils/retry.ts new file mode 100644 index 0000000000000..421289d1c0479 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/utils/retry.ts @@ -0,0 +1,53 @@ +/* + * 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 { setTimeout } from 'timers/promises'; +import { errors as EsErrors } from '@elastic/elasticsearch'; +import type { Logger } from '@kbn/logging'; + +const MAX_ATTEMPTS = 5; + +const retryResponseStatuses = [ + 503, // ServiceUnavailable + 408, // RequestTimeout + 410, // Gone +]; + +const isRetryableError = (e: any) => + e instanceof EsErrors.NoLivingConnectionsError || + e instanceof EsErrors.ConnectionError || + e instanceof EsErrors.TimeoutError || + (e instanceof EsErrors.ResponseError && retryResponseStatuses.includes(e?.statusCode!)); + +/** + * Retries any transient network or configuration issues encountered from Elasticsearch with an exponential backoff. + * Should only be used to wrap operations that are idempotent and can be safely executed more than once. + */ +export const retryTransientEsErrors = async ( + esCall: () => Promise, + { logger, attempt = 0 }: { logger?: Logger; attempt?: number } = {} +): Promise => { + try { + return await esCall(); + } catch (e) { + if (attempt < MAX_ATTEMPTS && isRetryableError(e)) { + const retryCount = attempt + 1; + const retryDelaySec = Math.min(Math.pow(2, retryCount), 64); // 2s, 4s, 8s, 16s, 32s, 64s, 64s, 64s ... + + logger?.warn( + `Retrying Elasticsearch operation after [${retryDelaySec}s] due to error: ${e.toString()} ${ + e.stack + }` + ); + + await setTimeout(retryDelaySec * 1000); + return retryTransientEsErrors(esCall, { logger, attempt: retryCount }); + } + + throw e; + } +};