Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SLO] Create SLO / Edit SLO Form - Custom KQL #147843

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
499b830
Create SLO Edit Form route and components
CoenWarmer Dec 20, 2022
be4872b
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 20, 2022
5fa5bd9
Use existing useFetchSloDetails hook
CoenWarmer Dec 20, 2022
7b72f71
Add translations
CoenWarmer Dec 21, 2022
437af3e
Implement RHF
CoenWarmer Dec 21, 2022
8d4b94f
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 22, 2022
1a0ef11
Remove top padding in SLO Welcome prompt
CoenWarmer Dec 22, 2022
f5578ac
Add Duration type
CoenWarmer Dec 22, 2022
ae46989
Update types
CoenWarmer Dec 22, 2022
ce37b02
Add Timeslices options
CoenWarmer Dec 22, 2022
2310d03
First pass of editing
CoenWarmer Dec 22, 2022
a478bbc
Add button to create new SLO to SLO List
CoenWarmer Dec 27, 2022
2f1a15a
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 28, 2022
da8fd08
Update types
CoenWarmer Dec 28, 2022
66d0d11
Remove extraneous sort function
CoenWarmer Dec 28, 2022
a6adb7b
Further camel casing
CoenWarmer Dec 28, 2022
025c650
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 28, 2022
7210a86
Update import statements
CoenWarmer Dec 28, 2022
6d24136
Fix translation strings
CoenWarmer Dec 28, 2022
2590878
Update casing
CoenWarmer Dec 28, 2022
c24a58e
Fix editing
CoenWarmer Dec 28, 2022
eb3693c
Add Storybook stories
CoenWarmer Dec 29, 2022
9b6718f
Updated translations
CoenWarmer Dec 29, 2022
1e5b629
Update docs
CoenWarmer Dec 29, 2022
3a09efc
Update types
CoenWarmer Dec 29, 2022
dcbebeb
Break out preprocessing of form values into separate function
CoenWarmer Dec 29, 2022
995d7e2
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 29, 2022
e764ee8
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 30, 2022
6fdb112
Update types
CoenWarmer Dec 30, 2022
3397db9
Have duration be a union of Duration or string, to fix TS compilation
CoenWarmer Dec 30, 2022
62c0cbd
Revert to main
CoenWarmer Dec 30, 2022
8705f40
Add BudgetingMethod type, update types
CoenWarmer Dec 30, 2022
4439403
Move SLI_OPTIONS const to constants to prevent importing issue
CoenWarmer Dec 30, 2022
45acd4a
Validate fields asynchronously
CoenWarmer Dec 30, 2022
aea2d58
Add unit tests
CoenWarmer Dec 30, 2022
71805fe
Address PR comments
CoenWarmer Dec 30, 2022
49b7d95
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 30, 2022
b483c9f
Last comments
CoenWarmer Dec 30, 2022
e8bc37d
Change route config
CoenWarmer Dec 31, 2022
2ef861b
Merge branch 'main' of github.com:elastic/kibana into feat/147753-slo…
CoenWarmer Dec 31, 2022
639ca91
[CI] Auto-commit changed files from 'node scripts/ts_project_linter -…
kibanamachine Dec 31, 2022
51aa1da
Merge branch 'main' into feat/147753-slo-edit-form-custom-kql-new
kibanamachine Jan 2, 2023
e0e6993
Merge branch 'main' into feat/147753-slo-edit-form-custom-kql-new
kibanamachine Jan 3, 2023
6529070
Merge branch 'main' into feat/147753-slo-edit-form-custom-kql-new
kibanamachine Jan 3, 2023
07037cf
Update min max values for percentage fields
kdelemme Jan 3, 2023
e3f3500
Fix tests
kdelemme Jan 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions packages/kbn-slo-schema/src/rest_specs/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ const getSLOParamsSchema = t.type({
});

const sortDirectionSchema = t.union([t.literal('asc'), t.literal('desc')]);
const sortBySchema = t.union([t.literal('name'), t.literal('indicator_type')]);
const sortBySchema = t.union([t.literal('name'), t.literal('indicatorType')]);

const findSLOParamsSchema = t.partial({
query: t.partial({
name: t.string,
indicator_types: indicatorTypesArraySchema,
indicatorTypes: indicatorTypesArraySchema,
page: t.string,
per_page: t.string,
sort_by: sortBySchema,
sort_direction: sortDirectionSchema,
perPage: t.string,
sortBy: sortBySchema,
sortDirection: sortDirectionSchema,
}),
});

Expand Down Expand Up @@ -123,6 +123,8 @@ type UpdateSLOResponse = t.OutputOf<typeof updateSLOResponseSchema>;
type FindSLOParams = t.TypeOf<typeof findSLOParamsSchema.props.query>;
type FindSLOResponse = t.OutputOf<typeof findSLOResponseSchema>;

type BudgetingMethod = t.TypeOf<typeof budgetingMethodSchema>;

export {
createSLOParamsSchema,
deleteSLOParamsSchema,
Expand All @@ -136,6 +138,7 @@ export {
updateSLOResponseSchema,
};
export type {
BudgetingMethod,
CreateSLOParams,
CreateSLOResponse,
FindSLOParams,
Expand Down
6 changes: 3 additions & 3 deletions packages/kbn-slo-schema/src/schema/indicators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import * as t from 'io-ts';
import { allOrAnyString, dateRangeSchema } from './common';

const apmTransactionDurationIndicatorTypeSchema = t.literal('sli.apm.transaction_duration');
const apmTransactionDurationIndicatorTypeSchema = t.literal('sli.apm.transactionDuration');
const apmTransactionDurationIndicatorSchema = t.type({
type: apmTransactionDurationIndicatorTypeSchema,
params: t.intersection([
Expand All @@ -26,7 +26,7 @@ const apmTransactionDurationIndicatorSchema = t.type({
]),
});

const apmTransactionErrorRateIndicatorTypeSchema = t.literal('sli.apm.transaction_error_rate');
const apmTransactionErrorRateIndicatorTypeSchema = t.literal('sli.apm.transactionErrorRate');
const apmTransactionErrorRateIndicatorSchema = t.type({
type: apmTransactionErrorRateIndicatorTypeSchema,
params: t.intersection([
Expand Down Expand Up @@ -69,7 +69,7 @@ const indicatorTypesSchema = t.union([
]);

// Validate that a string is a comma separated list of indicator types,
// e.g. sli.kql.custom,sli.apm.transaction_duration
// e.g. sli.kql.custom,sli.apm.transactionDuration
// Transform to an array of indicator type
const indicatorTypesArraySchema = new t.Type<string[], string, unknown>(
'indicatorTypesArray',
Expand Down
4 changes: 2 additions & 2 deletions packages/kbn-slo-schema/src/schema/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { durationType } from './duration';
import { indicatorSchema } from './indicators';
import { timeWindowSchema } from './time_window';

const occurrencesBudgetingMethodSchema = t.literal<string>('occurrences');
const timeslicesBudgetingMethodSchema = t.literal<string>('timeslices');
const occurrencesBudgetingMethodSchema = t.literal('occurrences');
const timeslicesBudgetingMethodSchema = t.literal('timeslices');

const budgetingMethodSchema = t.union([
occurrencesBudgetingMethodSchema,
Expand Down
128 changes: 67 additions & 61 deletions x-pack/plugins/observability/dev_docs/slo.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# SLO
# SLO
CoenWarmer marked this conversation as resolved.
Show resolved Hide resolved

Add the feature flag: `xpack.observability.unsafe.slo.enabled: true` in your Kibana config to enable the various SLO APIs.

## Supported SLI

We currently support the following SLI:

- APM Transaction Error Rate (Availability)
- APM Transaction Duration (Latency)
- Custom KQL
Expand All @@ -19,30 +20,31 @@ The **custom KQL** SLI requires an index pattern, an optional filter query, a nu

We support **calendar aligned** and **rolling** time windows. Any duration greater than 1 day can be used: days, weeks, months, quarters, years.

**Rolling time window:** Requires a duration, e.g. `1w` for one week, and `is_rolling: true`. SLOs defined with such time window, will only considere the SLI data from the last duration period as a moving window.
**Rolling time window:** Requires a duration, e.g. `1w` for one week, and `isRolling: true`. SLOs defined with such time window, will only considere the SLI data from the last duration period as a moving window.

**Calendar aligned time window:** Requires a duration, e.g. `1M` for one month, and a `calendar.start_time` date in ISO 8601 in UTC, which marks the beginning of the first period. From start time and the duration, the system will compute the different time windows. For example, starting the calendar on the **01/01/2022** with a monthly duration, if today is the **24/10/2022**, the window associated is: `[2022-10-01T00:00:00Z, 2022-11-01T00:00:00Z]`
**Calendar aligned time window:** Requires a duration, e.g. `1M` for one month, and a `calendar.startTime` date in ISO 8601 in UTC, which marks the beginning of the first period. From start time and the duration, the system will compute the different time windows. For example, starting the calendar on the **01/01/2022** with a monthly duration, if today is the **24/10/2022**, the window associated is: `[2022-10-01T00:00:00Z, 2022-11-01T00:00:00Z]`

### Budgeting method

An SLO can be configured with an **occurrences** or **timeslices** budgeting method.
An SLO can be configured with an **occurrences** or **timeslices** budgeting method.

An **occurrences** budgeting method uses the number of **good** and **total** events during the time window.

A **timeslices** budgeting method uses the number of **good slices** and **total slices** during the time window. A slice is an arbitrary time window (smaller than the overall SLO time window) that is either considered good or bad, calculated from the timeslice threshold and the ratio of good over total events that happened during the slice window.

For example, defining a **timeslices** budgeting method with a `95%` slice threshold and `5m` slice window means that a 1 week SLO is split in 2,016 slices (`7*24*60 / 5`); for a 99% SLO target there will be approximately 20 minutes of available error budget. Each bucket is either good or bad depending on the ratio of good over total events during that bucket, compared to the slice threshold of 95%.

### Objective
### Objective

The target objective is the value the SLO needs to meet during the time window.
If a **timeslices** budgeting method is used, we also need to define the **timeslice_target** which can be different than the overall SLO target.
If a **timeslices** budgeting method is used, we also need to define the **timesliceTarget** which can be different than the overall SLO target.

### Optional settings

The default settings should be sufficient for most users, but if needed, the following properties can be overwritten:
- timestamp_field: The date time field to use from the source index
- sync_delay: The ingest delay in the source data

- timestampField: The date time field to use from the source index
- syncDelay: The ingest delay in the source data
- frequency: How often do we query the source data

## Example
Expand All @@ -62,25 +64,26 @@ curl --request POST \
"name": "My SLO Name",
"description": "My SLO Description",
"indicator": {
"type": "sli.apm.transaction_error_rate",
"type": "sli.apm.transactionErrorRate",
"params": {
"environment": "production",
"service": "o11y-app",
"transaction_type": "request",
"transaction_name": "GET /api",
"good_status_codes": ["2xx", "3xx", "4xx"]
"transactionType": "request",
"transactionName": "GET /api",
"goodStatusCodes": ["2xx", "3xx", "4xx"]
}
},
"time_window": {
"timeWindow": {
"duration": "30d",
"is_rolling": true
"isRolling": true
},
"budgeting_method": "occurrences",
"budgetingMethod": "occurrences",
"objective": {
"target": 0.99
}
}'
```

</details>

<details>
Expand All @@ -96,27 +99,28 @@ curl --request POST \
"name": "My SLO Name",
"description": "My SLO Description",
"indicator": {
"type": "sli.apm.transaction_error_rate",
"type": "sli.apm.transactionErrorRate",
"params": {
"environment": "production",
"service": "o11y-app",
"transaction_type": "request",
"transaction_name": "GET /api",
"good_status_codes": ["2xx", "3xx", "4xx"]
"transactionType": "request",
"transactionName": "GET /api",
"goodStatusCodes": ["2xx", "3xx", "4xx"]
}
},
"time_window": {
"timeWindow": {
"duration": "1q",
"calendar": {
"start_time": "2022-06-01T00:00:00.000Z"
"startTime": "2022-06-01T00:00:00.000Z"
}
},
"budgeting_method": "occurrences",
"budgetingMethod": "occurrences",
"objective": {
"target": 0.95
}
}'
```

</details>

<details>
Expand All @@ -132,27 +136,28 @@ curl --request POST \
"name": "My SLO Name",
"description": "My SLO Description",
"indicator": {
"type": "sli.apm.transaction_error_rate",
"type": "sli.apm.transactionErrorRate",
"params": {
"environment": "production",
"service": "o11y-app",
"transaction_type": "request",
"transaction_name": "GET /api",
"good_status_codes": ["2xx", "3xx", "4xx"]
"transactionType": "request",
"transactionName": "GET /api",
"goodStatusCodes": ["2xx", "3xx", "4xx"]
}
},
"time_window": {
"timeWindow": {
"duration": "1w",
"is_rolling": true
"isRolling": true
},
"budgeting_method": "timeslices",
"budgetingMethod": "timeslices",
"objective": {
"target": 0.90,
"timeslice_target": 0.86,
"timeslice_window": "5m"
"timesliceTarget": 0.86,
"timesliceWindow": "5m"
}
}'
```

</details>

### Latency
Expand All @@ -170,25 +175,26 @@ curl --request POST \
"name": "My SLO Name",
"description": "My SLO Description",
"indicator": {
"type": "sli.apm.transaction_duration",
"type": "sli.apm.transactionDuration",
"params": {
"environment": "production",
"service": "o11y-app",
"transaction_type": "request",
"transaction_name": "GET /api",
"transactionType": "request",
"transactionName": "GET /api",
"threshold.us": 500000
}
},
"time_window": {
"timeWindow": {
"duration": "7d",
"is_rolling": true
"isRolling": true
},
"budgeting_method": "occurrences",
"budgetingMethod": "occurrences",
"objective": {
"target": 0.99
}
}'
```

</details>

<details>
Expand All @@ -204,29 +210,29 @@ curl --request POST \
"name": "My SLO Name",
"description": "My SLO Description",
"indicator": {
"type": "sli.apm.transaction_duration",
"type": "sli.apm.transactionDuration",
"params": {
"environment": "production",
"service": "o11y-app",
"transaction_type": "request",
"transaction_name": "GET /api",
"transactionType": "request",
"transactionName": "GET /api",
"threshold.us": 500000
}
},
"time_window": {
"timeWindow": {
"duration": "7d",
"is_rolling": true
"isRolling": true
},
"budgeting_method": "timeslices",
"budgetingMethod": "timeslices",
"objective": {
"target": 0.95,
"timeslice_target": 0.90,
"timeslice_window": "1m"
"timesliceTarget": 0.90,
"timesliceWindow": "1m"
}
}'
```
</details>

</details>

<details>
<summary>99.9% of GET /api under 500ms weekly aligned (5m timeslices)</summary>
Expand All @@ -241,35 +247,34 @@ curl --request POST \
"name": "My SLO Name",
"description": "My SLO Description",
"indicator": {
"type": "sli.apm.transaction_duration",
"type": "sli.apm.transactionDuration",
"params": {
"environment": "production",
"service": "o11y-app",
"transaction_type": "request",
"transaction_name": "GET /api",
"transactionType": "request",
"transactionName": "GET /api",
"threshold.us": 500000
}
},
"time_window": {
"timeWindow": {
"duration": "7d",
"calendar": {
"start_time": "2022-01-01T00:00:00.000Z"
"calendar": {
"startTime": "2022-01-01T00:00:00.000Z"
}
},
"budgeting_method": "timeslices",
"budgetingMethod": "timeslices",
"objective": {
"target": 0.999,
"timeslice_target": 0.95,
"timeslice_window": "5m"
"timesliceTarget": 0.95,
"timesliceWindow": "5m"
}
}'
```
</details>

</details>

### Custom


<details>
<summary>98.5% of 'logs lantency < 300ms' for 'groupId: group-0' over the last 7 days</summary>

Expand All @@ -291,14 +296,15 @@ curl --request POST \
"filter": "labels.groupId: group-0"
}
},
"time_window": {
"timeWindow": {
"duration": "7d",
"is_rolling": true
"isRolling": true
},
"budgeting_method": "occurrences",
"budgetingMethod": "occurrences",
"objective": {
"target": 0.985
}
}'
```
</details>

</details>
2 changes: 2 additions & 0 deletions x-pack/plugins/observability/public/config/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export const paths = {
ruleDetails: (ruleId?: string | null) =>
ruleId ? `${RULES_PAGE_LINK}/${encodeURI(ruleId)}` : RULES_PAGE_LINK,
slos: SLOS_PAGE_LINK,
sloCreate: `${SLOS_PAGE_LINK}/create`,
sloEdit: (sloId: string) => `${SLOS_PAGE_LINK}/edit/${encodeURI(sloId)}`,
sloDetails: (sloId: string) => `${SLOS_PAGE_LINK}/${encodeURI(sloId)}`,
},
management: {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/observability/public/data/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const baseSlo: Omit<SLOWithSummaryResponse, 'id'> = {
index: 'some-index',
filter: 'baz: foo and bar > 2',
good: 'http_status: 2xx',
total: '',
total: 'a query',
},
},
timeWindow: {
Expand Down
Loading