revert(slo): enrich policy and reset api (#171420)

- Revert "feat(slo): add reset api (#170473)"
- Revert "[SLO] Use enrich policy to add SLO details to summary
(#169993)"
This commit is contained in:
Kevin Delemme 2023-11-16 13:10:03 -05:00 committed by GitHub
parent b9cab392b2
commit 3791a73dfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 2059 additions and 1858 deletions

View file

@ -2363,9 +2363,6 @@
},
"tags": {
"type": "keyword"
},
"version": {
"type": "long"
}
}
},

View file

@ -142,7 +142,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
"siem-ui-timeline": "d3de8ff3617be8f2a799d66b1471b9be6124bf40",
"siem-ui-timeline-note": "0a32fb776907f596bedca292b8c646496ae9c57b",
"siem-ui-timeline-pinned-event": "082daa3ce647b33873f6abccf340bdfa32057c8d",
"slo": "9a9995e4572de1839651c43b5fc4dc8276bb5815",
"slo": "2048ab6791df2e1ae0936f29c20765cb8d2fcfaa",
"space": "8de4ec513e9bbc6b2f1d635161d850be7747d38e",
"spaces-usage-stats": "3abca98713c52af8b30300e386c7779b3025a20e",
"synthetics-monitor": "33ddc4b8979f378edf58bcc7ba13c5c5b572f42d",

View file

@ -8,4 +8,3 @@
export * from './src/schema';
export * from './src/rest_specs';
export * from './src/models/duration';
export * from './src/models/pagination';

View file

@ -1,17 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export interface Paginated<T> {
total: number;
page: number;
perPage: number;
results: T[];
}
export interface Pagination {
page: number;
perPage: number;
}

View file

@ -6,7 +6,6 @@
*/
import * as t from 'io-ts';
import { toBooleanRt } from '@kbn/io-ts-utils';
import {
allOrAnyString,
apmTransactionDurationIndicatorSchema,
@ -106,7 +105,6 @@ const sloResponseSchema = t.intersection([
groupBy: allOrAnyString,
createdAt: dateType,
updatedAt: dateType,
version: t.number,
}),
t.partial({
instanceId: allOrAnyString,
@ -155,12 +153,6 @@ const manageSLOParamsSchema = t.type({
path: t.type({ id: sloIdSchema }),
});
const resetSLOParamsSchema = t.type({
path: t.type({ id: sloIdSchema }),
});
const resetSLOResponseSchema = sloResponseSchema;
const updateSLOResponseSchema = sloResponseSchema;
const findSLOResponseSchema = t.type({
@ -186,21 +178,23 @@ const fetchHistoricalSummaryResponseSchema = t.array(
})
);
const findSloDefinitionsParamsSchema = t.partial({
query: t.partial({
/**
* The query params schema for /internal/observability/slo/_definitions
*
* @private
*/
const findSloDefinitionsParamsSchema = t.type({
query: t.type({
search: t.string,
includeOutdatedOnly: toBooleanRt,
page: t.string,
perPage: t.string,
}),
});
const findSloDefinitionsResponseSchema = t.type({
page: t.number,
perPage: t.number,
total: t.number,
results: t.array(sloResponseSchema),
});
/**
* The response schema for /internal/observability/slo/_definitions
*
* @private
*/
const findSloDefinitionsResponseSchema = t.array(sloResponseSchema);
const getSLOBurnRatesResponseSchema = t.type({
burnRates: t.array(
@ -246,9 +240,6 @@ type GetSLOResponse = t.OutputOf<typeof getSLOResponseSchema>;
type ManageSLOParams = t.TypeOf<typeof manageSLOParamsSchema.props.path>;
type ResetSLOParams = t.TypeOf<typeof resetSLOParamsSchema.props.path>;
type ResetSLOResponse = t.OutputOf<typeof resetSLOResponseSchema>;
type UpdateSLOInput = t.OutputOf<typeof updateSLOParamsSchema.props.body>;
type UpdateSLOParams = t.TypeOf<typeof updateSLOParamsSchema.props.body>;
type UpdateSLOResponse = t.OutputOf<typeof updateSLOResponseSchema>;
@ -263,8 +254,12 @@ type FetchHistoricalSummaryParams = t.TypeOf<typeof fetchHistoricalSummaryParams
type FetchHistoricalSummaryResponse = t.OutputOf<typeof fetchHistoricalSummaryResponseSchema>;
type HistoricalSummaryResponse = t.OutputOf<typeof historicalSummarySchema>;
type FindSLODefinitionsParams = t.TypeOf<typeof findSloDefinitionsParamsSchema.props.query>;
type FindSLODefinitionsResponse = t.OutputOf<typeof findSloDefinitionsResponseSchema>;
/**
* The response type for /internal/observability/slo/_definitions
*
* @private
*/
type FindSloDefinitionsResponse = t.OutputOf<typeof findSloDefinitionsResponseSchema>;
type GetPreviewDataParams = t.TypeOf<typeof getPreviewDataParamsSchema.props.body>;
type GetPreviewDataResponse = t.OutputOf<typeof getPreviewDataResponseSchema>;
@ -301,8 +296,6 @@ export {
findSloDefinitionsParamsSchema,
findSloDefinitionsResponseSchema,
manageSLOParamsSchema,
resetSLOParamsSchema,
resetSLOResponseSchema,
sloResponseSchema,
sloWithSummaryResponseSchema,
updateSLOParamsSchema,
@ -328,11 +321,8 @@ export type {
FetchHistoricalSummaryParams,
FetchHistoricalSummaryResponse,
HistoricalSummaryResponse,
FindSLODefinitionsParams,
FindSLODefinitionsResponse,
FindSloDefinitionsResponse,
ManageSLOParams,
ResetSLOParams,
ResetSLOResponse,
SLOResponse,
SLOWithSummaryResponse,
UpdateSLOInput,

View file

@ -50,7 +50,6 @@ const sloSchema = t.type({
createdAt: dateType,
updatedAt: dateType,
groupBy: allOrAnyString,
version: t.number,
});
const sloWithSummarySchema = t.intersection([sloSchema, t.type({ summary: summarySchema })]);

View file

@ -11,8 +11,7 @@
"**/*.ts"
],
"kbn_references": [
"@kbn/std",
"@kbn/io-ts-utils"
"@kbn/std"
],
"exclude": [
"target/**/*",

View file

@ -58,7 +58,6 @@ export const PoliciesTable: FunctionComponent<Props> = ({
fill
iconType="plusInCircle"
{...reactRouterNavigate(history, '/enrich_policies/create')}
data-test-subj="enrichPoliciesPoliciesTableCreateButton"
>
<FormattedMessage
id="xpack.idxMgmt.enrichPolicies.table.createPolicyButton"

View file

@ -143,7 +143,7 @@
{
"name": "page",
"in": "query",
"description": "The page to use for pagination, must be greater or equal than 1",
"description": "The page number to return",
"schema": {
"type": "integer",
"default": 1
@ -153,7 +153,7 @@
{
"name": "perPage",
"in": "query",
"description": "Number of SLOs returned by page",
"description": "The number of SLOs to return per page",
"schema": {
"type": "integer",
"default": 25,
@ -280,7 +280,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/slo_with_summary_response"
"$ref": "#/components/schemas/slo_response"
}
}
}
@ -361,7 +361,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/slo_definition_response"
"$ref": "#/components/schemas/slo_response"
}
}
}
@ -605,79 +605,6 @@
}
}
},
"/s/{spaceId}/api/observability/slos/{sloId}/_reset": {
"post": {
"summary": "Resets an SLO.",
"operationId": "resetSloOp",
"description": "You must have the `write` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges.\n",
"tags": [
"slo"
],
"parameters": [
{
"$ref": "#/components/parameters/kbn_xsrf"
},
{
"$ref": "#/components/parameters/space_id"
},
{
"$ref": "#/components/parameters/slo_id"
}
],
"responses": {
"204": {
"description": "Successful request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/slo_definition_response"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/400_response"
}
}
}
},
"401": {
"description": "Unauthorized response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/401_response"
}
}
}
},
"403": {
"description": "Unauthorized response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/403_response"
}
}
}
},
"404": {
"description": "Not found response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/404_response"
}
}
}
}
}
}
},
"/s/{spaceId}/internal/observability/slos/_historical_summary": {
"post": {
"summary": "Retrieves the historical summary for a list of SLOs",
@ -748,104 +675,6 @@
}
}
},
"/s/{spaceId}/internal/observability/slos/_definitions": {
"get": {
"summary": "Get the SLO definitions",
"operationId": "getDefinitionsOp",
"description": "You must have the `read` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges.\n",
"tags": [
"slo"
],
"parameters": [
{
"$ref": "#/components/parameters/kbn_xsrf"
},
{
"$ref": "#/components/parameters/space_id"
},
{
"name": "includeOutdatedOnly",
"in": "query",
"description": "Indicates if the API returns only outdated SLO or all SLO definitions",
"schema": {
"type": "boolean"
},
"example": true
},
{
"name": "search",
"in": "query",
"description": "Filters the SLOs by name",
"schema": {
"type": "string"
},
"example": "my service availability"
},
{
"name": "page",
"in": "query",
"description": "The page to use for pagination, must be greater or equal than 1",
"schema": {
"type": "number"
},
"example": 1
},
{
"name": "perPage",
"in": "query",
"description": "Number of SLOs returned by page",
"schema": {
"type": "integer",
"default": 100,
"maximum": 1000
},
"example": 100
}
],
"responses": {
"200": {
"description": "Successful request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/find_slo_definitions_response"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/400_response"
}
}
}
},
"401": {
"description": "Unauthorized response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/401_response"
}
}
}
},
"403": {
"description": "Unauthorized response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/403_response"
}
}
}
}
}
}
},
"/s/{spaceId}/api/observability/slos/_delete_instances": {
"post": {
"summary": "Batch delete rollup and summary data for the matching list of sloId and instanceId",
@ -1757,7 +1586,7 @@
}
}
},
"slo_with_summary_response": {
"slo_response": {
"title": "SLO response",
"type": "object",
"required": [
@ -1776,8 +1605,7 @@
"instanceId",
"tags",
"createdAt",
"updatedAt",
"version"
"updatedAt"
],
"properties": {
"id": {
@ -1879,11 +1707,6 @@
"description": "The last update date",
"type": "string",
"example": "2023-01-12T10:03:19.000Z"
},
"version": {
"description": "The internal SLO version",
"type": "number",
"example": 2
}
}
},
@ -1907,7 +1730,7 @@
"results": {
"type": "array",
"items": {
"$ref": "#/components/schemas/slo_with_summary_response"
"$ref": "#/components/schemas/slo_response"
}
}
}
@ -2170,126 +1993,6 @@
}
}
},
"slo_definition_response": {
"title": "SLO definition response",
"type": "object",
"required": [
"id",
"name",
"description",
"indicator",
"timeWindow",
"budgetingMethod",
"objective",
"settings",
"revision",
"enabled",
"groupBy",
"tags",
"createdAt",
"updatedAt",
"version"
],
"properties": {
"id": {
"description": "The identifier of the SLO.",
"type": "string",
"example": "8853df00-ae2e-11ed-90af-09bb6422b258"
},
"name": {
"description": "The name of the SLO.",
"type": "string",
"example": "My Service SLO"
},
"description": {
"description": "The description of the SLO.",
"type": "string",
"example": "My SLO description"
},
"indicator": {
"discriminator": {
"propertyName": "type",
"mapping": {
"sli.apm.transactionErrorRate": "#/components/schemas/indicator_properties_apm_availability",
"sli.kql.custom": "#/components/schemas/indicator_properties_custom_kql",
"sli.apm.transactionDuration": "#/components/schemas/indicator_properties_apm_latency",
"sli.metric.custom": "#/components/schemas/indicator_properties_custom_metric",
"sli.histogram.custom": "#/components/schemas/indicator_properties_histogram",
"sli.metric.timeslice": "#/components/schemas/indicator_properties_timeslice_metric"
}
},
"oneOf": [
{
"$ref": "#/components/schemas/indicator_properties_custom_kql"
},
{
"$ref": "#/components/schemas/indicator_properties_apm_availability"
},
{
"$ref": "#/components/schemas/indicator_properties_apm_latency"
},
{
"$ref": "#/components/schemas/indicator_properties_custom_metric"
},
{
"$ref": "#/components/schemas/indicator_properties_histogram"
},
{
"$ref": "#/components/schemas/indicator_properties_timeslice_metric"
}
]
},
"timeWindow": {
"$ref": "#/components/schemas/time_window"
},
"budgetingMethod": {
"$ref": "#/components/schemas/budgeting_method"
},
"objective": {
"$ref": "#/components/schemas/objective"
},
"settings": {
"$ref": "#/components/schemas/settings"
},
"revision": {
"description": "The SLO revision",
"type": "number",
"example": 2
},
"enabled": {
"description": "Indicate if the SLO is enabled",
"type": "boolean",
"example": true
},
"groupBy": {
"description": "optional group by field to use to generate an SLO per distinct value",
"type": "string",
"example": "some.field"
},
"tags": {
"description": "List of tags",
"type": "array",
"items": {
"type": "string"
}
},
"createdAt": {
"description": "The creation date",
"type": "string",
"example": "2023-01-12T10:03:19.000Z"
},
"updatedAt": {
"description": "The last update date",
"type": "string",
"example": "2023-01-12T10:03:19.000Z"
},
"version": {
"description": "The internal SLO version",
"type": "number",
"example": 2
}
}
},
"historical_summary_request": {
"title": "Historical summary request",
"type": "object",
@ -2333,31 +2036,6 @@
}
}
},
"find_slo_definitions_response": {
"title": "Find SLO definitions response",
"description": "A paginated response of SLO definitions matching the query.\n",
"type": "object",
"properties": {
"page": {
"type": "number",
"example": 2
},
"perPage": {
"type": "number",
"example": 100
},
"total": {
"type": "number",
"example": 123
},
"results": {
"type": "array",
"items": {
"$ref": "#/components/schemas/slo_definition_response"
}
}
}
},
"delete_slo_instances_request": {
"title": "Delete SLO instances request",
"description": "The delete SLO instances request takes a list of SLO id and instance id, then delete the rollup and summary data. This API can be used to remove the staled data of an instance SLO that no longer get updated.\n",

View file

@ -86,14 +86,14 @@ paths:
example: 'slo.name:latency* and slo.tags : "prod"'
- name: page
in: query
description: The page to use for pagination, must be greater or equal than 1
description: The page number to return
schema:
type: integer
default: 1
example: 1
- name: perPage
in: query
description: Number of SLOs returned by page
description: The number of SLOs to return per page
schema:
type: integer
default: 25
@ -176,7 +176,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/slo_with_summary_response'
$ref: '#/components/schemas/slo_response'
'400':
description: Bad request
content:
@ -224,7 +224,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/slo_definition_response'
$ref: '#/components/schemas/slo_response'
'400':
description: Bad request
content:
@ -365,49 +365,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/404_response'
/s/{spaceId}/api/observability/slos/{sloId}/_reset:
post:
summary: Resets an SLO.
operationId: resetSloOp
description: |
You must have the `write` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges.
tags:
- slo
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
- $ref: '#/components/parameters/space_id'
- $ref: '#/components/parameters/slo_id'
responses:
'204':
description: Successful request
content:
application/json:
schema:
$ref: '#/components/schemas/slo_definition_response'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/400_response'
'401':
description: Unauthorized response
content:
application/json:
schema:
$ref: '#/components/schemas/401_response'
'403':
description: Unauthorized response
content:
application/json:
schema:
$ref: '#/components/schemas/403_response'
'404':
description: Not found response
content:
application/json:
schema:
$ref: '#/components/schemas/404_response'
/s/{spaceId}/internal/observability/slos/_historical_summary:
post:
summary: Retrieves the historical summary for a list of SLOs
@ -450,68 +407,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/403_response'
/s/{spaceId}/internal/observability/slos/_definitions:
get:
summary: Get the SLO definitions
operationId: getDefinitionsOp
description: |
You must have the `read` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges.
tags:
- slo
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
- $ref: '#/components/parameters/space_id'
- name: includeOutdatedOnly
in: query
description: Indicates if the API returns only outdated SLO or all SLO definitions
schema:
type: boolean
example: true
- name: search
in: query
description: Filters the SLOs by name
schema:
type: string
example: my service availability
- name: page
in: query
description: The page to use for pagination, must be greater or equal than 1
schema:
type: number
example: 1
- name: perPage
in: query
description: Number of SLOs returned by page
schema:
type: integer
default: 100
maximum: 1000
example: 100
responses:
'200':
description: Successful request
content:
application/json:
schema:
$ref: '#/components/schemas/find_slo_definitions_response'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/400_response'
'401':
description: Unauthorized response
content:
application/json:
schema:
$ref: '#/components/schemas/401_response'
'403':
description: Unauthorized response
content:
application/json:
schema:
$ref: '#/components/schemas/403_response'
/s/{spaceId}/api/observability/slos/_delete_instances:
post:
summary: Batch delete rollup and summary data for the matching list of sloId and instanceId
@ -1207,7 +1102,7 @@ components:
example: 0.9836
errorBudget:
$ref: '#/components/schemas/error_budget'
slo_with_summary_response:
slo_response:
title: SLO response
type: object
required:
@ -1227,7 +1122,6 @@ components:
- tags
- createdAt
- updatedAt
- version
properties:
id:
description: The identifier of the SLO.
@ -1297,10 +1191,6 @@ components:
description: The last update date
type: string
example: '2023-01-12T10:03:19.000Z'
version:
description: The internal SLO version
type: number
example: 2
find_slo_response:
title: Find SLO response
description: |
@ -1319,7 +1209,7 @@ components:
results:
type: array
items:
$ref: '#/components/schemas/slo_with_summary_response'
$ref: '#/components/schemas/slo_response'
400_response:
title: Bad request
type: object
@ -1495,92 +1385,6 @@ components:
type: array
items:
type: string
slo_definition_response:
title: SLO definition response
type: object
required:
- id
- name
- description
- indicator
- timeWindow
- budgetingMethod
- objective
- settings
- revision
- enabled
- groupBy
- tags
- createdAt
- updatedAt
- version
properties:
id:
description: The identifier of the SLO.
type: string
example: 8853df00-ae2e-11ed-90af-09bb6422b258
name:
description: The name of the SLO.
type: string
example: My Service SLO
description:
description: The description of the SLO.
type: string
example: My SLO description
indicator:
discriminator:
propertyName: type
mapping:
sli.apm.transactionErrorRate: '#/components/schemas/indicator_properties_apm_availability'
sli.kql.custom: '#/components/schemas/indicator_properties_custom_kql'
sli.apm.transactionDuration: '#/components/schemas/indicator_properties_apm_latency'
sli.metric.custom: '#/components/schemas/indicator_properties_custom_metric'
sli.histogram.custom: '#/components/schemas/indicator_properties_histogram'
sli.metric.timeslice: '#/components/schemas/indicator_properties_timeslice_metric'
oneOf:
- $ref: '#/components/schemas/indicator_properties_custom_kql'
- $ref: '#/components/schemas/indicator_properties_apm_availability'
- $ref: '#/components/schemas/indicator_properties_apm_latency'
- $ref: '#/components/schemas/indicator_properties_custom_metric'
- $ref: '#/components/schemas/indicator_properties_histogram'
- $ref: '#/components/schemas/indicator_properties_timeslice_metric'
timeWindow:
$ref: '#/components/schemas/time_window'
budgetingMethod:
$ref: '#/components/schemas/budgeting_method'
objective:
$ref: '#/components/schemas/objective'
settings:
$ref: '#/components/schemas/settings'
revision:
description: The SLO revision
type: number
example: 2
enabled:
description: Indicate if the SLO is enabled
type: boolean
example: true
groupBy:
description: optional group by field to use to generate an SLO per distinct value
type: string
example: some.field
tags:
description: List of tags
type: array
items:
type: string
createdAt:
description: The creation date
type: string
example: '2023-01-12T10:03:19.000Z'
updatedAt:
description: The last update date
type: string
example: '2023-01-12T10:03:19.000Z'
version:
description: The internal SLO version
type: number
example: 2
historical_summary_request:
title: Historical summary request
type: object
@ -1611,25 +1415,6 @@ components:
example: 0.9836
errorBudget:
$ref: '#/components/schemas/error_budget'
find_slo_definitions_response:
title: Find SLO definitions response
description: |
A paginated response of SLO definitions matching the query.
type: object
properties:
page:
type: number
example: 2
perPage:
type: number
example: 100
total:
type: number
example: 123
results:
type: array
items:
$ref: '#/components/schemas/slo_definition_response'
delete_slo_instances_request:
title: Delete SLO instances request
description: |

View file

@ -1,18 +0,0 @@
title: Find SLO definitions response
description: >
A paginated response of SLO definitions matching the query.
type: object
properties:
page:
type: number
example: 2
perPage:
type: number
example: 100
total:
type: number
example: 123
results:
type: array
items:
$ref: 'slo_definition_response.yaml'

View file

@ -15,4 +15,4 @@ properties:
results:
type: array
items:
$ref: 'slo_with_summary_response.yaml'
$ref: 'slo_response.yaml'

View file

@ -1,85 +0,0 @@
title: SLO definition response
type: object
required:
- id
- name
- description
- indicator
- timeWindow
- budgetingMethod
- objective
- settings
- revision
- enabled
- groupBy
- tags
- createdAt
- updatedAt
- version
properties:
id:
description: The identifier of the SLO.
type: string
example: 8853df00-ae2e-11ed-90af-09bb6422b258
name:
description: The name of the SLO.
type: string
example: My Service SLO
description:
description: The description of the SLO.
type: string
example: My SLO description
indicator:
discriminator:
propertyName: type
mapping:
sli.apm.transactionErrorRate: './indicator_properties_apm_availability.yaml'
sli.kql.custom: './indicator_properties_custom_kql.yaml'
sli.apm.transactionDuration: './indicator_properties_apm_latency.yaml'
sli.metric.custom: './indicator_properties_custom_metric.yaml'
sli.histogram.custom: './indicator_properties_histogram.yaml'
sli.metric.timeslice: './indicator_properties_timeslice_metric.yaml'
oneOf:
- $ref: "indicator_properties_custom_kql.yaml"
- $ref: "indicator_properties_apm_availability.yaml"
- $ref: "indicator_properties_apm_latency.yaml"
- $ref: "indicator_properties_custom_metric.yaml"
- $ref: "indicator_properties_histogram.yaml"
- $ref: "indicator_properties_timeslice_metric.yaml"
timeWindow:
$ref: "time_window.yaml"
budgetingMethod:
$ref: "budgeting_method.yaml"
objective:
$ref: "objective.yaml"
settings:
$ref: "settings.yaml"
revision:
description: The SLO revision
type: number
example: 2
enabled:
description: Indicate if the SLO is enabled
type: boolean
example: true
groupBy:
description: optional group by field to use to generate an SLO per distinct value
type: string
example: "some.field"
tags:
description: List of tags
type: array
items:
type: string
createdAt:
description: The creation date
type: string
example: "2023-01-12T10:03:19.000Z"
updatedAt:
description: The last update date
type: string
example: "2023-01-12T10:03:19.000Z"
version:
description: The internal SLO version
type: number
example: 2

View file

@ -17,7 +17,6 @@ required:
- tags
- createdAt
- updatedAt
- version
properties:
id:
description: The identifier of the SLO.
@ -87,7 +86,3 @@ properties:
description: The last update date
type: string
example: "2023-01-12T10:03:19.000Z"
version:
description: The internal SLO version
type: number
example: 2

View file

@ -20,15 +20,11 @@ paths:
"/s/{spaceId}/api/observability/slos/{sloId}":
$ref: "paths/s@{spaceid}@api@slos@{sloid}.yaml"
"/s/{spaceId}/api/observability/slos/{sloId}/enable":
$ref: "paths/s@{spaceid}@api@slos@{sloid}@enable.yaml"
$ref: "paths/s@{spaceid}@api@slos@{sloid}@{enable}.yaml"
"/s/{spaceId}/api/observability/slos/{sloId}/disable":
$ref: "paths/s@{spaceid}@api@slos@{sloid}@disable.yaml"
"/s/{spaceId}/api/observability/slos/{sloId}/_reset":
$ref: "paths/s@{spaceid}@api@slos@{sloid}@_reset.yaml"
$ref: "paths/s@{spaceid}@api@slos@{sloid}@{disable}.yaml"
"/s/{spaceId}/internal/observability/slos/_historical_summary":
$ref: "paths/s@{spaceid}@api@slos@_historical_summary.yaml"
"/s/{spaceId}/internal/observability/slos/_definitions":
$ref: "paths/s@{spaceid}@api@slos@_definitions.yaml"
"/s/{spaceId}/api/observability/slos/_delete_instances":
$ref: "paths/s@{spaceid}@api@slos@_delete_instances.yaml"
components:

View file

@ -68,14 +68,14 @@ get:
example: 'slo.name:latency* and slo.tags : "prod"'
- name: page
in: query
description: The page to use for pagination, must be greater or equal than 1
description: The page number to return
schema:
type: integer
default: 1
example: 1
- name: perPage
in: query
description: Number of SLOs returned by page
description: The number of SLOs to return per page
schema:
type: integer
default: 25

View file

@ -1,62 +0,0 @@
get:
summary: Get the SLO definitions
operationId: getDefinitionsOp
description: >
You must have the `read` privileges for the **SLOs** feature in the
**Observability** section of the Kibana feature privileges.
tags:
- slo
parameters:
- $ref: ../components/headers/kbn_xsrf.yaml
- $ref: ../components/parameters/space_id.yaml
- name: includeOutdatedOnly
in: query
description: Indicates if the API returns only outdated SLO or all SLO definitions
schema:
type: boolean
example: true
- name: search
in: query
description: Filters the SLOs by name
schema:
type: string
example: 'my service availability'
- name: page
in: query
description: The page to use for pagination, must be greater or equal than 1
schema:
type: number
example: 1
- name: perPage
in: query
description: Number of SLOs returned by page
schema:
type: integer
default: 100
maximum: 1000
example: 100
responses:
'200':
description: Successful request
content:
application/json:
schema:
$ref: '../components/schemas/find_slo_definitions_response.yaml'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '../components/schemas/400_response.yaml'
'401':
description: Unauthorized response
content:
application/json:
schema:
$ref: '../components/schemas/401_response.yaml'
'403':
description: Unauthorized response
content:
application/json:
schema:
$ref: '../components/schemas/403_response.yaml'

View file

@ -22,7 +22,7 @@ get:
content:
application/json:
schema:
$ref: '../components/schemas/slo_with_summary_response.yaml'
$ref: '../components/schemas/slo_response.yaml'
'400':
description: Bad request
content:
@ -72,7 +72,7 @@ put:
content:
application/json:
schema:
$ref: '../components/schemas/slo_definition_response.yaml'
$ref: '../components/schemas/slo_response.yaml'
'400':
description: Bad request
content:

View file

@ -1,43 +0,0 @@
post:
summary: Resets an SLO.
operationId: resetSloOp
description: >
You must have the `write` privileges for the **SLOs** feature in the
**Observability** section of the Kibana feature privileges.
tags:
- slo
parameters:
- $ref: ../components/headers/kbn_xsrf.yaml
- $ref: ../components/parameters/space_id.yaml
- $ref: ../components/parameters/slo_id.yaml
responses:
'204':
description: Successful request
content:
application/json:
schema:
$ref: '../components/schemas/slo_definition_response.yaml'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '../components/schemas/400_response.yaml'
'401':
description: Unauthorized response
content:
application/json:
schema:
$ref: '../components/schemas/401_response.yaml'
'403':
description: Unauthorized response
content:
application/json:
schema:
$ref: '../components/schemas/403_response.yaml'
'404':
description: Not found response
content:
application/json:
schema:
$ref: '../components/schemas/404_response.yaml'

View file

@ -22,7 +22,7 @@ function SloSelector({ initialSlo, onSelected, errors }: Props) {
const [options, setOptions] = useState<Array<EuiComboBoxOptionOption<string>>>([]);
const [selectedOptions, setSelectedOptions] = useState<Array<EuiComboBoxOptionOption<string>>>();
const [searchValue, setSearchValue] = useState<string>('');
const { isLoading, data } = useFetchSloDefinitions({ name: searchValue });
const { isLoading, data: sloList } = useFetchSloDefinitions({ name: searchValue });
const hasError = errors !== undefined && errors.length > 0;
useEffect(() => {
@ -30,17 +30,17 @@ function SloSelector({ initialSlo, onSelected, errors }: Props) {
}, [initialSlo]);
useEffect(() => {
const isLoadedWithData = !isLoading && !!data?.results;
const isLoadedWithData = !isLoading && sloList !== undefined;
const opts: Array<EuiComboBoxOptionOption<string>> = isLoadedWithData
? data?.results?.map((slo) => ({ value: slo.id, label: slo.name }))
? sloList.map((slo) => ({ value: slo.id, label: slo.name }))
: [];
setOptions(opts);
}, [isLoading, data]);
}, [isLoading, sloList]);
const onChange = (opts: Array<EuiComboBoxOptionOption<string>>) => {
setSelectedOptions(opts);
const selectedSlo =
opts.length === 1 ? data?.results?.find((slo) => slo.id === opts[0].value) : undefined;
opts.length === 1 ? sloList?.find((slo) => slo.id === opts[0].value) : undefined;
onSelected(selectedSlo);
};

View file

@ -555,7 +555,7 @@ export function useLensDefinition(slo: SLOResponse): TypedLensByValueInput['attr
adHocDataViews: {
'32ca1ad4-81c0-4daf-b9d1-07118044bdc5': {
id: '32ca1ad4-81c0-4daf-b9d1-07118044bdc5',
title: '.slo-observability.sli-v3.*',
title: '.slo-observability.sli-v2.*',
timeFieldName: '@timestamp',
sourceFilters: [],
fieldFormats: {},

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import { ALL_VALUE, FindSLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema';
import { cloneDeep } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { ALL_VALUE, FindSLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema';
import {
buildDegradingSummary,
buildHealthySummary,
@ -16,8 +16,8 @@ import {
buildTimeslicesObjective,
buildViolatedSummary,
} from './common';
import { buildApmAvailabilityIndicator, buildCustomKqlIndicator } from './indicator';
import { buildCalendarAlignedTimeWindow, buildRollingTimeWindow } from './time_window';
import { buildApmAvailabilityIndicator, buildCustomKqlIndicator } from './indicator';
export const emptySloList: FindSLOResponse = {
results: [],
@ -68,7 +68,6 @@ const baseSlo: Omit<SLOWithSummaryResponse, 'id'> = {
enabled: true,
createdAt: now,
updatedAt: now,
version: 2,
};
export const sloList: FindSLOResponse = {

View file

@ -5,16 +5,24 @@
* 2.0.
*/
import { FindSLODefinitionsResponse } from '@kbn/slo-schema';
import { useQuery } from '@tanstack/react-query';
import { FindSloDefinitionsResponse, SLOResponse } from '@kbn/slo-schema';
import {
QueryObserverResult,
RefetchOptions,
RefetchQueryFilters,
useQuery,
} from '@tanstack/react-query';
import { useKibana } from '../../utils/kibana_react';
import { sloKeys } from './query_key_factory';
export interface UseFetchSloDefinitionsResponse {
data: FindSLODefinitionsResponse | undefined;
isLoading: boolean;
isSuccess: boolean;
isError: boolean;
data: SLOResponse[] | undefined;
refetch: <TPageData>(
options?: (RefetchOptions & RefetchQueryFilters<TPageData>) | undefined
) => Promise<QueryObserverResult<SLOResponse[], unknown>>;
}
interface Params {
@ -25,13 +33,18 @@ export function useFetchSloDefinitions({ name = '' }: Params): UseFetchSloDefini
const { http } = useKibana().services;
const search = name.endsWith('*') ? name : `${name}*`;
const { isLoading, isError, isSuccess, data } = useQuery({
const { isLoading, isError, isSuccess, data, refetch } = useQuery({
queryKey: sloKeys.definitions(search),
queryFn: async ({ signal }) => {
try {
const response = await http.get<FindSLODefinitionsResponse>(
'/api/observability/slos/_definitions',
{ query: { search }, signal }
const response = await http.get<FindSloDefinitionsResponse>(
'/internal/observability/slos/_definitions',
{
query: {
search,
},
signal,
}
);
return response;
@ -43,5 +56,5 @@ export function useFetchSloDefinitions({ name = '' }: Params): UseFetchSloDefini
refetchOnWindowFocus: false,
});
return { isLoading, isError, isSuccess, data };
return { isLoading, isError, isSuccess, data, refetch };
}

View file

@ -20,7 +20,7 @@ describe('SloEditLocator', () => {
it('should return correct url when slo is provided', async () => {
const location = await locator.getLocation(buildSlo({ id: 'foo' }));
expect(location.path).toEqual(
"/slos/edit/foo?_a=(budgetingMethod:occurrences,createdAt:'2022-12-29T10:11:12.000Z',description:'some%20description%20useful',enabled:!t,groupBy:'*',id:foo,indicator:(params:(filter:'baz:%20foo%20and%20bar%20%3E%202',good:'http_status:%202xx',index:some-index,timestampField:custom_timestamp,total:'a%20query'),type:sli.kql.custom),instanceId:'*',name:'super%20important%20level%20service',objective:(target:0.98),revision:1,settings:(frequency:'1m',syncDelay:'1m'),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:'30d',type:rolling),updatedAt:'2022-12-29T10:11:12.000Z',version:2)"
"/slos/edit/foo?_a=(budgetingMethod:occurrences,createdAt:'2022-12-29T10:11:12.000Z',description:'some%20description%20useful',enabled:!t,groupBy:'*',id:foo,indicator:(params:(filter:'baz:%20foo%20and%20bar%20%3E%202',good:'http_status:%202xx',index:some-index,timestampField:custom_timestamp,total:'a%20query'),type:sli.kql.custom),instanceId:'*',name:'super%20important%20level%20service',objective:(target:0.98),revision:1,settings:(frequency:'1m',syncDelay:'1m'),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:'30d',type:rolling),updatedAt:'2022-12-29T10:11:12.000Z')"
);
});
});

View file

@ -252,7 +252,6 @@ describe('SLO Details Page', () => {
settings,
updatedAt,
instanceId,
version,
...newSlo
} = slo;

View file

@ -12,14 +12,6 @@ export const getSLOMappingsTemplate = (name: string) => ({
template: {
mappings: {
properties: {
event: {
properties: {
ingested: {
type: 'date',
format: 'strict_date_optional_time',
},
},
},
'@timestamp': {
type: 'date',
format: 'date_optional_time||epoch_millis',
@ -58,10 +50,34 @@ export const getSLOMappingsTemplate = (name: string) => ({
revision: {
type: 'long',
},
groupBy: {
type: 'keyword',
ignore_above: 256,
},
instanceId: {
type: 'keyword',
ignore_above: 256,
},
name: {
type: 'keyword',
ignore_above: 256,
},
description: {
type: 'keyword',
ignore_above: 256,
},
tags: {
type: 'keyword',
ignore_above: 256,
},
indicator: {
properties: {
type: {
type: 'keyword',
ignore_above: 256,
},
},
},
objective: {
properties: {
target: {

View file

@ -55,10 +55,12 @@ export const getSLOSummaryMappingsTemplate = (name: string) => ({
ignore_above: 256,
},
name: {
type: 'text',
type: 'keyword',
ignore_above: 256,
},
description: {
type: 'text',
type: 'keyword',
ignore_above: 256,
},
tags: {
type: 'keyword',
@ -118,14 +120,6 @@ export const getSLOSummaryMappingsTemplate = (name: string) => ({
isTempDoc: {
type: 'boolean',
},
latestSliTimestamp: {
type: 'date',
format: 'date_optional_time||epoch_millis',
},
summaryUpdatedAt: {
type: 'date',
format: 'date_optional_time||epoch_millis',
},
},
},
},

View file

@ -5,9 +5,8 @@
* 2.0.
*/
export const SLO_MODEL_VERSION = 2;
export const SLO_RESOURCES_VERSION = 3;
export const SLO_SUMMARY_TRANSFORMS_VERSION = 4;
export const SLO_RESOURCES_VERSION = 2;
export const SLO_SUMMARY_TRANSFORMS_VERSION = 3;
export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings';
export const SLO_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.sli-settings';
@ -33,7 +32,6 @@ export const SLO_SUMMARY_TEMP_INDEX_NAME = `.slo-observability.summary-v${SLO_RE
export const SLO_SUMMARY_DESTINATION_INDEX_PATTERN = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}*`; // include temp and non-temp summary indices
export const SLO_SUMMARY_INGEST_PIPELINE_NAME = `.slo-observability.summary.pipeline`;
export const SLO_SUMMARY_ENRICH_POLICY_NAME = `slo-observability.summary.enrich_policy`;
export const getSLOTransformId = (sloId: string, sloRevision: number) =>
`slo-${sloId}-${sloRevision}`;

View file

@ -1,39 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { SO_SLO_TYPE } from '../../saved_objects';
import { SLO_SUMMARY_ENRICH_POLICY_NAME } from '../constants';
export const getSLOSummaryEnrichPolicy = () => ({
name: SLO_SUMMARY_ENRICH_POLICY_NAME,
match: {
indices: '.kibana',
match_field: 'slo.id',
enrich_fields: [
'slo.name',
'slo.description',
'slo.tags',
'slo.indicator.type',
'slo.objective.target',
'slo.budgetingMethod',
'slo.timeWindow.type',
'slo.timeWindow.duration',
'slo.groupBy',
],
query: {
bool: {
filter: [
{
match_phrase: {
type: SO_SLO_TYPE,
},
},
],
},
},
},
});

View file

@ -5,48 +5,12 @@
* 2.0.
*/
import { SLO_RESOURCES_VERSION, SLO_SUMMARY_ENRICH_POLICY_NAME } from '../constants';
import { SLO_RESOURCES_VERSION } from '../constants';
export const getSLOPipelineTemplate = (id: string, indexNamePrefix: string) => ({
id,
description: 'Monthly date-time index naming for SLO data',
processors: [
{
enrich: {
field: 'slo.id',
policy_name: SLO_SUMMARY_ENRICH_POLICY_NAME,
target_field: '_enrich',
},
},
{
set: {
field: 'slo.timeWindow',
copy_from: '_enrich.slo.timeWindow',
},
},
{
set: {
field: 'slo.budgetingMethod',
copy_from: '_enrich.slo.budgetingMethod',
},
},
{
set: {
field: 'slo.objective.target',
copy_from: '_enrich.slo.objective.target',
},
},
{
remove: {
field: '_enrich',
},
},
{
set: {
field: 'event.ingested',
value: '{{{_ingest.timestamp}}}',
},
},
{
date_index_name: {
field: '@timestamp',

View file

@ -5,12 +5,19 @@
* 2.0.
*/
import { SLO_RESOURCES_VERSION, SLO_SUMMARY_ENRICH_POLICY_NAME } from '../constants';
import { SLO_RESOURCES_VERSION } from '../constants';
export const getSLOSummaryPipelineTemplate = (id: string) => ({
id,
description: 'SLO summary ingest pipeline',
processors: [
{
split: {
description: 'Split comma separated list of tags into an array',
field: 'slo.tags',
separator: ',',
},
},
{
set: {
description: "if 'statusCode == 0', set status to NO_DATA",
@ -43,72 +50,6 @@ export const getSLOSummaryPipelineTemplate = (id: string) => ({
value: 'HEALTHY',
},
},
{
enrich: {
field: 'slo.id',
policy_name: SLO_SUMMARY_ENRICH_POLICY_NAME,
target_field: '_enrich',
},
},
{
set: {
field: 'slo.name',
copy_from: '_enrich.slo.name',
},
},
{
set: {
field: 'slo.description',
copy_from: '_enrich.slo.description',
},
},
{
set: {
field: 'slo.indicator',
copy_from: '_enrich.slo.indicator',
},
},
{
set: {
field: 'slo.timeWindow',
copy_from: '_enrich.slo.timeWindow',
},
},
{
set: {
field: 'slo.groupBy',
copy_from: '_enrich.slo.groupBy',
},
},
{
set: {
field: 'slo.tags',
copy_from: '_enrich.slo.tags',
},
},
{
set: {
field: 'slo.objective',
copy_from: '_enrich.slo.objective',
},
},
{
set: {
field: 'slo.budgetingMethod',
copy_from: '_enrich.slo.budgetingMethod',
},
},
{
remove: {
field: '_enrich',
},
},
{
set: {
field: 'summaryUpdatedAt',
value: '{{{_ingest.timestamp}}}',
},
},
],
_meta: {
description: 'SLO summary ingest pipeline',

View file

@ -19,7 +19,6 @@ import {
getSLOInstancesParamsSchema,
getSLOParamsSchema,
manageSLOParamsSchema,
resetSLOParamsSchema,
updateSLOParamsSchema,
} from '@kbn/slo-schema';
import type { IndicatorTypes } from '../../domain/models';
@ -42,7 +41,6 @@ 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 {
ApmTransactionDurationTransformGenerator,
@ -50,8 +48,8 @@ import {
HistogramTransformGenerator,
KQLCustomTransformGenerator,
MetricCustomTransformGenerator,
TimesliceMetricTransformGenerator,
TransformGenerator,
TimesliceMetricTransformGenerator,
} from '../../services/slo/transform_generators';
import type { ObservabilityRequestHandlerContext } from '../../types';
import { createObservabilityServerRoute } from '../create_observability_server_route';
@ -85,11 +83,10 @@ const createSLORoute = createObservabilityServerRoute({
await assertPlatinumLicense(context);
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
const systemEsClient = (await context.core).elasticsearch.client.asInternalUser;
const soClient = (await context.core).savedObjects.client;
const repository = new KibanaSavedObjectsSLORepository(soClient);
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
const createSLO = new CreateSLO(esClient, systemEsClient, repository, transformManager);
const createSLO = new CreateSLO(esClient, repository, transformManager);
const response = await createSLO.execute(params.body);
@ -108,12 +105,11 @@ const updateSLORoute = createObservabilityServerRoute({
await assertPlatinumLicense(context);
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
const systemEsClient = (await context.core).elasticsearch.client.asInternalUser;
const soClient = (await context.core).savedObjects.client;
const repository = new KibanaSavedObjectsSLORepository(soClient);
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
const updateSLO = new UpdateSLO(repository, transformManager, esClient, systemEsClient);
const updateSLO = new UpdateSLO(repository, transformManager, esClient);
const response = await updateSLO.execute(params.path.id, params.body);
@ -138,20 +134,13 @@ const deleteSLORoute = createObservabilityServerRoute({
await assertPlatinumLicense(context);
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
const systemEsClient = (await context.core).elasticsearch.client.asInternalUser;
const soClient = (await context.core).savedObjects.client;
const rulesClient = getRulesClientWithRequest(request);
const repository = new KibanaSavedObjectsSLORepository(soClient);
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
const deleteSLO = new DeleteSLO(
repository,
transformManager,
esClient,
rulesClient,
systemEsClient
);
const deleteSLO = new DeleteSLO(repository, transformManager, esClient, rulesClient);
await deleteSLO.execute(params.path.id);
},
@ -225,29 +214,6 @@ const disableSLORoute = createObservabilityServerRoute({
},
});
const resetSLORoute = createObservabilityServerRoute({
endpoint: 'POST /api/observability/slos/{id}/_reset 2023-10-31',
options: {
tags: ['access:slo_write'],
access: 'public',
},
params: resetSLOParamsSchema,
handler: async ({ context, params, logger }) => {
await assertPlatinumLicense(context);
const soClient = (await context.core).savedObjects.client;
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
const repository = new KibanaSavedObjectsSLORepository(soClient);
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
const resetSLO = new ResetSLO(esClient, repository, transformManager);
const response = await resetSLO.execute(params.path.id);
return response;
},
});
const findSLORoute = createObservabilityServerRoute({
endpoint: 'GET /api/observability/slos 2023-10-31',
options: {
@ -287,9 +253,10 @@ const deleteSloInstancesRoute = createObservabilityServerRoute({
});
const findSloDefinitionsRoute = createObservabilityServerRoute({
endpoint: 'GET /api/observability/slos/_definitions 2023-10-31',
endpoint: 'GET /internal/observability/slos/_definitions',
options: {
tags: ['access:slo_read'],
access: 'internal',
},
params: findSloDefinitionsParamsSchema,
handler: async ({ context, params }) => {
@ -299,7 +266,7 @@ const findSloDefinitionsRoute = createObservabilityServerRoute({
const repository = new KibanaSavedObjectsSLORepository(soClient);
const findSloDefinitions = new FindSLODefinitions(repository);
const response = await findSloDefinitions.execute(params?.query ?? {});
const response = await findSloDefinitions.execute(params.query.search);
return response;
},
@ -428,5 +395,4 @@ export const sloRouteRepository = {
...getSloBurnRates,
...getPreviewData,
...getSLOInstancesRoute,
...resetSLORoute,
};

View file

@ -17,6 +17,7 @@ type StoredSLOBefore890 = StoredSLO & {
isCalendar?: boolean;
};
};
const migrateSlo890: SavedObjectMigrationFn<StoredSLOBefore890, StoredSLO> = (doc) => {
const { timeWindow, ...other } = doc.attributes;
return {
@ -37,21 +38,6 @@ export const slo: SavedObjectsType = {
name: SO_SLO_TYPE,
hidden: false,
namespaceType: 'multiple-isolated',
switchToModelVersionAt: '8.10.0',
modelVersions: {
1: {
changes: [
{ type: 'mappings_addition', addedMappings: { version: { type: 'long' } } },
{
type: 'data_backfill',
backfillFn: (doc) => {
// we explicitely set the version to 1, so we know which SLOs requires a migration to the following version.
return { attributes: { version: doc.attributes.version ?? 1 } };
},
},
],
},
},
mappings: {
dynamic: false,
properties: {
@ -67,7 +53,6 @@ export const slo: SavedObjectsType = {
budgetingMethod: { type: 'keyword' },
enabled: { type: 'boolean' },
tags: { type: 'keyword' },
version: { type: 'long' },
},
},
management: {

View file

@ -41,16 +41,8 @@ Array [
},
},
"id": "slo-unique-id",
"index": ".slo-observability.summary-v3.temp",
"index": ".slo-observability.summary-v2.temp",
"refresh": true,
},
]
`;
exports[`CreateSLO happy path calls the expected services 2`] = `
Array [
Object {
"name": "slo-observability.summary.enrich_policy",
},
]
`;

View file

@ -11,7 +11,7 @@ Array [
},
},
},
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"filter": Array [

View file

@ -3,7 +3,7 @@
exports[`Summary Search Client returns the summary documents without duplicate temporary summary documents 1`] = `
Array [
Object {
"index": ".slo-observability.summary-v3*",
"index": ".slo-observability.summary-v2*",
"query": Object {
"bool": Object {
"filter": Array [

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`UpdateSLO when the revision bumps indexes a temporary summary document 1`] = `
exports[`UpdateSLO index a temporary summary document 1`] = `
Array [
Object {
"document": Object {
@ -44,7 +44,7 @@ Array [
},
},
"id": "slo-unique-id",
"index": ".slo-observability.summary-v3.temp",
"index": ".slo-observability.summary-v2.temp",
"refresh": true,
},
]

View file

@ -15,22 +15,15 @@ import { TransformManager } from './transform_manager';
describe('CreateSLO', () => {
let esClientMock: ElasticsearchClientMock;
let esSystemClientMock: ElasticsearchClientMock;
let mockRepository: jest.Mocked<SLORepository>;
let mockTransformManager: jest.Mocked<TransformManager>;
let createSLO: CreateSLO;
beforeEach(() => {
esClientMock = elasticsearchServiceMock.createElasticsearchClient();
esSystemClientMock = elasticsearchServiceMock.createElasticsearchClient();
mockRepository = createSLORepositoryMock();
mockTransformManager = createTransformManagerMock();
createSLO = new CreateSLO(
esClientMock,
esSystemClientMock,
mockRepository,
mockTransformManager
);
createSLO = new CreateSLO(esClientMock, mockRepository, mockTransformManager);
});
describe('happy path', () => {
@ -66,7 +59,6 @@ describe('CreateSLO', () => {
expect(mockTransformManager.start).toHaveBeenCalledWith('slo-transform-id');
expect(response).toEqual(expect.objectContaining({ id: 'unique-id' }));
expect(esClientMock.index.mock.calls[0]).toMatchSnapshot();
expect(esSystemClientMock.enrich.executePolicy.mock.calls[0]).toMatchSnapshot();
});
it('overrides the default values when provided', async () => {

View file

@ -8,11 +8,7 @@
import { ElasticsearchClient } from '@kbn/core/server';
import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema';
import { v4 as uuidv4 } from 'uuid';
import {
SLO_MODEL_VERSION,
SLO_SUMMARY_ENRICH_POLICY_NAME,
SLO_SUMMARY_TEMP_INDEX_NAME,
} from '../../assets/constants';
import { SLO_SUMMARY_TEMP_INDEX_NAME } from '../../assets/constants';
import { Duration, DurationUnit, SLO } from '../../domain/models';
import { validateSLO } from '../../domain/services';
import { SLORepository } from './slo_repository';
@ -22,7 +18,6 @@ import { TransformManager } from './transform_manager';
export class CreateSLO {
constructor(
private esClient: ElasticsearchClient,
private systemClient: ElasticsearchClient,
private repository: SLORepository,
private transformManager: TransformManager
) {}
@ -59,8 +54,6 @@ export class CreateSLO {
refresh: true,
});
await this.systemClient.enrich.executePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME });
return this.toResponse(slo);
}
@ -79,7 +72,6 @@ export class CreateSLO {
createdAt: now,
updatedAt: now,
groupBy: !!params.groupBy ? params.groupBy : ALL_VALUE,
version: SLO_MODEL_VERSION,
};
}

View file

@ -24,7 +24,6 @@ describe('DeleteSLO', () => {
let mockRepository: jest.Mocked<SLORepository>;
let mockTransformManager: jest.Mocked<TransformManager>;
let mockEsClient: jest.Mocked<ElasticsearchClient>;
let mockSystemEsClient: jest.Mocked<ElasticsearchClient>;
let mockRulesClient: jest.Mocked<RulesClientApi>;
let deleteSLO: DeleteSLO;
@ -32,15 +31,8 @@ describe('DeleteSLO', () => {
mockRepository = createSLORepositoryMock();
mockTransformManager = createTransformManagerMock();
mockEsClient = elasticsearchServiceMock.createElasticsearchClient();
mockSystemEsClient = elasticsearchServiceMock.createElasticsearchClient();
mockRulesClient = rulesClientMock.create();
deleteSLO = new DeleteSLO(
mockRepository,
mockTransformManager,
mockEsClient,
mockRulesClient,
mockSystemEsClient
);
deleteSLO = new DeleteSLO(mockRepository, mockTransformManager, mockEsClient, mockRulesClient);
});
describe('happy path', () => {
@ -80,7 +72,6 @@ describe('DeleteSLO', () => {
},
})
);
expect(mockSystemEsClient.enrich.executePolicy).toHaveBeenCalled();
expect(mockRulesClient.bulkDeleteRules).toHaveBeenCalledWith({
filter: `alert.attributes.params.sloId:${slo.id}`,
});

View file

@ -11,7 +11,6 @@ import {
getSLOTransformId,
SLO_DESTINATION_INDEX_PATTERN,
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
SLO_SUMMARY_ENRICH_POLICY_NAME,
} from '../../assets/constants';
import { SLORepository } from './slo_repository';
import { TransformManager } from './transform_manager';
@ -21,8 +20,7 @@ export class DeleteSLO {
private repository: SLORepository,
private transformManager: TransformManager,
private esClient: ElasticsearchClient,
private rulesClient: RulesClientApi,
private systemClient: ElasticsearchClient
private rulesClient: RulesClientApi
) {}
public async execute(sloId: string): Promise<void> {
@ -36,7 +34,6 @@ export class DeleteSLO {
await this.deleteSummaryData(slo.id);
await this.deleteAssociatedRules(slo.id);
await this.repository.deleteById(slo.id);
await this.systemClient.enrich.executePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME });
}
private async deleteRollupData(sloId: string): Promise<void> {

View file

@ -43,7 +43,7 @@ describe('DeleteSLOInstances', () => {
expect(mockEsClient.deleteByQuery).toHaveBeenCalledTimes(2);
expect(mockEsClient.deleteByQuery.mock.calls[0][0]).toMatchInlineSnapshot(`
Object {
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"should": Array [
@ -103,7 +103,7 @@ describe('DeleteSLOInstances', () => {
`);
expect(mockEsClient.deleteByQuery.mock.calls[1][0]).toMatchInlineSnapshot(`
Object {
"index": ".slo-observability.summary-v3*",
"index": ".slo-observability.summary-v2*",
"query": Object {
"bool": Object {
"should": Array [

View file

@ -5,14 +5,13 @@
* 2.0.
*/
import { ALL_VALUE, Paginated } from '@kbn/slo-schema';
import { SLO_MODEL_VERSION } from '../../assets/constants';
import { ALL_VALUE } from '@kbn/slo-schema';
import { SLO } from '../../domain/models';
import { FindSLO } from './find_slo';
import { createSLO } from './fixtures/slo';
import { createSLORepositoryMock, createSummarySearchClientMock } from './mocks';
import { SLORepository } from './slo_repository';
import { SLOSummary, SummarySearchClient } from './summary_search_client';
import { Paginated, SLOSummary, SummarySearchClient } from './summary_search_client';
describe('FindSLO', () => {
let mockRepository: jest.Mocked<SLORepository>;
@ -96,7 +95,6 @@ describe('FindSLO', () => {
revision: slo.revision,
groupBy: slo.groupBy,
instanceId: ALL_VALUE,
version: SLO_MODEL_VERSION,
},
],
});

View file

@ -5,11 +5,11 @@
* 2.0.
*/
import { FindSLOParams, FindSLOResponse, findSLOResponseSchema, Pagination } from '@kbn/slo-schema';
import { FindSLOParams, FindSLOResponse, findSLOResponseSchema } from '@kbn/slo-schema';
import { SLO, SLOWithSummary } from '../../domain/models';
import { IllegalArgumentError } from '../../errors';
import { SLORepository } from './slo_repository';
import { SLOSummary, Sort, SummarySearchClient } from './summary_search_client';
import { Pagination, SLOSummary, Sort, SummarySearchClient } from './summary_search_client';
const DEFAULT_PAGE = 1;
const DEFAULT_PER_PAGE = 25;
@ -55,7 +55,7 @@ function toPagination(params: FindSLOParams): Pagination {
const perPage = Number(params.perPage);
if (!isNaN(perPage) && perPage > MAX_PER_PAGE) {
throw new IllegalArgumentError(`perPage limit to ${MAX_PER_PAGE}`);
throw new IllegalArgumentError('perPage limit to 5000');
}
return {

View file

@ -5,40 +5,14 @@
* 2.0.
*/
import {
FindSLODefinitionsParams,
FindSLODefinitionsResponse,
findSloDefinitionsResponseSchema,
Pagination,
} from '@kbn/slo-schema';
import { IllegalArgumentError } from '../../errors';
import { FindSloDefinitionsResponse, findSloDefinitionsResponseSchema } from '@kbn/slo-schema';
import { SLORepository } from './slo_repository';
const MAX_PER_PAGE = 1000;
const DEFAULT_PER_PAGE = 100;
const DEFAULT_PAGE = 1;
export class FindSLODefinitions {
constructor(private repository: SLORepository) {}
public async execute(params: FindSLODefinitionsParams): Promise<FindSLODefinitionsResponse> {
const result = await this.repository.search(params.search ?? '', toPagination(params), {
includeOutdatedOnly: params.includeOutdatedOnly === true ? true : false,
});
return findSloDefinitionsResponseSchema.encode(result);
public async execute(search: string): Promise<FindSloDefinitionsResponse> {
const sloList = await this.repository.search(search);
return findSloDefinitionsResponseSchema.encode(sloList);
}
}
function toPagination(params: FindSLODefinitionsParams): Pagination {
const page = Number(params.page);
const perPage = Number(params.perPage);
if (!isNaN(perPage) && perPage > MAX_PER_PAGE) {
throw new IllegalArgumentError(`perPage limit to ${MAX_PER_PAGE}`);
}
return {
page: !isNaN(page) && page >= 1 ? page : DEFAULT_PAGE,
perPage: !isNaN(perPage) && perPage >= 1 ? perPage : DEFAULT_PER_PAGE,
};
}

View file

@ -15,7 +15,6 @@ import {
} from '@kbn/slo-schema';
import { cloneDeep } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { SLO_MODEL_VERSION } from '../../../assets/constants';
import {
APMTransactionDurationIndicator,
APMTransactionErrorRateIndicator,
@ -140,7 +139,7 @@ export const createHistogramIndicator = (
},
});
const defaultSLO: Omit<SLO, 'id' | 'revision' | 'createdAt' | 'updatedAt' | 'version'> = {
const defaultSLO: Omit<SLO, 'id' | 'revision' | 'createdAt' | 'updatedAt'> = {
name: 'irrelevant',
description: 'irrelevant',
timeWindow: sevenDaysRolling(),
@ -191,7 +190,6 @@ export const createSLO = (params: Partial<SLO> = {}): SLO => {
revision: 1,
createdAt: now,
updatedAt: now,
version: SLO_MODEL_VERSION,
...params,
});
};

View file

@ -6,7 +6,6 @@
*/
import { ALL_VALUE } from '@kbn/slo-schema';
import { SLO_MODEL_VERSION } from '../../assets/constants';
import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo';
import { GetSLO } from './get_slo';
import { createSummaryClientMock, createSLORepositoryMock } from './mocks';
@ -85,7 +84,6 @@ describe('GetSLO', () => {
revision: slo.revision,
groupBy: slo.groupBy,
instanceId: ALL_VALUE,
version: SLO_MODEL_VERSION,
});
});
});

View file

@ -1,80 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { ElasticsearchClient } from '@kbn/core/server';
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
import {
getSLOTransformId,
SLO_DESTINATION_INDEX_PATTERN,
SLO_MODEL_VERSION,
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
} from '../../assets/constants';
import { createSLO } from './fixtures/slo';
import { createSLORepositoryMock, createTransformManagerMock } from './mocks';
import { ResetSLO } from './reset_slo';
import { SLORepository } from './slo_repository';
import { TransformManager } from './transform_manager';
describe('ResetSLO', () => {
let mockRepository: jest.Mocked<SLORepository>;
let mockTransformManager: jest.Mocked<TransformManager>;
let mockEsClient: jest.Mocked<ElasticsearchClient>;
let resetSLO: ResetSLO;
beforeEach(() => {
mockRepository = createSLORepositoryMock();
mockTransformManager = createTransformManagerMock();
mockEsClient = elasticsearchServiceMock.createElasticsearchClient();
resetSLO = new ResetSLO(mockEsClient, mockRepository, mockTransformManager);
});
it('resets the SLO', async () => {
const slo = createSLO({ version: 1 });
mockRepository.findById.mockResolvedValueOnce(slo);
mockRepository.save.mockImplementation((v) => Promise.resolve(v));
await resetSLO.execute(slo.id);
const transformId = getSLOTransformId(slo.id, slo.revision);
expect(mockTransformManager.stop).toBeCalledWith(transformId);
expect(mockTransformManager.uninstall).toBeCalledWith(transformId);
expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
index: SLO_DESTINATION_INDEX_PATTERN,
query: {
bool: {
filter: [{ term: { 'slo.id': slo.id } }],
},
},
})
);
expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
query: {
bool: {
filter: [{ term: { 'slo.id': slo.id } }],
},
},
})
);
expect(mockTransformManager.install).toBeCalledWith(slo);
expect(mockTransformManager.preview).toBeCalledWith(transformId);
expect(mockTransformManager.start).toBeCalledWith(transformId);
expect(mockRepository.save).toHaveBeenCalledWith({
...slo,
version: SLO_MODEL_VERSION,
updatedAt: expect.anything(),
});
});
});

View file

@ -1,96 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { ElasticsearchClient } from '@kbn/core/server';
import { resetSLOResponseSchema } from '@kbn/slo-schema';
import {
getSLOTransformId,
SLO_DESTINATION_INDEX_PATTERN,
SLO_MODEL_VERSION,
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
SLO_SUMMARY_TEMP_INDEX_NAME,
} from '../../assets/constants';
import { SLORepository } from './slo_repository';
import { createTempSummaryDocument } from './summary_transform/helpers/create_temp_summary';
import { TransformManager } from './transform_manager';
export class ResetSLO {
constructor(
private esClient: ElasticsearchClient,
private repository: SLORepository,
private transformManager: TransformManager
) {}
public async execute(sloId: string) {
const slo = await this.repository.findById(sloId);
const transformId = getSLOTransformId(slo.id, slo.revision);
await this.transformManager.stop(transformId);
await this.transformManager.uninstall(transformId);
await Promise.all([this.deleteRollupData(slo.id), this.deleteSummaryData(slo.id)]);
await this.transformManager.install(slo);
try {
await this.transformManager.preview(transformId);
await this.transformManager.start(transformId);
} catch (err) {
await this.transformManager.uninstall(transformId);
throw err;
}
await this.esClient.index({
index: SLO_SUMMARY_TEMP_INDEX_NAME,
id: `slo-${slo.id}`,
document: createTempSummaryDocument(slo),
refresh: true,
});
const updatedSlo = await this.repository.save(
Object.assign({ ...slo, version: SLO_MODEL_VERSION, updatedAt: new Date() })
);
return resetSLOResponseSchema.encode(updatedSlo);
}
/**
* Deleting all SLI rollup data matching the sloId. All revision will be deleted in case of
* residual documents.
*
* @param sloId
*/
private async deleteRollupData(sloId: string): Promise<void> {
await this.esClient.deleteByQuery({
index: SLO_DESTINATION_INDEX_PATTERN,
refresh: true,
query: {
bool: {
filter: [{ term: { 'slo.id': sloId } }],
},
},
});
}
/**
* Deleting the summary documents matching the sloId. All revision will be deleted in case of
* residual documents.
*
* @param sloId
*/
private async deleteSummaryData(sloId: string): Promise<void> {
await this.esClient.deleteByQuery({
index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
refresh: true,
query: {
bool: {
filter: [{ term: { 'slo.id': sloId } }],
},
},
});
}
}

View file

@ -14,20 +14,15 @@ import {
SLO_INGEST_PIPELINE_NAME,
SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME,
SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME,
SLO_SUMMARY_ENRICH_POLICY_NAME,
SLO_SUMMARY_INDEX_TEMPLATE_NAME,
SLO_SUMMARY_INGEST_PIPELINE_NAME,
} from '../../assets/constants';
import { getSLOSummaryEnrichPolicy } from '../../assets/enrich_policies/slo_summary_enrich_policy';
import { DefaultResourceInstaller } from './resource_installer';
describe('resourceInstaller', () => {
it('installs the common resources', async () => {
const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient();
mockClusterClient.indices.getIndexTemplate.mockResponseOnce({ index_templates: [] });
mockClusterClient.enrich.getPolicy.mockResponseOnce({
policies: [],
});
const installer = new DefaultResourceInstaller(mockClusterClient, loggerMock.create());
await installer.ensureCommonResourcesInstalled();
@ -59,21 +54,6 @@ describe('resourceInstaller', () => {
expect.objectContaining({ name: SLO_SUMMARY_INDEX_TEMPLATE_NAME })
);
expect(mockClusterClient.enrich.getPolicy).toHaveBeenCalledTimes(1);
expect(mockClusterClient.enrich.getPolicy).toHaveBeenNthCalledWith(1, {
name: SLO_SUMMARY_ENRICH_POLICY_NAME,
});
expect(mockClusterClient.enrich.putPolicy).toHaveBeenCalledTimes(1);
expect(mockClusterClient.enrich.putPolicy).toHaveBeenNthCalledWith(
1,
getSLOSummaryEnrichPolicy()
);
expect(mockClusterClient.enrich.executePolicy).toHaveBeenCalledTimes(1);
expect(mockClusterClient.enrich.executePolicy).toHaveBeenNthCalledWith(1, {
name: SLO_SUMMARY_ENRICH_POLICY_NAME,
});
expect(mockClusterClient.ingest.putPipeline).toHaveBeenCalledTimes(2);
expect(mockClusterClient.ingest.putPipeline).toHaveBeenNthCalledWith(
1,
@ -84,34 +64,4 @@ describe('resourceInstaller', () => {
expect.objectContaining({ id: SLO_SUMMARY_INGEST_PIPELINE_NAME })
);
});
it('skips installing the enrich policy if it exists', async () => {
const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient();
mockClusterClient.indices.getIndexTemplate.mockResponseOnce({ index_templates: [] });
mockClusterClient.enrich.getPolicy.mockResponseOnce({
policies: [
{
config: {
// Sigh.... the Elasticsarch type for an enrich policy has defined the
// query as a string which is completely wrong, it's a QueryDSLContainer!
//
// See: https://github.com/elastic/elasticsearch-js/issues/2074
match: {
...getSLOSummaryEnrichPolicy().match,
name: SLO_SUMMARY_ENRICH_POLICY_NAME,
} as any,
},
},
],
});
const installer = new DefaultResourceInstaller(mockClusterClient, loggerMock.create());
await installer.ensureCommonResourcesInstalled();
expect(mockClusterClient.enrich.getPolicy).toHaveBeenCalledTimes(1);
expect(mockClusterClient.enrich.getPolicy).toHaveBeenNthCalledWith(1, {
name: SLO_SUMMARY_ENRICH_POLICY_NAME,
});
expect(mockClusterClient.enrich.putPolicy).not.toHaveBeenCalled();
expect(mockClusterClient.enrich.executePolicy).not.toHaveBeenCalled();
});
});

View file

@ -7,7 +7,6 @@
import type {
ClusterPutComponentTemplateRequest,
EnrichPutPolicyRequest,
IndicesPutIndexTemplateRequest,
IngestPutPipelineRequest,
} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
@ -32,7 +31,6 @@ import {
SLO_SUMMARY_INGEST_PIPELINE_NAME,
SLO_SUMMARY_TEMP_INDEX_NAME,
} from '../../assets/constants';
import { getSLOSummaryEnrichPolicy } from '../../assets/enrich_policies/slo_summary_enrich_policy';
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';
@ -86,8 +84,6 @@ export class DefaultResourceInstaller implements ResourceInstaller {
await this.createIndex(SLO_SUMMARY_DESTINATION_INDEX_NAME);
await this.createIndex(SLO_SUMMARY_TEMP_INDEX_NAME);
await this.createOrUpdateEnrichPolicy(getSLOSummaryEnrichPolicy());
await this.createOrUpdateIngestPipelineTemplate(
getSLOPipelineTemplate(SLO_INGEST_PIPELINE_NAME, SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX)
);
@ -116,20 +112,6 @@ export class DefaultResourceInstaller implements ResourceInstaller {
return this.execute(() => this.esClient.ingest.putPipeline(template));
}
private async createOrUpdateEnrichPolicy(policy: EnrichPutPolicyRequest) {
return this.execute(async () => {
const existingPolicy = await this.esClient.enrich.getPolicy({ name: policy.name });
if (existingPolicy.policies.some(({ config }) => config.match?.name === policy.name)) {
this.logger.info(`SLO summary erich policy [${policy.name}] already exists.`);
return;
}
this.logger.info(`Installing SLO summary erich policy [${policy.name}]`);
return this.esClient.enrich
.putPolicy(policy)
.then(() => this.esClient.enrich.executePolicy({ name: policy.name }));
});
}
private async createIndex(indexName: string) {
try {
await this.execute(() => this.esClient.indices.create({ index: indexName }));

View file

@ -8,7 +8,6 @@
import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server';
import { savedObjectsClientMock } from '@kbn/core/server/mocks';
import { sloSchema } from '@kbn/slo-schema';
import { SLO_MODEL_VERSION } from '../../assets/constants';
import { SLO, StoredSLO } from '../../domain/models';
import { SLOIdConflict, SLONotFound } from '../../errors';
import { SO_SLO_TYPE } from '../../saved_objects';
@ -165,42 +164,19 @@ describe('KibanaSavedObjectsSLORepository', () => {
expect(soClientMock.delete).toHaveBeenCalledWith(SO_SLO_TYPE, SOME_SLO.id);
});
describe('search', () => {
it('searches by name', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO]));
it('searches by name', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO]));
const results = await repository.search(SOME_SLO.name, { page: 1, perPage: 100 });
const results = await repository.search(SOME_SLO.name);
expect(results.results).toEqual([SOME_SLO, ANOTHER_SLO]);
expect(soClientMock.find).toHaveBeenCalledWith({
type: SO_SLO_TYPE,
page: 1,
perPage: 100,
search: SOME_SLO.name,
searchFields: ['name'],
});
});
it('searches only the outdated ones', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO]));
const results = await repository.search(
SOME_SLO.name,
{ page: 1, perPage: 100 },
{ includeOutdatedOnly: true }
);
expect(results.results).toEqual([SOME_SLO, ANOTHER_SLO]);
expect(soClientMock.find).toHaveBeenCalledWith({
type: SO_SLO_TYPE,
page: 1,
perPage: 100,
search: SOME_SLO.name,
searchFields: ['name'],
filter: `slo.attributes.version < ${SLO_MODEL_VERSION}`,
});
expect(results).toEqual([SOME_SLO, ANOTHER_SLO]);
expect(soClientMock.find).toHaveBeenCalledWith({
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
search: SOME_SLO.name,
searchFields: ['name'],
});
});
});

View file

@ -7,11 +7,10 @@
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-server';
import { Paginated, Pagination, sloSchema } from '@kbn/slo-schema';
import { sloSchema } from '@kbn/slo-schema';
import { fold } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/pipeable';
import * as t from 'io-ts';
import { SLO_MODEL_VERSION } from '../../assets/constants';
import { SLO, StoredSLO } from '../../domain/models';
import { SLOIdConflict, SLONotFound } from '../../errors';
import { SO_SLO_TYPE } from '../../saved_objects';
@ -21,11 +20,7 @@ export interface SLORepository {
findAllByIds(ids: string[]): Promise<SLO[]>;
findById(id: string): Promise<SLO>;
deleteById(id: string): Promise<void>;
search(
search: string,
pagination: Pagination,
options?: { includeOutdatedOnly?: boolean }
): Promise<Paginated<SLO>>;
search(search: string): Promise<SLO[]>;
}
export class KibanaSavedObjectsSLORepository implements SLORepository {
@ -104,28 +99,19 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
}
}
async search(
search: string,
pagination: Pagination,
options: { includeOutdatedOnly?: boolean } = { includeOutdatedOnly: false }
): Promise<Paginated<SLO>> {
const response = await this.soClient.find<StoredSLO>({
type: SO_SLO_TYPE,
page: pagination.page,
perPage: pagination.perPage,
search,
searchFields: ['name'],
...(!!options.includeOutdatedOnly && {
filter: `slo.attributes.version < ${SLO_MODEL_VERSION}`,
}),
});
return {
total: response.total,
perPage: response.per_page,
page: response.page,
results: response.saved_objects.map((slo) => toSLO(slo.attributes)),
};
async search(search: string): Promise<SLO[]> {
try {
const response = await this.soClient.find<StoredSLO>({
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
search,
searchFields: ['name'],
});
return response.saved_objects.map((slo) => toSLO(slo.attributes));
} catch (err) {
throw err;
}
}
}
@ -135,13 +121,7 @@ function toStoredSLO(slo: SLO): StoredSLO {
function toSLO(storedSLO: StoredSLO): SLO {
return pipe(
sloSchema.decode({
...storedSLO,
// version was added in 8.12.0. This is a safeguard against SO migration issue.
// if not present, we considered the version to be 1, e.g. not migrated.
// We would need to call the _reset api on this SLO.
version: storedSLO.version ?? 1,
}),
sloSchema.decode(storedSLO),
fold(() => {
throw new Error('Invalid Stored SLO');
}, t.identity)

View file

@ -7,13 +7,17 @@
import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks';
import { loggerMock } from '@kbn/logging-mocks';
import { Pagination } from '@kbn/slo-schema/src/models/pagination';
import {
aHitFromSummaryIndex,
aHitFromTempSummaryIndex,
aSummaryDocument,
} from './fixtures/summary_search_document';
import { DefaultSummarySearchClient, Sort, SummarySearchClient } from './summary_search_client';
import {
DefaultSummarySearchClient,
Pagination,
Sort,
SummarySearchClient,
} from './summary_search_client';
const defaultSort: Sort = {
field: 'sli_value',

View file

@ -6,7 +6,7 @@
*/
import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { ALL_VALUE, Paginated, Pagination } from '@kbn/slo-schema';
import { ALL_VALUE } from '@kbn/slo-schema';
import { assertNever } from '@kbn/std';
import _ from 'lodash';
import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../assets/constants';
@ -30,6 +30,13 @@ interface EsSummaryDocument {
isTempDoc: boolean;
}
export interface Paginated<T> {
total: number;
page: number;
perPage: number;
results: T[];
}
export interface SLOSummary {
id: SLOId;
instanceId: string;
@ -42,6 +49,11 @@ export interface Sort {
direction: 'asc' | 'desc';
}
export interface Pagination {
page: number;
perPage: number;
}
export interface SummarySearchClient {
search(kqlQuery: string, sort: Sort, pagination: Pagination): Promise<Paginated<SLOSummary>>;
}

View file

@ -7,11 +7,11 @@ Array [
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 4,
"version": 3,
},
"description": "Summarize every SLO with timeslices budgeting method and a 7 days rolling time window",
"dest": Object {
"index": ".slo-observability.summary-v3",
"index": ".slo-observability.summary-v2",
"pipeline": ".slo-observability.summary.pipeline",
},
"frequency": "1m",
@ -52,11 +52,6 @@ Array [
"field": "slo.isGoodSlice",
},
},
"latestSliTimestamp": Object {
"max": Object {
"field": "@timestamp",
},
},
"sliValue": Object {
"bucket_script": Object {
"buckets_path": Object {
@ -112,21 +107,46 @@ Array [
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
@ -156,7 +176,7 @@ Array [
"unattended": true,
},
"source": Object {
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"filter": Array [
@ -199,8 +219,8 @@ Array [
},
"sync": Object {
"time": Object {
"delay": "65s",
"field": "event.ingested",
"delay": "125s",
"field": "@timestamp",
},
},
"transform_id": "slo-summary-timeslices-7d-rolling",
@ -216,11 +236,11 @@ Array [
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 4,
"version": 3,
},
"description": "Summarize every SLO with timeslices budgeting method and a 30 days rolling time window",
"dest": Object {
"index": ".slo-observability.summary-v3",
"index": ".slo-observability.summary-v2",
"pipeline": ".slo-observability.summary.pipeline",
},
"frequency": "1m",
@ -261,11 +281,6 @@ Array [
"field": "slo.isGoodSlice",
},
},
"latestSliTimestamp": Object {
"max": Object {
"field": "@timestamp",
},
},
"sliValue": Object {
"bucket_script": Object {
"buckets_path": Object {
@ -321,21 +336,46 @@ Array [
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
@ -365,7 +405,7 @@ Array [
"unattended": true,
},
"source": Object {
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"filter": Array [
@ -408,8 +448,8 @@ Array [
},
"sync": Object {
"time": Object {
"delay": "65s",
"field": "event.ingested",
"delay": "125s",
"field": "@timestamp",
},
},
"transform_id": "slo-summary-timeslices-30d-rolling",
@ -425,11 +465,11 @@ Array [
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 4,
"version": 3,
},
"description": "Summarize every SLO with timeslices budgeting method and a 90 days rolling time window",
"dest": Object {
"index": ".slo-observability.summary-v3",
"index": ".slo-observability.summary-v2",
"pipeline": ".slo-observability.summary.pipeline",
},
"frequency": "1m",
@ -470,11 +510,6 @@ Array [
"field": "slo.isGoodSlice",
},
},
"latestSliTimestamp": Object {
"max": Object {
"field": "@timestamp",
},
},
"sliValue": Object {
"bucket_script": Object {
"buckets_path": Object {
@ -530,21 +565,46 @@ Array [
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
@ -574,7 +634,7 @@ Array [
"unattended": true,
},
"source": Object {
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"filter": Array [
@ -617,8 +677,8 @@ Array [
},
"sync": Object {
"time": Object {
"delay": "65s",
"field": "event.ingested",
"delay": "125s",
"field": "@timestamp",
},
},
"transform_id": "slo-summary-timeslices-90d-rolling",
@ -634,11 +694,11 @@ Array [
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 4,
"version": 3,
},
"description": "Summarize every SLO with timeslices budgeting method and a weekly calendar aligned time window",
"dest": Object {
"index": ".slo-observability.summary-v3",
"index": ".slo-observability.summary-v2",
"pipeline": ".slo-observability.summary.pipeline",
},
"frequency": "1m",
@ -694,11 +754,6 @@ Array [
"field": "slo.isGoodSlice",
},
},
"latestSliTimestamp": Object {
"max": Object {
"field": "@timestamp",
},
},
"sliValue": Object {
"bucket_script": Object {
"buckets_path": Object {
@ -752,21 +807,46 @@ Array [
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
@ -796,7 +876,7 @@ Array [
"unattended": true,
},
"source": Object {
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"filter": Array [
@ -839,8 +919,8 @@ Array [
},
"sync": Object {
"time": Object {
"delay": "65s",
"field": "event.ingested",
"delay": "125s",
"field": "@timestamp",
},
},
"transform_id": "slo-summary-timeslices-weekly-aligned",
@ -856,11 +936,11 @@ Array [
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 4,
"version": 3,
},
"description": "Summarize every SLO with timeslices budgeting method and a monthly calendar aligned time window",
"dest": Object {
"index": ".slo-observability.summary-v3",
"index": ".slo-observability.summary-v2",
"pipeline": ".slo-observability.summary.pipeline",
},
"frequency": "1m",
@ -883,7 +963,7 @@ Array [
},
"script": Object {
"source": "
Date d = new Date();
Date d = new Date();
Instant instant = Instant.ofEpochMilli(d.getTime());
LocalDateTime now = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
LocalDateTime startOfMonth = now
@ -893,7 +973,7 @@ Array [
.withSecond(0);
LocalDateTime startOfNextMonth = startOfMonth.plusMonths(1);
double sliceDurationInMinutes = params.sliceDurationInSeconds / 60;
return Math.ceil(Duration.between(startOfMonth, startOfNextMonth).toMinutes() / sliceDurationInMinutes);
",
},
@ -931,11 +1011,6 @@ Array [
"field": "slo.isGoodSlice",
},
},
"latestSliTimestamp": Object {
"max": Object {
"field": "@timestamp",
},
},
"sliValue": Object {
"bucket_script": Object {
"buckets_path": Object {
@ -989,21 +1064,46 @@ Array [
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
@ -1033,7 +1133,7 @@ Array [
"unattended": true,
},
"source": Object {
"index": ".slo-observability.sli-v3*",
"index": ".slo-observability.sli-v2*",
"query": Object {
"bool": Object {
"filter": Array [
@ -1076,8 +1176,8 @@ Array [
},
"sync": Object {
"time": Object {
"delay": "65s",
"field": "event.ingested",
"delay": "125s",
"field": "@timestamp",
},
},
"transform_id": "slo-summary-timeslices-monthly-aligned",

View file

@ -16,11 +16,36 @@ export const groupBy = {
field: 'slo.revision',
},
},
'slo.groupBy': {
terms: {
field: 'slo.groupBy',
},
},
'slo.instanceId': {
terms: {
field: 'slo.instanceId',
},
},
'slo.name': {
terms: {
field: 'slo.name',
},
},
'slo.description': {
terms: {
field: 'slo.description',
},
},
'slo.tags': {
terms: {
field: 'slo.tags',
},
},
'slo.indicator.type': {
terms: {
field: 'slo.indicator.type',
},
},
'slo.budgetingMethod': {
terms: {
field: 'slo.budgetingMethod',

View file

@ -130,11 +130,6 @@ export const SUMMARY_OCCURRENCES_30D_ROLLING: TransformPutTransformRequest = {
},
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -142,8 +137,8 @@ export const SUMMARY_OCCURRENCES_30D_ROLLING: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -130,11 +130,6 @@ export const SUMMARY_OCCURRENCES_7D_ROLLING: TransformPutTransformRequest = {
},
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -142,8 +137,8 @@ export const SUMMARY_OCCURRENCES_7D_ROLLING: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -130,11 +130,6 @@ export const SUMMARY_OCCURRENCES_90D_ROLLING: TransformPutTransformRequest = {
},
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -142,8 +137,8 @@ export const SUMMARY_OCCURRENCES_90D_ROLLING: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -128,11 +128,6 @@ export const SUMMARY_OCCURRENCES_MONTHLY_ALIGNED: TransformPutTransformRequest =
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -140,8 +135,8 @@ export const SUMMARY_OCCURRENCES_MONTHLY_ALIGNED: TransformPutTransformRequest =
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -128,11 +128,6 @@ export const SUMMARY_OCCURRENCES_WEEKLY_ALIGNED: TransformPutTransformRequest =
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -140,8 +135,8 @@ export const SUMMARY_OCCURRENCES_WEEKLY_ALIGNED: TransformPutTransformRequest =
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -130,11 +130,6 @@ export const SUMMARY_TIMESLICES_30D_ROLLING: TransformPutTransformRequest = {
},
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -142,8 +137,8 @@ export const SUMMARY_TIMESLICES_30D_ROLLING: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -130,11 +130,6 @@ export const SUMMARY_TIMESLICES_7D_ROLLING: TransformPutTransformRequest = {
},
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -142,8 +137,8 @@ export const SUMMARY_TIMESLICES_7D_ROLLING: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -130,11 +130,6 @@ export const SUMMARY_TIMESLICES_90D_ROLLING: TransformPutTransformRequest = {
},
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -142,8 +137,8 @@ export const SUMMARY_TIMESLICES_90D_ROLLING: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -78,7 +78,7 @@ export const SUMMARY_TIMESLICES_MONTHLY_ALIGNED: TransformPutTransformRequest =
},
script: {
source: `
Date d = new Date();
Date d = new Date();
Instant instant = Instant.ofEpochMilli(d.getTime());
LocalDateTime now = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
LocalDateTime startOfMonth = now
@ -88,7 +88,7 @@ export const SUMMARY_TIMESLICES_MONTHLY_ALIGNED: TransformPutTransformRequest =
.withSecond(0);
LocalDateTime startOfNextMonth = startOfMonth.plusMonths(1);
double sliceDurationInMinutes = params.sliceDurationInSeconds / 60;
return Math.ceil(Duration.between(startOfMonth, startOfNextMonth).toMinutes() / sliceDurationInMinutes);
`,
},
@ -158,11 +158,6 @@ export const SUMMARY_TIMESLICES_MONTHLY_ALIGNED: TransformPutTransformRequest =
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -170,8 +165,8 @@ export const SUMMARY_TIMESLICES_MONTHLY_ALIGNED: TransformPutTransformRequest =
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -143,11 +143,6 @@ export const SUMMARY_TIMESLICES_WEEKLY_ALIGNED: TransformPutTransformRequest = {
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
},
},
latestSliTimestamp: {
max: {
field: '@timestamp',
},
},
},
},
description:
@ -155,8 +150,8 @@ export const SUMMARY_TIMESLICES_WEEKLY_ALIGNED: TransformPutTransformRequest = {
frequency: '1m',
sync: {
time: {
field: 'event.ingested',
delay: '65s',
field: '@timestamp',
delay: '125s',
},
},
settings: {

View file

@ -190,21 +190,66 @@ Object {
"field": "service.environment",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
}
`;
@ -259,21 +304,66 @@ Object {
"field": "service.name",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
}
`;
@ -323,21 +413,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.name": Object {
"terms": Object {
"field": "transaction.name",
@ -392,21 +527,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.type": Object {
"terms": Object {
"field": "transaction.type",
@ -420,11 +600,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -480,26 +660,71 @@ Object {
"field": "service.name",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.name": Object {
"terms": Object {
"field": "transaction.name",
@ -569,30 +794,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.apm.transactionDuration')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {
@ -610,11 +889,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -661,21 +940,66 @@ Object {
"field": "service.name",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.name": Object {
"terms": Object {
"field": "transaction.name",
@ -745,24 +1069,78 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('occurrences')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.apm.transactionDuration')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.999)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {

View file

@ -178,21 +178,66 @@ Object {
"field": "service.environment",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
}
`;
@ -243,21 +288,66 @@ Object {
"field": "service.name",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
}
`;
@ -303,21 +393,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.name": Object {
"terms": Object {
"field": "transaction.name",
@ -368,21 +503,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.type": Object {
"terms": Object {
"field": "transaction.type",
@ -396,11 +576,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -449,26 +629,71 @@ Object {
"field": "service.name",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.name": Object {
"terms": Object {
"field": "transaction.name",
@ -534,30 +759,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.apm.transactionErrorRate')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {
@ -575,11 +854,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -619,21 +898,66 @@ Object {
"field": "service.name",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
"transaction.name": Object {
"terms": Object {
"field": "transaction.name",
@ -699,24 +1023,78 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('occurrences')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.apm.transactionErrorRate')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.999)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {

View file

@ -77,11 +77,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -151,26 +151,71 @@ Object {
"fixed_interval": "2m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -208,30 +253,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.histogram.custom')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {
@ -249,11 +348,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -314,21 +413,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -366,24 +510,78 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('occurrences')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.histogram.custom')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.999)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {

View file

@ -118,11 +118,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -166,26 +166,71 @@ Object {
"fixed_interval": "2m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -223,30 +268,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.kql.custom')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {
@ -264,11 +363,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -303,21 +402,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -355,24 +499,78 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('occurrences')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.kql.custom')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.999)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {

View file

@ -117,11 +117,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -203,26 +203,71 @@ Object {
"fixed_interval": "2m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -260,30 +305,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.metric.custom')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {
@ -301,11 +400,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -378,21 +477,66 @@ Object {
"fixed_interval": "1m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -430,24 +574,78 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('occurrences')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.metric.custom')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.999)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {

View file

@ -33,11 +33,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -173,26 +173,71 @@ Object {
"fixed_interval": "2m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -227,30 +272,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.metric.timeslice')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {
@ -268,11 +367,11 @@ Object {
"_meta": Object {
"managed": true,
"managed_by": "observability",
"version": 3,
"version": 2,
},
"description": "Rolled-up SLI data for SLO: irrelevant",
"dest": Object {
"index": ".slo-observability.sli-v3",
"index": ".slo-observability.sli-v2",
"pipeline": ".slo-observability.sli.pipeline",
},
"frequency": "1m",
@ -408,26 +507,71 @@ Object {
"fixed_interval": "2m",
},
},
"slo.budgetingMethod": Object {
"terms": Object {
"field": "slo.budgetingMethod",
},
},
"slo.description": Object {
"terms": Object {
"field": "slo.description",
},
},
"slo.groupBy": Object {
"terms": Object {
"field": "slo.groupBy",
},
},
"slo.id": Object {
"terms": Object {
"field": "slo.id",
},
},
"slo.indicator.type": Object {
"terms": Object {
"field": "slo.indicator.type",
},
},
"slo.instanceId": Object {
"terms": Object {
"field": "slo.instanceId",
},
},
"slo.name": Object {
"terms": Object {
"field": "slo.name",
},
},
"slo.objective.sliceDurationInSeconds": Object {
"terms": Object {
"field": "slo.objective.sliceDurationInSeconds",
},
},
"slo.objective.target": Object {
"terms": Object {
"field": "slo.objective.target",
},
},
"slo.revision": Object {
"terms": Object {
"field": "slo.revision",
},
},
"slo.tags": Object {
"terms": Object {
"field": "slo.tags",
},
},
"slo.timeWindow.duration": Object {
"terms": Object {
"field": "slo.timeWindow.duration",
},
},
"slo.timeWindow.type": Object {
"terms": Object {
"field": "slo.timeWindow.type",
},
},
},
},
"settings": Object {
@ -462,30 +606,84 @@ Object {
},
},
"runtime_mappings": Object {
"slo.budgetingMethod": Object {
"script": Object {
"source": "emit('timeslices')",
},
"type": "keyword",
},
"slo.description": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.groupBy": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.id": Object {
"script": Object {
"source": Any<String>,
},
"type": "keyword",
},
"slo.indicator.type": Object {
"script": Object {
"source": "emit('sli.metric.timeslice')",
},
"type": "keyword",
},
"slo.instanceId": Object {
"script": Object {
"source": "emit('*')",
},
"type": "keyword",
},
"slo.name": Object {
"script": Object {
"source": "emit('irrelevant')",
},
"type": "keyword",
},
"slo.objective.sliceDurationInSeconds": Object {
"script": Object {
"source": "emit(120)",
},
"type": "long",
},
"slo.objective.target": Object {
"script": Object {
"source": "emit(0.98)",
},
"type": "double",
},
"slo.revision": Object {
"script": Object {
"source": "emit(1)",
},
"type": "long",
},
"slo.tags": Object {
"script": Object {
"source": "emit('critical,k8s')",
},
"type": "keyword",
},
"slo.timeWindow.duration": Object {
"script": Object {
"source": "emit('7d')",
},
"type": "keyword",
},
"slo.timeWindow.type": Object {
"script": Object {
"source": "emit('rolling')",
},
"type": "keyword",
},
},
},
"sync": Object {

View file

@ -32,6 +32,12 @@ export abstract class TransformGenerator {
source: `emit(${slo.revision})`,
},
},
'slo.groupBy': {
type: 'keyword',
script: {
source: `emit('${!!slo.groupBy ? slo.groupBy : ALL_VALUE}')`,
},
},
...(mustIncludeAllInstanceId && {
'slo.instanceId': {
type: 'keyword',
@ -40,6 +46,36 @@ export abstract class TransformGenerator {
},
},
}),
'slo.name': {
type: 'keyword',
script: {
source: `emit('${slo.name}')`,
},
},
'slo.description': {
type: 'keyword',
script: {
source: `emit('${slo.description}')`,
},
},
'slo.tags': {
type: 'keyword',
script: {
source: `emit('${slo.tags}')`,
},
},
'slo.indicator.type': {
type: 'keyword',
script: {
source: `emit('${slo.indicator.type}')`,
},
},
'slo.objective.target': {
type: 'double',
script: {
source: `emit(${slo.objective.target})`,
},
},
...(slo.objective.timesliceWindow && {
'slo.objective.sliceDurationInSeconds': {
type: 'long',
@ -48,6 +84,24 @@ export abstract class TransformGenerator {
},
},
}),
'slo.budgetingMethod': {
type: 'keyword',
script: {
source: `emit('${slo.budgetingMethod}')`,
},
},
'slo.timeWindow.duration': {
type: 'keyword',
script: {
source: `emit('${slo.timeWindow.duration.format()}')`,
},
},
'slo.timeWindow.type': {
type: 'keyword',
script: {
source: `emit('${slo.timeWindow.type}')`,
},
},
};
}
@ -71,12 +125,21 @@ export abstract class TransformGenerator {
return {
'slo.id': { terms: { field: 'slo.id' } },
'slo.revision': { terms: { field: 'slo.revision' } },
'slo.groupBy': { terms: { field: 'slo.groupBy' } },
'slo.instanceId': { terms: { field: instanceIdField } },
'slo.name': { terms: { field: 'slo.name' } },
'slo.description': { terms: { field: 'slo.description' } },
'slo.tags': { terms: { field: 'slo.tags' } },
'slo.indicator.type': { terms: { field: 'slo.indicator.type' } },
'slo.objective.target': { terms: { field: 'slo.objective.target' } },
...(slo.objective.timesliceWindow && {
'slo.objective.sliceDurationInSeconds': {
terms: { field: 'slo.objective.sliceDurationInSeconds' },
},
}),
'slo.budgetingMethod': { terms: { field: 'slo.budgetingMethod' } },
'slo.timeWindow.duration': { terms: { field: 'slo.timeWindow.duration' } },
'slo.timeWindow.type': { terms: { field: 'slo.timeWindow.type' } },
...extraGroupByFields,
// @timestamp field defined in the destination index
'@timestamp': {

View file

@ -8,7 +8,7 @@
import { ElasticsearchClient } from '@kbn/core/server';
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
import { UpdateSLOParams } from '@kbn/slo-schema';
import { cloneDeep, omit, pick } from 'lodash';
import { cloneDeep, pick, omit } from 'lodash';
import {
getSLOTransformId,
@ -16,14 +16,12 @@ import {
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
} from '../../assets/constants';
import { SLO } from '../../domain/models';
import { fiveMinute, oneMinute, twoMinute } from './fixtures/duration';
import { fiveMinute, oneMinute } from './fixtures/duration';
import {
createAPMTransactionErrorRateIndicator,
createSLO,
createSLOWithTimeslicesBudgetingMethod,
createMetricCustomIndicator,
} from './fixtures/slo';
import { thirtyDaysRolling } from './fixtures/time_window';
import { createSLORepositoryMock, createTransformManagerMock } from './mocks';
import { SLORepository } from './slo_repository';
import { TransformManager } from './transform_manager';
@ -33,23 +31,25 @@ describe('UpdateSLO', () => {
let mockRepository: jest.Mocked<SLORepository>;
let mockTransformManager: jest.Mocked<TransformManager>;
let mockEsClient: jest.Mocked<ElasticsearchClient>;
let mockSystemEsClient: jest.Mocked<ElasticsearchClient>;
let updateSLO: UpdateSLO;
beforeEach(() => {
mockRepository = createSLORepositoryMock();
mockTransformManager = createTransformManagerMock();
mockEsClient = elasticsearchServiceMock.createElasticsearchClient();
mockSystemEsClient = elasticsearchServiceMock.createElasticsearchClient();
updateSLO = new UpdateSLO(
mockRepository,
mockTransformManager,
mockEsClient,
mockSystemEsClient
);
updateSLO = new UpdateSLO(mockRepository, mockTransformManager, mockEsClient);
});
describe('when the update payload does not change the original SLO', () => {
function expectNoCallsToAnyMocks() {
expect(mockTransformManager.stop).not.toBeCalled();
expect(mockTransformManager.uninstall).not.toBeCalled();
expect(mockTransformManager.install).not.toBeCalled();
expect(mockTransformManager.preview).not.toBeCalled();
expect(mockTransformManager.start).not.toBeCalled();
expect(mockEsClient.deleteByQuery).not.toBeCalled();
}
it('returns early with a full identical SLO payload', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
@ -157,14 +157,11 @@ describe('UpdateSLO', () => {
});
});
it("bumps the revision when changing 'settings'", async () => {
it('updates the settings correctly', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const newSettings = {
syncDelay: twoMinute(),
frequency: fiveMinute(),
};
const newSettings = { ...slo.settings, timestamp_field: 'newField' };
await updateSLO.execute(slo.id, { settings: newSettings });
expectDeletionOfOriginalSLO(slo);
@ -172,14 +169,14 @@ describe('UpdateSLO', () => {
expect.objectContaining({
...slo,
settings: newSettings,
revision: slo.revision + 1,
revision: 2,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
it("bumps the revision when changing 'budgetingMethod'", async () => {
it('updates the budgeting method correctly', async () => {
const slo = createSLO({ budgetingMethod: 'occurrences' });
mockRepository.findById.mockResolvedValueOnce(slo);
@ -193,23 +190,10 @@ describe('UpdateSLO', () => {
});
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
budgetingMethod: 'timeslices',
objective: {
target: slo.objective.target,
timesliceTarget: 0.9,
timesliceWindow: oneMinute(),
},
revision: slo.revision + 1,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
it("bumps the revision when changing 'objective.timesliceTarget'", async () => {
it('updates the timeslice target correctly', async () => {
const slo = createSLOWithTimeslicesBudgetingMethod();
mockRepository.findById.mockResolvedValueOnce(slo);
@ -222,22 +206,10 @@ describe('UpdateSLO', () => {
});
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
objective: {
target: slo.objective.target,
timesliceTarget: 0.1,
timesliceWindow: slo.objective.timesliceWindow,
},
revision: slo.revision + 1,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
it("bumps the revision when changing 'objective.timesliceWindow'", async () => {
it('consideres a timeslice window change as a breaking change', async () => {
const slo = createSLOWithTimeslicesBudgetingMethod();
mockRepository.findById.mockResolvedValueOnce(slo);
@ -250,165 +222,41 @@ describe('UpdateSLO', () => {
});
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
objective: {
target: slo.objective.target,
timesliceTarget: slo.objective.timesliceTarget,
timesliceWindow: fiveMinute(),
},
revision: slo.revision + 1,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
it("bumps the revision when changing 'objective'", async () => {
const slo = createSLO();
it('index a temporary summary document', async () => {
const slo = createSLO({
id: 'unique-id',
indicator: createAPMTransactionErrorRateIndicator({ environment: 'development' }),
});
mockRepository.findById.mockResolvedValueOnce(slo);
await updateSLO.execute(slo.id, {
objective: {
target: 0.5,
},
});
const newIndicator = createAPMTransactionErrorRateIndicator({ environment: 'production' });
await updateSLO.execute(slo.id, { indicator: newIndicator });
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
objective: {
target: 0.5,
},
revision: slo.revision + 1,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
expect(mockEsClient.index.mock.calls[0]).toMatchSnapshot();
});
it("bumps the revision when changing 'timeWindow'", async () => {
const slo = createSLO();
it('removes the original data from the original SLO', async () => {
const slo = createSLO({
indicator: createAPMTransactionErrorRateIndicator({ environment: 'development' }),
});
mockRepository.findById.mockResolvedValueOnce(slo);
await updateSLO.execute(slo.id, {
timeWindow: thirtyDaysRolling(),
});
const newIndicator = createAPMTransactionErrorRateIndicator({ environment: 'production' });
await updateSLO.execute(slo.id, { indicator: newIndicator });
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
timeWindow: thirtyDaysRolling(),
revision: slo.revision + 1,
indicator: newIndicator,
revision: 2,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
it("bumps the revision when changing 'groupBy'", async () => {
const slo = createSLO({ groupBy: 'labels.projectId' });
mockRepository.findById.mockResolvedValueOnce(slo);
await updateSLO.execute(slo.id, {
groupBy: '*',
});
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
groupBy: '*',
revision: slo.revision + 1,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
it("bumps the revision when changing 'indicator'", async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
await updateSLO.execute(slo.id, {
indicator: createMetricCustomIndicator(),
});
expectDeletionOfOriginalSLO(slo);
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
indicator: createMetricCustomIndicator(),
revision: slo.revision + 1,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
});
describe('when the revision does not bump', () => {
it('stores the updated SLO', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
await updateSLO.execute(slo.id, {
name: 'a new name',
description: 'a new description',
tags: ['some', 'new tags'],
});
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
name: 'a new name',
description: 'a new description',
tags: ['some', 'new tags'],
revision: slo.revision,
updatedAt: expect.anything(),
})
);
expectNoCallsToAnyMocks();
});
});
describe('when the revision bumps', () => {
it('indexes a temporary summary document', async () => {
const slo = createSLO({
id: 'unique-id',
indicator: createAPMTransactionErrorRateIndicator({ environment: 'development' }),
});
mockRepository.findById.mockResolvedValueOnce(slo);
const newIndicator = createAPMTransactionErrorRateIndicator({ environment: 'production' });
await updateSLO.execute(slo.id, { indicator: newIndicator });
expect(mockEsClient.index.mock.calls[0]).toMatchSnapshot();
expect(mockSystemEsClient.enrich.executePolicy).toBeCalled();
});
it('removes the original data from the original SLO', async () => {
const slo = createSLO({
indicator: createAPMTransactionErrorRateIndicator({ environment: 'development' }),
});
mockRepository.findById.mockResolvedValueOnce(slo);
const newIndicator = createAPMTransactionErrorRateIndicator({ environment: 'production' });
await updateSLO.execute(slo.id, { indicator: newIndicator });
expect(mockRepository.save).toBeCalledWith(
expect.objectContaining({
...slo,
indicator: newIndicator,
revision: 2,
updatedAt: expect.anything(),
})
);
expectInstallationOfNewSLOTransform();
expectDeletionOfOriginalSLO(slo);
});
});
describe('when error happens during the transform installation step', () => {
@ -426,7 +274,6 @@ describe('UpdateSLO', () => {
);
expect(mockRepository.save).toHaveBeenCalledWith(slo);
expect(mockSystemEsClient.enrich.executePolicy).toHaveBeenCalled();
expect(mockTransformManager.preview).not.toHaveBeenCalled();
expect(mockTransformManager.start).not.toHaveBeenCalled();
expect(mockTransformManager.stop).not.toHaveBeenCalled();
@ -453,21 +300,11 @@ describe('UpdateSLO', () => {
getSLOTransformId(slo.id, slo.revision + 1)
);
expect(mockRepository.save).toHaveBeenCalledWith(slo);
expect(mockSystemEsClient.enrich.executePolicy).toHaveBeenCalled();
expect(mockTransformManager.stop).not.toHaveBeenCalled();
expect(mockEsClient.deleteByQuery).not.toHaveBeenCalled();
});
});
function expectNoCallsToAnyMocks() {
expect(mockTransformManager.stop).not.toBeCalled();
expect(mockTransformManager.uninstall).not.toBeCalled();
expect(mockTransformManager.install).not.toBeCalled();
expect(mockTransformManager.preview).not.toBeCalled();
expect(mockTransformManager.start).not.toBeCalled();
expect(mockEsClient.deleteByQuery).not.toBeCalled();
}
function expectInstallationOfNewSLOTransform() {
expect(mockTransformManager.install).toBeCalled();
expect(mockTransformManager.preview).toBeCalled();

View file

@ -7,12 +7,11 @@
import { ElasticsearchClient } from '@kbn/core/server';
import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kbn/slo-schema';
import { isEqual, pick } from 'lodash';
import { isEqual } from 'lodash';
import {
getSLOTransformId,
SLO_DESTINATION_INDEX_PATTERN,
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
SLO_SUMMARY_ENRICH_POLICY_NAME,
SLO_SUMMARY_TEMP_INDEX_NAME,
} from '../../assets/constants';
import { SLO } from '../../domain/models';
@ -25,8 +24,7 @@ export class UpdateSLO {
constructor(
private repository: SLORepository,
private transformManager: TransformManager,
private esClient: ElasticsearchClient,
private systemClient: ElasticsearchClient
private esClient: ElasticsearchClient
) {}
public async execute(sloId: string, params: UpdateSLOParams): Promise<UpdateSLOResponse> {
@ -39,38 +37,23 @@ export class UpdateSLO {
return this.toResponse(originalSlo);
}
const fields = [
'indicator',
'groupBy',
'timeWindow',
'objective',
'budgetingMethod',
'settings',
];
const requireRevisionBump = !isEqual(pick(originalSlo, fields), pick(updatedSlo, fields));
updatedSlo = Object.assign(updatedSlo, {
updatedAt: new Date(),
revision: requireRevisionBump ? originalSlo.revision + 1 : originalSlo.revision,
revision: originalSlo.revision + 1,
});
validateSLO(updatedSlo);
await this.repository.save(updatedSlo);
await this.systemClient.enrich.executePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME });
if (!requireRevisionBump) {
return this.toResponse(updatedSlo);
}
const updatedSloTransformId = getSLOTransformId(updatedSlo.id, updatedSlo.revision);
await this.repository.save(updatedSlo);
try {
await this.transformManager.install(updatedSlo);
} catch (err) {
await this.repository.save(originalSlo);
await this.systemClient.enrich.executePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME });
throw err;
}
const updatedSloTransformId = getSLOTransformId(updatedSlo.id, updatedSlo.revision);
try {
await this.transformManager.preview(updatedSloTransformId);
await this.transformManager.start(updatedSloTransformId);
@ -78,7 +61,6 @@ export class UpdateSLO {
await Promise.all([
this.transformManager.uninstall(updatedSloTransformId),
this.repository.save(originalSlo),
this.systemClient.enrich.executePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME }),
]);
throw err;

View file

@ -6,7 +6,6 @@
*/
import expect from '@kbn/expect';
import { SLO_SUMMARY_ENRICH_POLICY_NAME } from '@kbn/observability-plugin/server/assets/constants';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
@ -24,8 +23,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
before(async () => {
await log.debug('Creating test index');
try {
await es.ingest.deletePipeline({ id: '.slo-*' }, { ignore: [404] });
await es.enrich.deletePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME }, { ignore: [404] });
await es.indices.create({
index: INDEX_NAME,
body: {

View file

@ -6,7 +6,6 @@
*/
import expect from '@kbn/expect';
import { SLO_SUMMARY_ENRICH_POLICY_NAME } from '@kbn/observability-plugin/server/assets/constants';
import { FtrProviderContext } from '../../ftr_provider_context';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
@ -16,7 +15,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
const browser = getService('browser');
const retry = getService('retry');
const security = getService('security');
const es = getService('es');
describe('Home page', function () {
before(async () => {
@ -96,10 +94,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
describe('Enrich policies', () => {
before(async () => {
await es.ingest.deletePipeline({ id: '.slo-*' }, { ignore: [404] });
await es.enrich.deletePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME }, { ignore: [404] });
});
it('renders the enrich policies tab', async () => {
// Navigate to the component templates tab
await pageObjects.indexManagement.changeTabs('enrich_policiesTab');

View file

@ -6,7 +6,6 @@
*/
import expect from '@kbn/expect';
import { SLO_SUMMARY_ENRICH_POLICY_NAME } from '@kbn/observability-plugin/server/assets/constants';
import { FtrProviderContext } from '../../../../ftr_provider_context';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
@ -26,8 +25,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
before(async () => {
log.debug('Creating test index');
try {
await es.ingest.deletePipeline({ id: '.slo-*' }, { ignore: [404] });
await es.enrich.deletePolicy({ name: SLO_SUMMARY_ENRICH_POLICY_NAME }, { ignore: [404] });
await es.indices.create({
index: INDEX_NAME,
body: {