mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.12`: - [feat(slo): new slo architecture (#172224)](https://github.com/elastic/kibana/pull/172224) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Kevin Delemme","email":"kevin.delemme@elastic.co"},"sourceCommit":{"committedDate":"2023-12-12T13:45:12Z","message":"feat(slo): new slo architecture (#172224)","sha":"b51304f3f3c3e8510c44a235d0fc65c44fcce225","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:breaking","backport:prev-minor","ci:build-serverless-image","Feature:SLO","v8.12.0","Team:obs-ux-management","v8.13.0"],"number":172224,"url":"https://github.com/elastic/kibana/pull/172224","mergeCommit":{"message":"feat(slo): new slo architecture (#172224)","sha":"b51304f3f3c3e8510c44a235d0fc65c44fcce225"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/172224","number":172224,"mergeCommit":{"message":"feat(slo): new slo architecture (#172224)","sha":"b51304f3f3c3e8510c44a235d0fc65c44fcce225"}}]}] BACKPORT--> Co-authored-by: Kevin Delemme <kevin.delemme@elastic.co>
This commit is contained in:
parent
2d81cce6af
commit
8ef72a6256
104 changed files with 3702 additions and 5606 deletions
|
@ -721,7 +721,8 @@
|
|||
"indicator.params",
|
||||
"indicator.type",
|
||||
"name",
|
||||
"tags"
|
||||
"tags",
|
||||
"version"
|
||||
],
|
||||
"threshold-explorer-view": [],
|
||||
"observability-onboarding-state": [
|
||||
|
|
|
@ -2379,6 +2379,9 @@
|
|||
},
|
||||
"tags": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"version": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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": "2048ab6791df2e1ae0936f29c20765cb8d2fcfaa",
|
||||
"slo": "9a9995e4572de1839651c43b5fc4dc8276bb5815",
|
||||
"space": "8de4ec513e9bbc6b2f1d635161d850be7747d38e",
|
||||
"spaces-usage-stats": "3abca98713c52af8b30300e386c7779b3025a20e",
|
||||
"synthetics-monitor": "33ddc4b8979f378edf58bcc7ba13c5c5b572f42d",
|
||||
|
|
|
@ -8,3 +8,4 @@
|
|||
export * from './src/schema';
|
||||
export * from './src/rest_specs';
|
||||
export * from './src/models/duration';
|
||||
export * from './src/models/pagination';
|
||||
|
|
17
x-pack/packages/kbn-slo-schema/src/models/pagination.ts
Normal file
17
x-pack/packages/kbn-slo-schema/src/models/pagination.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { toBooleanRt } from '@kbn/io-ts-utils';
|
||||
import {
|
||||
allOrAnyString,
|
||||
apmTransactionDurationIndicatorSchema,
|
||||
|
@ -109,6 +110,7 @@ const sloResponseSchema = t.intersection([
|
|||
groupBy: allOrAnyString,
|
||||
createdAt: dateType,
|
||||
updatedAt: dateType,
|
||||
version: t.number,
|
||||
}),
|
||||
t.partial({
|
||||
instanceId: allOrAnyString,
|
||||
|
@ -157,6 +159,12 @@ 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({
|
||||
|
@ -182,23 +190,21 @@ const fetchHistoricalSummaryResponseSchema = t.array(
|
|||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* The query params schema for /internal/observability/slo/_definitions
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
const findSloDefinitionsParamsSchema = t.type({
|
||||
query: t.type({
|
||||
const findSloDefinitionsParamsSchema = t.partial({
|
||||
query: t.partial({
|
||||
search: t.string,
|
||||
includeOutdatedOnly: toBooleanRt,
|
||||
page: t.string,
|
||||
perPage: t.string,
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* The response schema for /internal/observability/slo/_definitions
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
const findSloDefinitionsResponseSchema = t.array(sloResponseSchema);
|
||||
const findSloDefinitionsResponseSchema = t.type({
|
||||
page: t.number,
|
||||
perPage: t.number,
|
||||
total: t.number,
|
||||
results: t.array(sloResponseSchema),
|
||||
});
|
||||
|
||||
const getSLOBurnRatesResponseSchema = t.type({
|
||||
burnRates: t.array(
|
||||
|
@ -244,6 +250,9 @@ 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>;
|
||||
|
@ -258,12 +267,8 @@ type FetchHistoricalSummaryParams = t.TypeOf<typeof fetchHistoricalSummaryParams
|
|||
type FetchHistoricalSummaryResponse = t.OutputOf<typeof fetchHistoricalSummaryResponseSchema>;
|
||||
type HistoricalSummaryResponse = t.OutputOf<typeof historicalSummarySchema>;
|
||||
|
||||
/**
|
||||
* The response type for /internal/observability/slo/_definitions
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
type FindSloDefinitionsResponse = t.OutputOf<typeof findSloDefinitionsResponseSchema>;
|
||||
type FindSLODefinitionsParams = t.TypeOf<typeof findSloDefinitionsParamsSchema.props.query>;
|
||||
type FindSLODefinitionsResponse = t.OutputOf<typeof findSloDefinitionsResponseSchema>;
|
||||
|
||||
type GetPreviewDataParams = t.TypeOf<typeof getPreviewDataParamsSchema.props.body>;
|
||||
type GetPreviewDataResponse = t.OutputOf<typeof getPreviewDataResponseSchema>;
|
||||
|
@ -300,6 +305,8 @@ export {
|
|||
findSloDefinitionsParamsSchema,
|
||||
findSloDefinitionsResponseSchema,
|
||||
manageSLOParamsSchema,
|
||||
resetSLOParamsSchema,
|
||||
resetSLOResponseSchema,
|
||||
sloResponseSchema,
|
||||
sloWithSummaryResponseSchema,
|
||||
updateSLOParamsSchema,
|
||||
|
@ -325,8 +332,11 @@ export type {
|
|||
FetchHistoricalSummaryParams,
|
||||
FetchHistoricalSummaryResponse,
|
||||
HistoricalSummaryResponse,
|
||||
FindSloDefinitionsResponse,
|
||||
FindSLODefinitionsParams,
|
||||
FindSLODefinitionsResponse,
|
||||
ManageSLOParams,
|
||||
ResetSLOParams,
|
||||
ResetSLOResponse,
|
||||
SLOResponse,
|
||||
SLOWithSummaryResponse,
|
||||
UpdateSLOInput,
|
||||
|
|
|
@ -50,6 +50,7 @@ const sloSchema = t.type({
|
|||
createdAt: dateType,
|
||||
updatedAt: dateType,
|
||||
groupBy: allOrAnyString,
|
||||
version: t.number,
|
||||
});
|
||||
|
||||
const sloWithSummarySchema = t.intersection([sloSchema, t.type({ summary: summarySchema })]);
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"**/*.ts"
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/std"
|
||||
"@kbn/std",
|
||||
"@kbn/io-ts-utils"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -15,11 +15,11 @@ export const journey = new Journey({
|
|||
.step('Go to Transforms', async ({ page, kbnUrl, kibanaPage }) => {
|
||||
await page.goto(kbnUrl.get(`app/management/data/transform`));
|
||||
await kibanaPage.waitForHeader();
|
||||
await page.waitForSelector(subj('transformButtonCreate'));
|
||||
await page.waitForSelector(subj('transformCreateFirstButton'));
|
||||
await page.waitForSelector(subj('globalLoadingIndicator-hidden'));
|
||||
})
|
||||
.step('Go to data view selection', async ({ page }) => {
|
||||
const createButtons = page.locator(subj('transformButtonCreate'));
|
||||
const createButtons = page.locator(subj('transformCreateFirstButton'));
|
||||
await createButtons.first().click();
|
||||
await page.waitForSelector(subj('savedObjectsFinderTable'));
|
||||
})
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export const SLO_RESOURCES_VERSION = 2;
|
||||
export const SLO_SUMMARY_TRANSFORMS_VERSION = 3;
|
||||
export const SLO_MODEL_VERSION = 2;
|
||||
export const SLO_RESOURCES_VERSION = 3;
|
||||
|
||||
export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings';
|
||||
export const SLO_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.sli-settings';
|
||||
|
@ -17,8 +17,7 @@ export const SLO_INDEX_TEMPLATE_PATTERN = `.slo-observability.sli-*`;
|
|||
export const SLO_DESTINATION_INDEX_NAME = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}`;
|
||||
export const SLO_DESTINATION_INDEX_PATTERN = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}*`;
|
||||
|
||||
export const SLO_INGEST_PIPELINE_NAME = `.slo-observability.sli.pipeline`;
|
||||
// slo-observability.sli-v<version>.(YYYY-MM-DD)
|
||||
export const SLO_INGEST_PIPELINE_NAME = `.slo-observability.sli.pipeline-v${SLO_RESOURCES_VERSION}`;
|
||||
export const SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}.`;
|
||||
|
||||
export const SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.summary-mappings';
|
||||
|
@ -26,12 +25,15 @@ export const SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.
|
|||
export const SLO_SUMMARY_INDEX_TEMPLATE_NAME = '.slo-observability.summary';
|
||||
export const SLO_SUMMARY_INDEX_TEMPLATE_PATTERN = `.slo-observability.summary-*`;
|
||||
|
||||
export const SLO_SUMMARY_TRANSFORM_NAME_PREFIX = 'slo-summary-';
|
||||
export const SLO_SUMMARY_DESTINATION_INDEX_NAME = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}`; // store the temporary summary document generated by transform
|
||||
export const SLO_SUMMARY_TEMP_INDEX_NAME = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}.temp`; // store the temporary summary document
|
||||
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 getSLOTransformId = (sloId: string, sloRevision: number) =>
|
||||
`slo-${sloId}-${sloRevision}`;
|
||||
|
||||
export const getSLOSummaryTransformId = (sloId: string, sloRevision: number) =>
|
||||
`slo-summary-${sloId}-${sloRevision}`;
|
||||
|
||||
export const getSLOSummaryPipelineId = (sloId: string, sloRevision: number) =>
|
||||
`.slo-observability.summary.pipeline-${sloId}-${sloRevision}`;
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
{
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"description": "The page number to return",
|
||||
"description": "The page to use for pagination, must be greater or equal than 1",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
|
@ -153,7 +153,7 @@
|
|||
{
|
||||
"name": "perPage",
|
||||
"in": "query",
|
||||
"description": "The number of SLOs to return per page",
|
||||
"description": "Number of SLOs returned by page",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 25,
|
||||
|
@ -280,7 +280,7 @@
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/slo_response"
|
||||
"$ref": "#/components/schemas/slo_with_summary_response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +361,7 @@
|
|||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/slo_response"
|
||||
"$ref": "#/components/schemas/slo_definition_response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -605,6 +605,79 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/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",
|
||||
|
@ -675,6 +748,104 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/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",
|
||||
|
@ -1587,7 +1758,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"slo_response": {
|
||||
"slo_with_summary_response": {
|
||||
"title": "SLO response",
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -1606,7 +1777,8 @@
|
|||
"instanceId",
|
||||
"tags",
|
||||
"createdAt",
|
||||
"updatedAt"
|
||||
"updatedAt",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
|
@ -1708,6 +1880,11 @@
|
|||
"description": "The last update date",
|
||||
"type": "string",
|
||||
"example": "2023-01-12T10:03:19.000Z"
|
||||
},
|
||||
"version": {
|
||||
"description": "The internal SLO version",
|
||||
"type": "number",
|
||||
"example": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1731,7 +1908,7 @@
|
|||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/slo_response"
|
||||
"$ref": "#/components/schemas/slo_with_summary_response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1994,6 +2171,126 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
|
@ -2037,6 +2334,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
|
|
|
@ -86,14 +86,14 @@ paths:
|
|||
example: 'slo.name:latency* and slo.tags : "prod"'
|
||||
- name: page
|
||||
in: query
|
||||
description: The page number to return
|
||||
description: The page to use for pagination, must be greater or equal than 1
|
||||
schema:
|
||||
type: integer
|
||||
default: 1
|
||||
example: 1
|
||||
- name: perPage
|
||||
in: query
|
||||
description: The number of SLOs to return per page
|
||||
description: Number of SLOs returned by page
|
||||
schema:
|
||||
type: integer
|
||||
default: 25
|
||||
|
@ -176,7 +176,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/slo_response'
|
||||
$ref: '#/components/schemas/slo_with_summary_response'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -224,7 +224,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/slo_response'
|
||||
$ref: '#/components/schemas/slo_definition_response'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -365,6 +365,49 @@ 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
|
||||
|
@ -407,6 +450,68 @@ 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
|
||||
|
@ -1103,7 +1208,7 @@ components:
|
|||
example: 0.9836
|
||||
errorBudget:
|
||||
$ref: '#/components/schemas/error_budget'
|
||||
slo_response:
|
||||
slo_with_summary_response:
|
||||
title: SLO response
|
||||
type: object
|
||||
required:
|
||||
|
@ -1123,6 +1228,7 @@ components:
|
|||
- tags
|
||||
- createdAt
|
||||
- updatedAt
|
||||
- version
|
||||
properties:
|
||||
id:
|
||||
description: The identifier of the SLO.
|
||||
|
@ -1192,6 +1298,10 @@ 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: |
|
||||
|
@ -1210,7 +1320,7 @@ components:
|
|||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/slo_response'
|
||||
$ref: '#/components/schemas/slo_with_summary_response'
|
||||
400_response:
|
||||
title: Bad request
|
||||
type: object
|
||||
|
@ -1386,6 +1496,92 @@ 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
|
||||
|
@ -1416,6 +1612,25 @@ 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: |
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
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'
|
|
@ -15,4 +15,4 @@ properties:
|
|||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'slo_response.yaml'
|
||||
$ref: 'slo_with_summary_response.yaml'
|
|
@ -0,0 +1,85 @@
|
|||
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
|
|
@ -17,6 +17,7 @@ required:
|
|||
- tags
|
||||
- createdAt
|
||||
- updatedAt
|
||||
- version
|
||||
properties:
|
||||
id:
|
||||
description: The identifier of the SLO.
|
||||
|
@ -86,3 +87,7 @@ 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
|
|
@ -20,11 +20,15 @@ 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"
|
||||
$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"
|
||||
"/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:
|
||||
|
|
|
@ -68,14 +68,14 @@ get:
|
|||
example: 'slo.name:latency* and slo.tags : "prod"'
|
||||
- name: page
|
||||
in: query
|
||||
description: The page number to return
|
||||
description: The page to use for pagination, must be greater or equal than 1
|
||||
schema:
|
||||
type: integer
|
||||
default: 1
|
||||
example: 1
|
||||
- name: perPage
|
||||
in: query
|
||||
description: The number of SLOs to return per page
|
||||
description: Number of SLOs returned by page
|
||||
schema:
|
||||
type: integer
|
||||
default: 25
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
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'
|
|
@ -22,7 +22,7 @@ get:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../components/schemas/slo_response.yaml'
|
||||
$ref: '../components/schemas/slo_with_summary_response.yaml'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
@ -72,7 +72,7 @@ put:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../components/schemas/slo_response.yaml'
|
||||
$ref: '../components/schemas/slo_definition_response.yaml'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
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'
|
|
@ -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: sloList } = useFetchSloDefinitions({ name: searchValue });
|
||||
const { isLoading, data } = 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 && sloList !== undefined;
|
||||
const isLoadedWithData = !isLoading && !!data?.results;
|
||||
const opts: Array<EuiComboBoxOptionOption<string>> = isLoadedWithData
|
||||
? sloList.map((slo) => ({ value: slo.id, label: slo.name }))
|
||||
? data?.results?.map((slo) => ({ value: slo.id, label: slo.name }))
|
||||
: [];
|
||||
setOptions(opts);
|
||||
}, [isLoading, sloList]);
|
||||
}, [isLoading, data]);
|
||||
|
||||
const onChange = (opts: Array<EuiComboBoxOptionOption<string>>) => {
|
||||
setSelectedOptions(opts);
|
||||
const selectedSlo =
|
||||
opts.length === 1 ? sloList?.find((slo) => slo.id === opts[0].value) : undefined;
|
||||
opts.length === 1 ? data?.results?.find((slo) => slo.id === opts[0].value) : undefined;
|
||||
onSelected(selectedSlo);
|
||||
};
|
||||
|
||||
|
|
|
@ -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 { buildCalendarAlignedTimeWindow, buildRollingTimeWindow } from './time_window';
|
||||
import { buildApmAvailabilityIndicator, buildCustomKqlIndicator } from './indicator';
|
||||
import { buildCalendarAlignedTimeWindow, buildRollingTimeWindow } from './time_window';
|
||||
|
||||
export const emptySloList: FindSLOResponse = {
|
||||
results: [],
|
||||
|
@ -68,6 +68,7 @@ const baseSlo: Omit<SLOWithSummaryResponse, 'id'> = {
|
|||
enabled: true,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
version: 2,
|
||||
};
|
||||
|
||||
export const sloList: FindSLOResponse = {
|
||||
|
|
|
@ -5,24 +5,16 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FindSloDefinitionsResponse, SLOResponse } from '@kbn/slo-schema';
|
||||
import {
|
||||
QueryObserverResult,
|
||||
RefetchOptions,
|
||||
RefetchQueryFilters,
|
||||
useQuery,
|
||||
} from '@tanstack/react-query';
|
||||
import { FindSLODefinitionsResponse } from '@kbn/slo-schema';
|
||||
import { 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 {
|
||||
|
@ -33,18 +25,13 @@ export function useFetchSloDefinitions({ name = '' }: Params): UseFetchSloDefini
|
|||
const { http } = useKibana().services;
|
||||
const search = name.endsWith('*') ? name : `${name}*`;
|
||||
|
||||
const { isLoading, isError, isSuccess, data, refetch } = useQuery({
|
||||
const { isLoading, isError, isSuccess, data } = useQuery({
|
||||
queryKey: sloKeys.definitions(search),
|
||||
queryFn: async ({ signal }) => {
|
||||
try {
|
||||
const response = await http.get<FindSloDefinitionsResponse>(
|
||||
'/internal/observability/slos/_definitions',
|
||||
{
|
||||
query: {
|
||||
search,
|
||||
},
|
||||
signal,
|
||||
}
|
||||
const response = await http.get<FindSLODefinitionsResponse>(
|
||||
'/api/observability/slos/_definitions',
|
||||
{ query: { search }, signal }
|
||||
);
|
||||
|
||||
return response;
|
||||
|
@ -56,5 +43,5 @@ export function useFetchSloDefinitions({ name = '' }: Params): UseFetchSloDefini
|
|||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
return { isLoading, isError, isSuccess, data, refetch };
|
||||
return { isLoading, isError, isSuccess, data };
|
||||
}
|
||||
|
|
|
@ -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')"
|
||||
"/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)"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -257,6 +257,7 @@ describe('SLO Details Page', () => {
|
|||
settings,
|
||||
updatedAt,
|
||||
instanceId,
|
||||
version,
|
||||
...newSlo
|
||||
} = slo;
|
||||
|
||||
|
|
|
@ -12,6 +12,14 @@ 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',
|
||||
|
@ -21,11 +29,9 @@ export const getSLOMappingsTemplate = (name: string) => ({
|
|||
properties: {
|
||||
name: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
environment: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -33,11 +39,9 @@ export const getSLOMappingsTemplate = (name: string) => ({
|
|||
properties: {
|
||||
name: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
type: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -50,56 +54,8 @@ 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: {
|
||||
type: 'double',
|
||||
},
|
||||
sliceDurationInSeconds: {
|
||||
type: 'long',
|
||||
},
|
||||
},
|
||||
},
|
||||
budgetingMethod: {
|
||||
type: 'keyword',
|
||||
},
|
||||
timeWindow: {
|
||||
properties: {
|
||||
duration: {
|
||||
type: 'keyword',
|
||||
},
|
||||
type: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
numerator: {
|
||||
type: 'long',
|
||||
|
@ -110,6 +66,9 @@ export const getSLOMappingsTemplate = (name: string) => ({
|
|||
isGoodSlice: {
|
||||
type: 'byte',
|
||||
},
|
||||
groupings: {
|
||||
type: 'flattened',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -17,11 +17,9 @@ export const getSLOSummaryMappingsTemplate = (name: string) => ({
|
|||
properties: {
|
||||
name: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
environment: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -29,11 +27,9 @@ export const getSLOSummaryMappingsTemplate = (name: string) => ({
|
|||
properties: {
|
||||
name: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
type: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -48,29 +44,49 @@ export const getSLOSummaryMappingsTemplate = (name: string) => ({
|
|||
},
|
||||
groupBy: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
groupings: {
|
||||
type: 'flattened',
|
||||
},
|
||||
instanceId: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
fields: {
|
||||
text: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
name: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
type: 'text',
|
||||
fields: {
|
||||
keyword: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
description: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
type: 'text',
|
||||
},
|
||||
tags: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
indicator: {
|
||||
properties: {
|
||||
type: {
|
||||
type: 'keyword',
|
||||
ignore_above: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
objective: {
|
||||
properties: {
|
||||
target: {
|
||||
type: 'double',
|
||||
},
|
||||
timesliceTarget: {
|
||||
type: 'double',
|
||||
},
|
||||
timesliceWindow: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -115,11 +131,21 @@ export const getSLOSummaryMappingsTemplate = (name: string) => ({
|
|||
},
|
||||
status: {
|
||||
type: 'keyword',
|
||||
ignore_above: 32,
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
},
|
||||
latestSliTimestamp: {
|
||||
type: 'date',
|
||||
format: 'date_optional_time||epoch_millis',
|
||||
},
|
||||
summaryUpdatedAt: {
|
||||
type: 'date',
|
||||
format: 'date_optional_time||epoch_millis',
|
||||
},
|
||||
spaceId: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -9,18 +9,25 @@ import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants';
|
|||
|
||||
export const getSLOPipelineTemplate = (id: string, indexNamePrefix: string) => ({
|
||||
id,
|
||||
description: 'Monthly date-time index naming for SLO data',
|
||||
description: 'Ingest pipeline for SLO rollup data',
|
||||
processors: [
|
||||
{
|
||||
set: {
|
||||
field: 'event.ingested',
|
||||
value: '{{{_ingest.timestamp}}}',
|
||||
},
|
||||
},
|
||||
{
|
||||
date_index_name: {
|
||||
field: '@timestamp',
|
||||
index_name_prefix: indexNamePrefix,
|
||||
date_rounding: 'M',
|
||||
date_formats: ['UNIX_MS', 'ISO8601', "yyyy-MM-dd'T'HH:mm:ss.SSSXX"],
|
||||
},
|
||||
},
|
||||
],
|
||||
_meta: {
|
||||
description: 'SLO ingest pipeline',
|
||||
description: 'Ingest pipeline for SLO rollup data',
|
||||
version: SLO_RESOURCES_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
|
|
|
@ -5,56 +5,167 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SLO_RESOURCES_VERSION } from '../../../common/slo/constants';
|
||||
import { timeslicesBudgetingMethodSchema } from '@kbn/slo-schema';
|
||||
import { getSLOSummaryPipelineId, SLO_RESOURCES_VERSION } from '../../../common/slo/constants';
|
||||
import { SLO } from '../../domain/models';
|
||||
|
||||
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: ',',
|
||||
export const getSLOSummaryPipelineTemplate = (slo: SLO, spaceId: string) => {
|
||||
const errorBudgetEstimated =
|
||||
slo.budgetingMethod === 'occurrences' && slo.timeWindow.type === 'calendarAligned';
|
||||
|
||||
const optionalObjectiveTimesliceProcessors = timeslicesBudgetingMethodSchema.is(
|
||||
slo.budgetingMethod
|
||||
)
|
||||
? [
|
||||
{
|
||||
set: {
|
||||
description: 'Set objective.timesliceTarget field',
|
||||
field: 'slo.objective.timesliceTarget',
|
||||
value: slo.objective.timesliceTarget,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set objective.timesliceWindow field',
|
||||
field: 'slo.objective.timesliceWindow',
|
||||
value: slo.objective.timesliceWindow!.format(),
|
||||
},
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
return {
|
||||
id: getSLOSummaryPipelineId(slo.id, slo.revision),
|
||||
description: `Ingest pipeline for SLO summary data [id: ${slo.id}, revision: ${slo.revision}]`,
|
||||
processors: [
|
||||
{
|
||||
set: {
|
||||
description: 'Set errorBudgetEstimated field',
|
||||
field: 'errorBudgetEstimated',
|
||||
value: errorBudgetEstimated,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 0', set status to NO_DATA",
|
||||
if: 'ctx.statusCode == 0',
|
||||
field: 'status',
|
||||
value: 'NO_DATA',
|
||||
{
|
||||
set: {
|
||||
description: 'Set isTempDoc field',
|
||||
field: 'isTempDoc',
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 1', set statusLabel to VIOLATED",
|
||||
if: 'ctx.statusCode == 1',
|
||||
field: 'status',
|
||||
value: 'VIOLATED',
|
||||
{
|
||||
set: {
|
||||
description: 'Set groupBy field',
|
||||
field: 'slo.groupBy',
|
||||
value: slo.groupBy,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 2', set status to DEGRADING",
|
||||
if: 'ctx.statusCode == 2',
|
||||
field: 'status',
|
||||
value: 'DEGRADING',
|
||||
{
|
||||
set: {
|
||||
description: 'Set name field',
|
||||
field: 'slo.name',
|
||||
value: slo.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 4', set status to HEALTHY",
|
||||
if: 'ctx.statusCode == 4',
|
||||
field: 'status',
|
||||
value: 'HEALTHY',
|
||||
{
|
||||
set: {
|
||||
description: 'Set description field',
|
||||
field: 'slo.description',
|
||||
value: slo.description,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set tags field',
|
||||
field: 'slo.tags',
|
||||
value: slo.tags,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set indicator.type field',
|
||||
field: 'slo.indicator.type',
|
||||
value: slo.indicator.type,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set budgetingMethod field',
|
||||
field: 'slo.budgetingMethod',
|
||||
value: slo.budgetingMethod,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set timeWindow.duration field',
|
||||
field: 'slo.timeWindow.duration',
|
||||
value: slo.timeWindow.duration.format(),
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set timeWindow.type field',
|
||||
field: 'slo.timeWindow.type',
|
||||
value: slo.timeWindow.type,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: 'Set objective.target field',
|
||||
field: 'slo.objective.target',
|
||||
value: slo.objective.target,
|
||||
},
|
||||
},
|
||||
...optionalObjectiveTimesliceProcessors,
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 0', set status to NO_DATA",
|
||||
if: 'ctx.statusCode == 0',
|
||||
field: 'status',
|
||||
value: 'NO_DATA',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 1', set statusLabel to VIOLATED",
|
||||
if: 'ctx.statusCode == 1',
|
||||
field: 'status',
|
||||
value: 'VIOLATED',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 2', set status to DEGRADING",
|
||||
if: 'ctx.statusCode == 2',
|
||||
field: 'status',
|
||||
value: 'DEGRADING',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
description: "if 'statusCode == 4', set status to HEALTHY",
|
||||
if: 'ctx.statusCode == 4',
|
||||
field: 'status',
|
||||
value: 'HEALTHY',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'summaryUpdatedAt',
|
||||
value: '{{{_ingest.timestamp}}}',
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'spaceId',
|
||||
value: spaceId,
|
||||
},
|
||||
},
|
||||
],
|
||||
_meta: {
|
||||
description: `Ingest pipeline for SLO summary data [id: ${slo.id}, revision: ${slo.revision}]`,
|
||||
version: SLO_RESOURCES_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
],
|
||||
_meta: {
|
||||
description: 'SLO summary ingest pipeline',
|
||||
version: SLO_RESOURCES_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -18,21 +18,21 @@ import {
|
|||
Plugin,
|
||||
PluginInitializerContext,
|
||||
} from '@kbn/core/server';
|
||||
import { LOG_EXPLORER_LOCATOR_ID, LogExplorerLocatorParams } from '@kbn/deeplinks-observability';
|
||||
import { LogExplorerLocatorParams, LOG_EXPLORER_LOCATOR_ID } from '@kbn/deeplinks-observability';
|
||||
import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server';
|
||||
import { hiddenTypes as filesSavedObjectTypes } from '@kbn/files-plugin/server/saved_objects';
|
||||
import type { GuidedOnboardingPluginSetup } from '@kbn/guided-onboarding-plugin/server';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server';
|
||||
import { SharePluginSetup } from '@kbn/share-plugin/server';
|
||||
import { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
|
||||
import {
|
||||
ApmRuleType,
|
||||
ES_QUERY_ID,
|
||||
METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID,
|
||||
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
|
||||
} from '@kbn/rule-data-utils';
|
||||
import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server';
|
||||
import { SharePluginSetup } from '@kbn/share-plugin/server';
|
||||
import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server';
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
|
||||
import { ObservabilityConfig } from '.';
|
||||
import { casesFeatureId, observabilityFeatureId, sloFeatureId } from '../common';
|
||||
import { SLO_BURN_RATE_RULE_TYPE_ID } from '../common/constants';
|
||||
|
@ -52,11 +52,7 @@ import { getObservabilityServerRouteRepository } from './routes/get_global_obser
|
|||
import { registerRoutes } from './routes/register_routes';
|
||||
import { slo, SO_SLO_TYPE } from './saved_objects';
|
||||
import { threshold } from './saved_objects/threshold';
|
||||
import {
|
||||
DefaultResourceInstaller,
|
||||
DefaultSLOInstaller,
|
||||
DefaultSummaryTransformInstaller,
|
||||
} from './services/slo';
|
||||
import { DefaultResourceInstaller, DefaultSLOInstaller } from './services/slo';
|
||||
|
||||
import { uiSettings } from './ui_settings';
|
||||
|
||||
|
@ -75,6 +71,7 @@ interface PluginSetup {
|
|||
|
||||
interface PluginStart {
|
||||
alerting: PluginStartContract;
|
||||
spaces?: SpacesPluginStart;
|
||||
}
|
||||
|
||||
const sloRuleTypes = [SLO_BURN_RATE_RULE_TYPE_ID];
|
||||
|
@ -350,6 +347,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
...plugins,
|
||||
core,
|
||||
},
|
||||
spaces: pluginStart.spaces,
|
||||
ruleDataService,
|
||||
getRulesClientWithRequest: pluginStart.alerting.getRulesClientWithRequest,
|
||||
},
|
||||
|
@ -360,15 +358,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
const esInternalClient = coreStart.elasticsearch.client.asInternalUser;
|
||||
|
||||
const sloResourceInstaller = new DefaultResourceInstaller(esInternalClient, this.logger);
|
||||
const sloSummaryInstaller = new DefaultSummaryTransformInstaller(
|
||||
esInternalClient,
|
||||
this.logger
|
||||
);
|
||||
const sloInstaller = new DefaultSLOInstaller(
|
||||
sloResourceInstaller,
|
||||
sloSummaryInstaller,
|
||||
this.logger
|
||||
);
|
||||
const sloInstaller = new DefaultSLOInstaller(sloResourceInstaller, this.logger);
|
||||
sloInstaller.install();
|
||||
});
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
parseEndpoint,
|
||||
routeValidationObject,
|
||||
} from '@kbn/server-route-repository';
|
||||
import { SpacesPluginStart } from '@kbn/spaces-plugin/server';
|
||||
import axios from 'axios';
|
||||
import * as t from 'io-ts';
|
||||
import { ObservabilityConfig } from '..';
|
||||
|
@ -33,6 +34,7 @@ export interface RegisterRoutesDependencies {
|
|||
pluginsSetup: {
|
||||
core: CoreSetup;
|
||||
};
|
||||
spaces?: SpacesPluginStart;
|
||||
ruleDataService: RuleDataPluginService;
|
||||
getRulesClientWithRequest: (request: KibanaRequest) => RulesClientApi;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,14 @@ import {
|
|||
getSLOInstancesParamsSchema,
|
||||
getSLOParamsSchema,
|
||||
manageSLOParamsSchema,
|
||||
resetSLOParamsSchema,
|
||||
updateSLOParamsSchema,
|
||||
} from '@kbn/slo-schema';
|
||||
import type { IndicatorTypes } from '../../domain/models';
|
||||
import {
|
||||
CreateSLO,
|
||||
DefaultSummaryClient,
|
||||
DefaultSummaryTransformManager,
|
||||
DefaultTransformManager,
|
||||
DeleteSLO,
|
||||
DeleteSLOInstances,
|
||||
|
@ -41,15 +43,17 @@ import { GetPreviewData } from '../../services/slo/get_preview_data';
|
|||
import { GetSLOInstances } from '../../services/slo/get_slo_instances';
|
||||
import { DefaultHistoricalSummaryClient } from '../../services/slo/historical_summary_client';
|
||||
import { ManageSLO } from '../../services/slo/manage_slo';
|
||||
import { ResetSLO } from '../../services/slo/reset_slo';
|
||||
import { DefaultSummarySearchClient } from '../../services/slo/summary_search_client';
|
||||
import { DefaultSummaryTransformGenerator } from '../../services/slo/summary_transform_generator/summary_transform_generator';
|
||||
import {
|
||||
ApmTransactionDurationTransformGenerator,
|
||||
ApmTransactionErrorRateTransformGenerator,
|
||||
HistogramTransformGenerator,
|
||||
KQLCustomTransformGenerator,
|
||||
MetricCustomTransformGenerator,
|
||||
TransformGenerator,
|
||||
TimesliceMetricTransformGenerator,
|
||||
TransformGenerator,
|
||||
} from '../../services/slo/transform_generators';
|
||||
import type { ObservabilityRequestHandlerContext } from '../../types';
|
||||
import { createObservabilityServerRoute } from '../create_observability_server_route';
|
||||
|
@ -79,14 +83,30 @@ const createSLORoute = createObservabilityServerRoute({
|
|||
access: 'public',
|
||||
},
|
||||
params: createSLOParamsSchema,
|
||||
handler: async ({ context, params, logger }) => {
|
||||
handler: async ({ context, params, logger, dependencies, request }) => {
|
||||
await assertPlatinumLicense(context);
|
||||
|
||||
const spaceId =
|
||||
(await dependencies.spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default';
|
||||
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
|
||||
const createSLO = new CreateSLO(esClient, repository, transformManager);
|
||||
const summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const createSLO = new CreateSLO(
|
||||
esClient,
|
||||
repository,
|
||||
transformManager,
|
||||
summaryTransformManager,
|
||||
logger,
|
||||
spaceId
|
||||
);
|
||||
|
||||
const response = await createSLO.execute(params.body);
|
||||
|
||||
|
@ -101,15 +121,30 @@ const updateSLORoute = createObservabilityServerRoute({
|
|||
access: 'public',
|
||||
},
|
||||
params: updateSLOParamsSchema,
|
||||
handler: async ({ context, params, logger }) => {
|
||||
handler: async ({ context, request, params, logger, dependencies }) => {
|
||||
await assertPlatinumLicense(context);
|
||||
|
||||
const spaceId =
|
||||
(await dependencies.spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default';
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
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);
|
||||
const summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const updateSLO = new UpdateSLO(
|
||||
repository,
|
||||
transformManager,
|
||||
summaryTransformManager,
|
||||
esClient,
|
||||
logger,
|
||||
spaceId
|
||||
);
|
||||
|
||||
const response = await updateSLO.execute(params.path.id, params.body);
|
||||
|
||||
|
@ -140,7 +175,19 @@ const deleteSLORoute = createObservabilityServerRoute({
|
|||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
|
||||
|
||||
const deleteSLO = new DeleteSLO(repository, transformManager, esClient, rulesClient);
|
||||
const summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const deleteSLO = new DeleteSLO(
|
||||
repository,
|
||||
transformManager,
|
||||
summaryTransformManager,
|
||||
esClient,
|
||||
rulesClient
|
||||
);
|
||||
|
||||
await deleteSLO.execute(params.path.id);
|
||||
},
|
||||
|
@ -183,7 +230,13 @@ const enableSLORoute = createObservabilityServerRoute({
|
|||
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
|
||||
const manageSLO = new ManageSLO(repository, transformManager);
|
||||
const summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const manageSLO = new ManageSLO(repository, transformManager, summaryTransformManager);
|
||||
|
||||
const response = await manageSLO.enable(params.path.id);
|
||||
|
||||
|
@ -206,7 +259,13 @@ const disableSLORoute = createObservabilityServerRoute({
|
|||
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
|
||||
const manageSLO = new ManageSLO(repository, transformManager);
|
||||
const summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const manageSLO = new ManageSLO(repository, transformManager, summaryTransformManager);
|
||||
|
||||
const response = await manageSLO.disable(params.path.id);
|
||||
|
||||
|
@ -214,6 +273,44 @@ 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, request, params, logger, dependencies }) => {
|
||||
await assertPlatinumLicense(context);
|
||||
|
||||
const spaceId =
|
||||
(await dependencies.spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default';
|
||||
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 summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const resetSLO = new ResetSLO(
|
||||
esClient,
|
||||
repository,
|
||||
transformManager,
|
||||
summaryTransformManager,
|
||||
logger,
|
||||
spaceId
|
||||
);
|
||||
|
||||
const response = await resetSLO.execute(params.path.id);
|
||||
|
||||
return response;
|
||||
},
|
||||
});
|
||||
|
||||
const findSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'GET /api/observability/slos 2023-10-31',
|
||||
options: {
|
||||
|
@ -221,13 +318,16 @@ const findSLORoute = createObservabilityServerRoute({
|
|||
access: 'public',
|
||||
},
|
||||
params: findSLOParamsSchema,
|
||||
handler: async ({ context, params, logger }) => {
|
||||
handler: async ({ context, request, params, logger, dependencies }) => {
|
||||
await assertPlatinumLicense(context);
|
||||
|
||||
const spaceId =
|
||||
(await dependencies.spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default';
|
||||
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const summarySearchClient = new DefaultSummarySearchClient(esClient, logger);
|
||||
const summarySearchClient = new DefaultSummarySearchClient(esClient, logger, spaceId);
|
||||
const findSLO = new FindSLO(repository, summarySearchClient);
|
||||
|
||||
const response = await findSLO.execute(params?.query ?? {});
|
||||
|
@ -253,10 +353,9 @@ const deleteSloInstancesRoute = createObservabilityServerRoute({
|
|||
});
|
||||
|
||||
const findSloDefinitionsRoute = createObservabilityServerRoute({
|
||||
endpoint: 'GET /internal/observability/slos/_definitions',
|
||||
endpoint: 'GET /api/observability/slos/_definitions 2023-10-31',
|
||||
options: {
|
||||
tags: ['access:slo_read'],
|
||||
access: 'internal',
|
||||
},
|
||||
params: findSloDefinitionsParamsSchema,
|
||||
handler: async ({ context, params }) => {
|
||||
|
@ -266,7 +365,7 @@ const findSloDefinitionsRoute = createObservabilityServerRoute({
|
|||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const findSloDefinitions = new FindSLODefinitions(repository);
|
||||
|
||||
const response = await findSloDefinitions.execute(params.query.search);
|
||||
const response = await findSloDefinitions.execute(params?.query ?? {});
|
||||
|
||||
return response;
|
||||
},
|
||||
|
@ -395,4 +494,5 @@ export const sloRouteRepository = {
|
|||
...getSloBurnRates,
|
||||
...getPreviewData,
|
||||
...getSLOInstancesRoute,
|
||||
...resetSLORoute,
|
||||
};
|
||||
|
|
|
@ -17,7 +17,6 @@ type StoredSLOBefore890 = StoredSLO & {
|
|||
isCalendar?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
const migrateSlo890: SavedObjectMigrationFn<StoredSLOBefore890, StoredSLO> = (doc) => {
|
||||
const { timeWindow, ...other } = doc.attributes;
|
||||
return {
|
||||
|
@ -38,6 +37,21 @@ 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: {
|
||||
|
@ -53,6 +67,7 @@ export const slo: SavedObjectsType = {
|
|||
budgetingMethod: { type: 'keyword' },
|
||||
enabled: { type: 'boolean' },
|
||||
tags: { type: 'keyword' },
|
||||
version: { type: 'long' },
|
||||
},
|
||||
},
|
||||
management: {
|
||||
|
|
|
@ -1,6 +1,144 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CreateSLO happy path calls the expected services 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"_meta": Object {
|
||||
"description": "Ingest pipeline for SLO summary data [id: unique-id, revision: 1]",
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Ingest pipeline for SLO summary data [id: unique-id, revision: 1]",
|
||||
"id": ".slo-observability.summary.pipeline-unique-id-1",
|
||||
"processors": Array [
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set errorBudgetEstimated field",
|
||||
"field": "errorBudgetEstimated",
|
||||
"value": false,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set isTempDoc field",
|
||||
"field": "isTempDoc",
|
||||
"value": false,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set groupBy field",
|
||||
"field": "slo.groupBy",
|
||||
"value": "*",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set name field",
|
||||
"field": "slo.name",
|
||||
"value": "irrelevant",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set description field",
|
||||
"field": "slo.description",
|
||||
"value": "irrelevant",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set tags field",
|
||||
"field": "slo.tags",
|
||||
"value": Array [],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set indicator.type field",
|
||||
"field": "slo.indicator.type",
|
||||
"value": "sli.apm.transactionErrorRate",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set budgetingMethod field",
|
||||
"field": "slo.budgetingMethod",
|
||||
"value": "occurrences",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set timeWindow.duration field",
|
||||
"field": "slo.timeWindow.duration",
|
||||
"value": "7d",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set timeWindow.type field",
|
||||
"field": "slo.timeWindow.type",
|
||||
"value": "rolling",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set objective.target field",
|
||||
"field": "slo.objective.target",
|
||||
"value": 0.99,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 0', set status to NO_DATA",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 0",
|
||||
"value": "NO_DATA",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 1', set statusLabel to VIOLATED",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 1",
|
||||
"value": "VIOLATED",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 2', set status to DEGRADING",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 2",
|
||||
"value": "DEGRADING",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 4', set status to HEALTHY",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 4",
|
||||
"value": "HEALTHY",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"field": "summaryUpdatedAt",
|
||||
"value": "{{{_ingest.timestamp}}}",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"field": "spaceId",
|
||||
"value": "some-space",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`CreateSLO happy path calls the expected services 2`] = `
|
||||
Array [
|
||||
Object {
|
||||
"document": Object {
|
||||
|
@ -25,6 +163,11 @@ Array [
|
|||
},
|
||||
"instanceId": "*",
|
||||
"name": "irrelevant",
|
||||
"objective": Object {
|
||||
"target": 0.99,
|
||||
"timesliceTarget": null,
|
||||
"timesliceWindow": null,
|
||||
},
|
||||
"revision": 1,
|
||||
"tags": Array [],
|
||||
"timeWindow": Object {
|
||||
|
@ -32,6 +175,7 @@ Array [
|
|||
"type": "rolling",
|
||||
},
|
||||
},
|
||||
"spaceId": "some-space",
|
||||
"status": "NO_DATA",
|
||||
"statusCode": 0,
|
||||
"totalEvents": 0,
|
||||
|
@ -41,7 +185,7 @@ Array [
|
|||
},
|
||||
},
|
||||
"id": "slo-unique-id",
|
||||
"index": ".slo-observability.summary-v2.temp",
|
||||
"index": ".slo-observability.summary-v3.temp",
|
||||
"refresh": true,
|
||||
},
|
||||
]
|
||||
|
|
177
x-pack/plugins/observability/server/services/slo/__snapshots__/delete_slo.test.ts.snap
generated
Normal file
177
x-pack/plugins/observability/server/services/slo/__snapshots__/delete_slo.test.ts.snap
generated
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"irrelevant",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 2`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 3`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 4`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 5`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 6`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"id": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
},
|
||||
Object {
|
||||
"ignore": Array [
|
||||
404,
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 7`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"index": ".slo-observability.sli-v3*",
|
||||
"query": Object {
|
||||
"match": Object {
|
||||
"slo.id": "irrelevant",
|
||||
},
|
||||
},
|
||||
"wait_for_completion": false,
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"index": ".slo-observability.summary-v3*",
|
||||
"query": Object {
|
||||
"match": Object {
|
||||
"slo.id": "irrelevant",
|
||||
},
|
||||
},
|
||||
"refresh": true,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 8`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"filter": "alert.attributes.params.sloId:irrelevant",
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`DeleteSLO happy path removes all resources associatde to the slo 9`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"irrelevant",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
|
@ -11,7 +11,7 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": ".slo-observability.sli-v2*",
|
||||
"index": ".slo-observability.sli-v3*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
|
65
x-pack/plugins/observability/server/services/slo/__snapshots__/manage_slo.test.ts.snap
generated
Normal file
65
x-pack/plugins/observability/server/services/slo/__snapshots__/manage_slo.test.ts.snap
generated
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ManageSLO Disable disables the slo when enabled 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ManageSLO Disable disables the slo when enabled 2`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ManageSLO Enable enables the slo when disabled 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ManageSLO Enable enables the slo when disabled 2`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
489
x-pack/plugins/observability/server/services/slo/__snapshots__/reset_slo.test.ts.snap
generated
Normal file
489
x-pack/plugins/observability/server/services/slo/__snapshots__/reset_slo.test.ts.snap
generated
Normal file
|
@ -0,0 +1,489 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ResetSLO resets all associated resources 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 2`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 3`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 4`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 5`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"index": ".slo-observability.sli-v3*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"slo.id": "irrelevant",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"refresh": true,
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"index": ".slo-observability.summary-v3*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"slo.id": "irrelevant",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"refresh": true,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 6`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2023-01-01T00:00:00.000Z,
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
"id": "irrelevant",
|
||||
"indicator": Object {
|
||||
"params": Object {
|
||||
"environment": "irrelevant",
|
||||
"index": "metrics-apm*",
|
||||
"service": "irrelevant",
|
||||
"threshold": 500,
|
||||
"transactionName": "irrelevant",
|
||||
"transactionType": "irrelevant",
|
||||
},
|
||||
"type": "sli.apm.transactionDuration",
|
||||
},
|
||||
"name": "irrelevant",
|
||||
"objective": Object {
|
||||
"target": 0.999,
|
||||
},
|
||||
"revision": 1,
|
||||
"settings": Object {
|
||||
"frequency": Duration {
|
||||
"unit": "m",
|
||||
"value": 1,
|
||||
},
|
||||
"syncDelay": Duration {
|
||||
"unit": "m",
|
||||
"value": 1,
|
||||
},
|
||||
},
|
||||
"tags": Array [
|
||||
"critical",
|
||||
"k8s",
|
||||
],
|
||||
"timeWindow": Object {
|
||||
"duration": Duration {
|
||||
"unit": "d",
|
||||
"value": 7,
|
||||
},
|
||||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2023-01-01T00:00:00.000Z,
|
||||
"version": 1,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 7`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 8`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"_meta": Object {
|
||||
"description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]",
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]",
|
||||
"id": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
"processors": Array [
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set errorBudgetEstimated field",
|
||||
"field": "errorBudgetEstimated",
|
||||
"value": false,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set isTempDoc field",
|
||||
"field": "isTempDoc",
|
||||
"value": false,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set groupBy field",
|
||||
"field": "slo.groupBy",
|
||||
"value": "*",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set name field",
|
||||
"field": "slo.name",
|
||||
"value": "irrelevant",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set description field",
|
||||
"field": "slo.description",
|
||||
"value": "irrelevant",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set tags field",
|
||||
"field": "slo.tags",
|
||||
"value": Array [
|
||||
"critical",
|
||||
"k8s",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set indicator.type field",
|
||||
"field": "slo.indicator.type",
|
||||
"value": "sli.apm.transactionDuration",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set budgetingMethod field",
|
||||
"field": "slo.budgetingMethod",
|
||||
"value": "occurrences",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set timeWindow.duration field",
|
||||
"field": "slo.timeWindow.duration",
|
||||
"value": "7d",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set timeWindow.type field",
|
||||
"field": "slo.timeWindow.type",
|
||||
"value": "rolling",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "Set objective.target field",
|
||||
"field": "slo.objective.target",
|
||||
"value": 0.999,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 0', set status to NO_DATA",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 0",
|
||||
"value": "NO_DATA",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 1', set statusLabel to VIOLATED",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 1",
|
||||
"value": "VIOLATED",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 2', set status to DEGRADING",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 2",
|
||||
"value": "DEGRADING",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"description": "if 'statusCode == 4', set status to HEALTHY",
|
||||
"field": "status",
|
||||
"if": "ctx.statusCode == 4",
|
||||
"value": "HEALTHY",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"field": "summaryUpdatedAt",
|
||||
"value": "{{{_ingest.timestamp}}}",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"field": "spaceId",
|
||||
"value": "some-space",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 9`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2023-01-01T00:00:00.000Z,
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
"id": "irrelevant",
|
||||
"indicator": Object {
|
||||
"params": Object {
|
||||
"environment": "irrelevant",
|
||||
"index": "metrics-apm*",
|
||||
"service": "irrelevant",
|
||||
"threshold": 500,
|
||||
"transactionName": "irrelevant",
|
||||
"transactionType": "irrelevant",
|
||||
},
|
||||
"type": "sli.apm.transactionDuration",
|
||||
},
|
||||
"name": "irrelevant",
|
||||
"objective": Object {
|
||||
"target": 0.999,
|
||||
},
|
||||
"revision": 1,
|
||||
"settings": Object {
|
||||
"frequency": Duration {
|
||||
"unit": "m",
|
||||
"value": 1,
|
||||
},
|
||||
"syncDelay": Duration {
|
||||
"unit": "m",
|
||||
"value": 1,
|
||||
},
|
||||
},
|
||||
"tags": Array [
|
||||
"critical",
|
||||
"k8s",
|
||||
],
|
||||
"timeWindow": Object {
|
||||
"duration": Duration {
|
||||
"unit": "d",
|
||||
"value": 7,
|
||||
},
|
||||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2023-01-01T00:00:00.000Z,
|
||||
"version": 1,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 10`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-irrelevant-1",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ResetSLO resets all associated resources 11`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"document": Object {
|
||||
"errorBudgetConsumed": 0,
|
||||
"errorBudgetEstimated": false,
|
||||
"errorBudgetInitial": 0.0010000000000000009,
|
||||
"errorBudgetRemaining": 1,
|
||||
"goodEvents": 0,
|
||||
"isTempDoc": true,
|
||||
"service": Object {
|
||||
"environment": null,
|
||||
"name": null,
|
||||
},
|
||||
"sliValue": -1,
|
||||
"slo": Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"description": "irrelevant",
|
||||
"groupBy": "*",
|
||||
"id": "irrelevant",
|
||||
"indicator": Object {
|
||||
"type": "sli.apm.transactionDuration",
|
||||
},
|
||||
"instanceId": "*",
|
||||
"name": "irrelevant",
|
||||
"objective": Object {
|
||||
"target": 0.999,
|
||||
"timesliceTarget": null,
|
||||
"timesliceWindow": null,
|
||||
},
|
||||
"revision": 1,
|
||||
"tags": Array [
|
||||
"critical",
|
||||
"k8s",
|
||||
],
|
||||
"timeWindow": Object {
|
||||
"duration": "7d",
|
||||
"type": "rolling",
|
||||
},
|
||||
},
|
||||
"spaceId": "some-space",
|
||||
"status": "NO_DATA",
|
||||
"statusCode": 0,
|
||||
"totalEvents": 0,
|
||||
"transaction": Object {
|
||||
"name": null,
|
||||
"type": null,
|
||||
},
|
||||
},
|
||||
"id": "slo-irrelevant",
|
||||
"index": ".slo-observability.summary-v3.temp",
|
||||
"refresh": true,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
|
@ -3,7 +3,7 @@
|
|||
exports[`Summary Search Client returns the summary documents without duplicate temporary summary documents 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"index": ".slo-observability.summary-v2*",
|
||||
"index": ".slo-observability.summary-v3*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
|
|
@ -1,51 +1,88 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`UpdateSLO index a temporary summary document 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"document": Object {
|
||||
"errorBudgetConsumed": 0,
|
||||
"errorBudgetEstimated": false,
|
||||
"errorBudgetInitial": 0.0010000000000000009,
|
||||
"errorBudgetRemaining": 1,
|
||||
"goodEvents": 0,
|
||||
"isTempDoc": true,
|
||||
"service": Object {
|
||||
"environment": null,
|
||||
"name": null,
|
||||
},
|
||||
"sliValue": -1,
|
||||
"slo": Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"description": "irrelevant",
|
||||
"groupBy": "*",
|
||||
"id": "unique-id",
|
||||
"indicator": Object {
|
||||
"type": "sli.apm.transactionErrorRate",
|
||||
},
|
||||
"instanceId": "*",
|
||||
"name": "irrelevant",
|
||||
"revision": 2,
|
||||
"tags": Array [
|
||||
"critical",
|
||||
"k8s",
|
||||
],
|
||||
"timeWindow": Object {
|
||||
"duration": "7d",
|
||||
"type": "rolling",
|
||||
},
|
||||
},
|
||||
"status": "NO_DATA",
|
||||
"statusCode": 0,
|
||||
"totalEvents": 0,
|
||||
"transaction": Object {
|
||||
"name": null,
|
||||
"type": null,
|
||||
},
|
||||
exports[`UpdateSLO when error happens during the update restores the previous SLO definition in the repository 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-original-id-2",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
"id": "slo-unique-id",
|
||||
"index": ".slo-observability.summary-v2.temp",
|
||||
"refresh": true,
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`UpdateSLO when error happens during the update restores the previous SLO definition in the repository 2`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-summary-original-id-2",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`UpdateSLO when error happens during the update restores the previous SLO definition in the repository 3`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-original-id-2",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`UpdateSLO when error happens during the update restores the previous SLO definition in the repository 4`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"slo-original-id-2",
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`UpdateSLO when error happens during the update restores the previous SLO definition in the repository 5`] = `
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"id": ".slo-observability.summary.pipeline-original-id-2",
|
||||
},
|
||||
Object {
|
||||
"ignore": Array [
|
||||
404,
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -5,25 +5,45 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks';
|
||||
import {
|
||||
ElasticsearchClientMock,
|
||||
elasticsearchServiceMock,
|
||||
loggingSystemMock,
|
||||
} from '@kbn/core/server/mocks';
|
||||
import { MockedLogger } from '@kbn/logging-mocks';
|
||||
import { CreateSLO } from './create_slo';
|
||||
import { fiveMinute, oneMinute } from './fixtures/duration';
|
||||
import { createAPMTransactionErrorRateIndicator, createSLOParams } from './fixtures/slo';
|
||||
import { createSLORepositoryMock, createTransformManagerMock } from './mocks';
|
||||
import {
|
||||
createSLORepositoryMock,
|
||||
createSummaryTransformManagerMock,
|
||||
createTransformManagerMock,
|
||||
} from './mocks';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
describe('CreateSLO', () => {
|
||||
let esClientMock: ElasticsearchClientMock;
|
||||
let loggerMock: jest.Mocked<MockedLogger>;
|
||||
let mockRepository: jest.Mocked<SLORepository>;
|
||||
let mockTransformManager: jest.Mocked<TransformManager>;
|
||||
let mockSummaryTransformManager: jest.Mocked<TransformManager>;
|
||||
let createSLO: CreateSLO;
|
||||
|
||||
beforeEach(() => {
|
||||
esClientMock = elasticsearchServiceMock.createElasticsearchClient();
|
||||
loggerMock = loggingSystemMock.createLogger();
|
||||
mockRepository = createSLORepositoryMock();
|
||||
mockTransformManager = createTransformManagerMock();
|
||||
createSLO = new CreateSLO(esClientMock, mockRepository, mockTransformManager);
|
||||
mockSummaryTransformManager = createSummaryTransformManagerMock();
|
||||
createSLO = new CreateSLO(
|
||||
esClientMock,
|
||||
mockRepository,
|
||||
mockTransformManager,
|
||||
mockSummaryTransformManager,
|
||||
loggerMock,
|
||||
'some-space'
|
||||
);
|
||||
});
|
||||
|
||||
describe('happy path', () => {
|
||||
|
@ -32,7 +52,8 @@ describe('CreateSLO', () => {
|
|||
id: 'unique-id',
|
||||
indicator: createAPMTransactionErrorRateIndicator(),
|
||||
});
|
||||
mockTransformManager.install.mockResolvedValue('slo-transform-id');
|
||||
mockTransformManager.install.mockResolvedValue('slo-id-revision');
|
||||
mockSummaryTransformManager.install.mockResolvedValue('slo-summary-id-revision');
|
||||
|
||||
const response = await createSLO.execute(sloParams);
|
||||
|
||||
|
@ -47,18 +68,21 @@ describe('CreateSLO', () => {
|
|||
revision: 1,
|
||||
tags: [],
|
||||
enabled: true,
|
||||
version: 2,
|
||||
createdAt: expect.any(Date),
|
||||
updatedAt: expect.any(Date),
|
||||
}),
|
||||
{ throwOnConflict: true }
|
||||
);
|
||||
expect(mockTransformManager.install).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ ...sloParams, id: 'unique-id' })
|
||||
);
|
||||
expect(mockTransformManager.preview).toHaveBeenCalledWith('slo-transform-id');
|
||||
expect(mockTransformManager.start).toHaveBeenCalledWith('slo-transform-id');
|
||||
expect(response).toEqual(expect.objectContaining({ id: 'unique-id' }));
|
||||
|
||||
expect(mockTransformManager.install).toHaveBeenCalled();
|
||||
expect(mockTransformManager.start).toHaveBeenCalled();
|
||||
expect(esClientMock.ingest.putPipeline.mock.calls[0]).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.install).toHaveBeenCalled();
|
||||
expect(mockSummaryTransformManager.start).toHaveBeenCalled();
|
||||
expect(esClientMock.index.mock.calls[0]).toMatchSnapshot();
|
||||
|
||||
expect(response).toEqual(expect.objectContaining({ id: 'unique-id' }));
|
||||
});
|
||||
|
||||
it('overrides the default values when provided', async () => {
|
||||
|
@ -93,32 +117,20 @@ describe('CreateSLO', () => {
|
|||
});
|
||||
|
||||
describe('unhappy path', () => {
|
||||
it('deletes the SLO when transform installation fails', async () => {
|
||||
mockTransformManager.install.mockRejectedValue(new Error('Transform install error'));
|
||||
it('rollbacks new resources on failure', async () => {
|
||||
mockTransformManager.install.mockRejectedValue(new Error('Rollup transform install error'));
|
||||
const sloParams = createSLOParams({ indicator: createAPMTransactionErrorRateIndicator() });
|
||||
|
||||
await expect(createSLO.execute(sloParams)).rejects.toThrowError('Transform install error');
|
||||
expect(mockRepository.deleteById).toBeCalled();
|
||||
});
|
||||
await expect(createSLO.execute(sloParams)).rejects.toThrowError(
|
||||
'Rollup transform install error'
|
||||
);
|
||||
|
||||
it('removes the transform and deletes the SLO when transform preview fails', async () => {
|
||||
mockTransformManager.install.mockResolvedValue('slo-transform-id');
|
||||
mockTransformManager.preview.mockRejectedValue(new Error('Transform preview error'));
|
||||
const sloParams = createSLOParams({ indicator: createAPMTransactionErrorRateIndicator() });
|
||||
|
||||
await expect(createSLO.execute(sloParams)).rejects.toThrowError('Transform preview error');
|
||||
expect(mockTransformManager.uninstall).toBeCalledWith('slo-transform-id');
|
||||
expect(mockRepository.deleteById).toBeCalled();
|
||||
});
|
||||
|
||||
it('removes the transform and deletes the SLO when transform start fails', async () => {
|
||||
mockTransformManager.install.mockResolvedValue('slo-transform-id');
|
||||
mockTransformManager.start.mockRejectedValue(new Error('Transform start error'));
|
||||
const sloParams = createSLOParams({ indicator: createAPMTransactionErrorRateIndicator() });
|
||||
|
||||
await expect(createSLO.execute(sloParams)).rejects.toThrowError('Transform start error');
|
||||
expect(mockTransformManager.uninstall).toBeCalledWith('slo-transform-id');
|
||||
expect(mockRepository.deleteById).toBeCalled();
|
||||
expect(mockSummaryTransformManager.stop).toHaveBeenCalled();
|
||||
expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled();
|
||||
expect(mockTransformManager.stop).toHaveBeenCalled();
|
||||
expect(mockTransformManager.uninstall).toHaveBeenCalled();
|
||||
expect(esClientMock.ingest.deletePipeline).toHaveBeenCalled();
|
||||
expect(mockRepository.deleteById).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,21 +5,32 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { SLO_SUMMARY_TEMP_INDEX_NAME } from '../../../common/slo/constants';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
getSLOTransformId,
|
||||
SLO_MODEL_VERSION,
|
||||
SLO_SUMMARY_TEMP_INDEX_NAME,
|
||||
} from '../../../common/slo/constants';
|
||||
import { getSLOSummaryPipelineTemplate } from '../../assets/ingest_templates/slo_summary_pipeline_template';
|
||||
import { Duration, DurationUnit, SLO } from '../../domain/models';
|
||||
import { validateSLO } from '../../domain/services';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { createTempSummaryDocument } from './summary_transform/helpers/create_temp_summary';
|
||||
import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
export class CreateSLO {
|
||||
constructor(
|
||||
private esClient: ElasticsearchClient,
|
||||
private repository: SLORepository,
|
||||
private transformManager: TransformManager
|
||||
private transformManager: TransformManager,
|
||||
private summaryTransformManager: TransformManager,
|
||||
private logger: Logger,
|
||||
private spaceId: string
|
||||
) {}
|
||||
|
||||
public async execute(params: CreateSLOParams): Promise<CreateSLOResponse> {
|
||||
|
@ -27,33 +38,48 @@ export class CreateSLO {
|
|||
validateSLO(slo);
|
||||
|
||||
await this.repository.save(slo, { throwOnConflict: true });
|
||||
let sloTransformId;
|
||||
|
||||
const rollupTransformId = getSLOTransformId(slo.id, slo.revision);
|
||||
const summaryTransformId = getSLOSummaryTransformId(slo.id, slo.revision);
|
||||
try {
|
||||
sloTransformId = await this.transformManager.install(slo);
|
||||
await this.transformManager.install(slo);
|
||||
await this.transformManager.start(rollupTransformId);
|
||||
await retryTransientEsErrors(
|
||||
() => this.esClient.ingest.putPipeline(getSLOSummaryPipelineTemplate(slo, this.spaceId)),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
|
||||
await this.summaryTransformManager.install(slo);
|
||||
await this.summaryTransformManager.start(summaryTransformId);
|
||||
|
||||
await retryTransientEsErrors(
|
||||
() =>
|
||||
this.esClient.index({
|
||||
index: SLO_SUMMARY_TEMP_INDEX_NAME,
|
||||
id: `slo-${slo.id}`,
|
||||
document: createTempSummaryDocument(slo, this.spaceId),
|
||||
refresh: true,
|
||||
}),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(
|
||||
`Cannot install the SLO [id: ${slo.id}, revision: ${slo.revision}]. Rolling back.`
|
||||
);
|
||||
|
||||
await this.summaryTransformManager.stop(summaryTransformId);
|
||||
await this.summaryTransformManager.uninstall(summaryTransformId);
|
||||
await this.transformManager.stop(rollupTransformId);
|
||||
await this.transformManager.uninstall(rollupTransformId);
|
||||
await this.esClient.ingest.deletePipeline(
|
||||
{ id: getSLOSummaryPipelineId(slo.id, slo.revision) },
|
||||
{ ignore: [404] }
|
||||
);
|
||||
await this.repository.deleteById(slo.id);
|
||||
throw err;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.transformManager.preview(sloTransformId);
|
||||
await this.transformManager.start(sloTransformId);
|
||||
} catch (err) {
|
||||
await Promise.all([
|
||||
this.transformManager.uninstall(sloTransformId),
|
||||
this.repository.deleteById(slo.id),
|
||||
]);
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
await this.esClient.index({
|
||||
index: SLO_SUMMARY_TEMP_INDEX_NAME,
|
||||
id: `slo-${slo.id}`,
|
||||
document: createTempSummaryDocument(slo),
|
||||
refresh: true,
|
||||
});
|
||||
|
||||
return this.toResponse(slo);
|
||||
}
|
||||
|
||||
|
@ -72,6 +98,7 @@ export class CreateSLO {
|
|||
createdAt: now,
|
||||
updatedAt: now,
|
||||
groupBy: !!params.groupBy ? params.groupBy : ALL_VALUE,
|
||||
version: SLO_MODEL_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,20 +9,20 @@ import { rulesClientMock } from '@kbn/alerting-plugin/server/rules_client.mock';
|
|||
import { RulesClientApi } from '@kbn/alerting-plugin/server/types';
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
|
||||
import {
|
||||
getSLOTransformId,
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
|
||||
} from '../../../common/slo/constants';
|
||||
import { DeleteSLO } from './delete_slo';
|
||||
import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo';
|
||||
import { createSLORepositoryMock, createTransformManagerMock } from './mocks';
|
||||
import {
|
||||
createSLORepositoryMock,
|
||||
createSummaryTransformManagerMock,
|
||||
createTransformManagerMock,
|
||||
} from './mocks';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
describe('DeleteSLO', () => {
|
||||
let mockRepository: jest.Mocked<SLORepository>;
|
||||
let mockTransformManager: jest.Mocked<TransformManager>;
|
||||
let mockSummaryTransformManager: jest.Mocked<TransformManager>;
|
||||
let mockEsClient: jest.Mocked<ElasticsearchClient>;
|
||||
let mockRulesClient: jest.Mocked<RulesClientApi>;
|
||||
let deleteSLO: DeleteSLO;
|
||||
|
@ -30,52 +30,37 @@ describe('DeleteSLO', () => {
|
|||
beforeEach(() => {
|
||||
mockRepository = createSLORepositoryMock();
|
||||
mockTransformManager = createTransformManagerMock();
|
||||
mockSummaryTransformManager = createSummaryTransformManagerMock();
|
||||
mockEsClient = elasticsearchServiceMock.createElasticsearchClient();
|
||||
mockRulesClient = rulesClientMock.create();
|
||||
deleteSLO = new DeleteSLO(mockRepository, mockTransformManager, mockEsClient, mockRulesClient);
|
||||
deleteSLO = new DeleteSLO(
|
||||
mockRepository,
|
||||
mockTransformManager,
|
||||
mockSummaryTransformManager,
|
||||
mockEsClient,
|
||||
mockRulesClient
|
||||
);
|
||||
});
|
||||
|
||||
describe('happy path', () => {
|
||||
it('removes the transform, the roll up data, the associated rules and the SLO from the repository', async () => {
|
||||
const slo = createSLO({ indicator: createAPMTransactionErrorRateIndicator() });
|
||||
it('removes all resources associatde to the slo', async () => {
|
||||
const slo = createSLO({
|
||||
id: 'irrelevant',
|
||||
indicator: createAPMTransactionErrorRateIndicator(),
|
||||
});
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
await deleteSLO.execute(slo.id);
|
||||
|
||||
expect(mockRepository.findById).toHaveBeenCalledWith(slo.id);
|
||||
expect(mockTransformManager.stop).toHaveBeenCalledWith(
|
||||
getSLOTransformId(slo.id, slo.revision)
|
||||
);
|
||||
expect(mockTransformManager.uninstall).toHaveBeenCalledWith(
|
||||
getSLOTransformId(slo.id, slo.revision)
|
||||
);
|
||||
expect(mockEsClient.deleteByQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
query: {
|
||||
match: {
|
||||
'slo.id': slo.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
|
||||
query: {
|
||||
match: {
|
||||
'slo.id': slo.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
expect(mockRulesClient.bulkDeleteRules).toHaveBeenCalledWith({
|
||||
filter: `alert.attributes.params.sloId:${slo.id}`,
|
||||
});
|
||||
expect(mockRepository.deleteById).toHaveBeenCalledWith(slo.id);
|
||||
expect(mockRepository.findById).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.stop).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.uninstall).toMatchSnapshot();
|
||||
expect(mockTransformManager.stop).toMatchSnapshot();
|
||||
expect(mockTransformManager.uninstall).toMatchSnapshot();
|
||||
expect(mockEsClient.ingest.deletePipeline).toMatchSnapshot();
|
||||
expect(mockEsClient.deleteByQuery).toMatchSnapshot();
|
||||
expect(mockRulesClient.bulkDeleteRules).toMatchSnapshot();
|
||||
expect(mockRepository.deleteById).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
import { RulesClientApi } from '@kbn/alerting-plugin/server/types';
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
getSLOTransformId,
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
|
||||
} from '../../../common/slo/constants';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
|
@ -19,6 +22,7 @@ export class DeleteSLO {
|
|||
constructor(
|
||||
private repository: SLORepository,
|
||||
private transformManager: TransformManager,
|
||||
private summaryTransformManager: TransformManager,
|
||||
private esClient: ElasticsearchClient,
|
||||
private rulesClient: RulesClientApi
|
||||
) {}
|
||||
|
@ -26,9 +30,20 @@ export class DeleteSLO {
|
|||
public async execute(sloId: string): Promise<void> {
|
||||
const slo = await this.repository.findById(sloId);
|
||||
|
||||
const sloTransformId = getSLOTransformId(slo.id, slo.revision);
|
||||
await this.transformManager.stop(sloTransformId);
|
||||
await this.transformManager.uninstall(sloTransformId);
|
||||
const summaryTransformId = getSLOSummaryTransformId(slo.id, slo.revision);
|
||||
await this.summaryTransformManager.stop(summaryTransformId);
|
||||
await this.summaryTransformManager.uninstall(summaryTransformId);
|
||||
|
||||
const rollupTransformId = getSLOTransformId(slo.id, slo.revision);
|
||||
await this.transformManager.stop(rollupTransformId);
|
||||
await this.transformManager.uninstall(rollupTransformId);
|
||||
|
||||
await retryTransientEsErrors(() =>
|
||||
this.esClient.ingest.deletePipeline(
|
||||
{ id: getSLOSummaryPipelineId(slo.id, slo.revision) },
|
||||
{ ignore: [404] }
|
||||
)
|
||||
);
|
||||
|
||||
await this.deleteRollupData(slo.id);
|
||||
await this.deleteSummaryData(slo.id);
|
||||
|
|
|
@ -43,7 +43,7 @@ describe('DeleteSLOInstances', () => {
|
|||
expect(mockEsClient.deleteByQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockEsClient.deleteByQuery.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"index": ".slo-observability.sli-v2*",
|
||||
"index": ".slo-observability.sli-v3*",
|
||||
"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-v2*",
|
||||
"index": ".slo-observability.summary-v3*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"should": Array [
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ALL_VALUE } from '@kbn/slo-schema';
|
||||
import { ALL_VALUE, Paginated } from '@kbn/slo-schema';
|
||||
import { SLO_MODEL_VERSION } from '../../../common/slo/constants';
|
||||
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 { Paginated, SLOSummary, SummarySearchClient } from './summary_search_client';
|
||||
import { SLOSummary, SummarySearchClient } from './summary_search_client';
|
||||
|
||||
describe('FindSLO', () => {
|
||||
let mockRepository: jest.Mocked<SLORepository>;
|
||||
|
@ -95,6 +96,7 @@ describe('FindSLO', () => {
|
|||
revision: slo.revision,
|
||||
groupBy: slo.groupBy,
|
||||
instanceId: ALL_VALUE,
|
||||
version: SLO_MODEL_VERSION,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -147,7 +149,7 @@ describe('FindSLO', () => {
|
|||
|
||||
await expect(findSLO.execute({ perPage: '5000' })).resolves.not.toThrow();
|
||||
await expect(findSLO.execute({ perPage: '5001' })).rejects.toThrowError(
|
||||
'perPage limit to 5000'
|
||||
'perPage limit set to 5000'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FindSLOParams, FindSLOResponse, findSLOResponseSchema } from '@kbn/slo-schema';
|
||||
import { FindSLOParams, FindSLOResponse, findSLOResponseSchema, Pagination } from '@kbn/slo-schema';
|
||||
import { SLO, SLOWithSummary } from '../../domain/models';
|
||||
import { IllegalArgumentError } from '../../errors';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { Pagination, SLOSummary, Sort, SummarySearchClient } from './summary_search_client';
|
||||
import { 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 5000');
|
||||
throw new IllegalArgumentError(`perPage limit set to ${MAX_PER_PAGE}`);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -5,14 +5,40 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FindSloDefinitionsResponse, findSloDefinitionsResponseSchema } from '@kbn/slo-schema';
|
||||
import {
|
||||
FindSLODefinitionsParams,
|
||||
FindSLODefinitionsResponse,
|
||||
findSloDefinitionsResponseSchema,
|
||||
Pagination,
|
||||
} from '@kbn/slo-schema';
|
||||
import { IllegalArgumentError } from '../../errors';
|
||||
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(search: string): Promise<FindSloDefinitionsResponse> {
|
||||
const sloList = await this.repository.search(search);
|
||||
return findSloDefinitionsResponseSchema.encode(sloList);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 set to ${MAX_PER_PAGE}`);
|
||||
}
|
||||
|
||||
return {
|
||||
page: !isNaN(page) && page >= 1 ? page : DEFAULT_PAGE,
|
||||
perPage: !isNaN(perPage) && perPage >= 1 ? perPage : DEFAULT_PER_PAGE,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from '@kbn/slo-schema';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { SLO_MODEL_VERSION } from '../../../../common/slo/constants';
|
||||
import {
|
||||
APMTransactionDurationIndicator,
|
||||
APMTransactionErrorRateIndicator,
|
||||
|
@ -139,7 +140,7 @@ export const createHistogramIndicator = (
|
|||
},
|
||||
});
|
||||
|
||||
const defaultSLO: Omit<SLO, 'id' | 'revision' | 'createdAt' | 'updatedAt'> = {
|
||||
const defaultSLO: Omit<SLO, 'id' | 'revision' | 'createdAt' | 'updatedAt' | 'version'> = {
|
||||
name: 'irrelevant',
|
||||
description: 'irrelevant',
|
||||
timeWindow: sevenDaysRolling(),
|
||||
|
@ -190,6 +191,7 @@ export const createSLO = (params: Partial<SLO> = {}): SLO => {
|
|||
revision: 1,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
version: SLO_MODEL_VERSION,
|
||||
...params,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { ALL_VALUE } from '@kbn/slo-schema';
|
||||
import { SLO_MODEL_VERSION } from '../../../common/slo/constants';
|
||||
import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo';
|
||||
import { GetSLO } from './get_slo';
|
||||
import { createSummaryClientMock, createSLORepositoryMock } from './mocks';
|
||||
|
@ -84,6 +85,7 @@ describe('GetSLO', () => {
|
|||
revision: slo.revision,
|
||||
groupBy: slo.groupBy,
|
||||
instanceId: ALL_VALUE,
|
||||
version: SLO_MODEL_VERSION,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,10 +14,10 @@ export * from './get_slo';
|
|||
export * from './historical_summary_client';
|
||||
export * from './resource_installer';
|
||||
export * from './slo_installer';
|
||||
export * from './summary_transform/summary_transform_installer';
|
||||
export * from './sli_client';
|
||||
export * from './slo_repository';
|
||||
export * from './transform_manager';
|
||||
export * from './summay_transform_manager';
|
||||
export * from './update_slo';
|
||||
export * from './summary_client';
|
||||
export * from './get_slo_instances';
|
||||
|
|
|
@ -7,19 +7,26 @@
|
|||
|
||||
import { createSLO } from './fixtures/slo';
|
||||
import { ManageSLO } from './manage_slo';
|
||||
import { createSLORepositoryMock, createTransformManagerMock } from './mocks';
|
||||
import {
|
||||
createSLORepositoryMock,
|
||||
createSummaryTransformManagerMock,
|
||||
createTransformManagerMock,
|
||||
} from './mocks';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
describe('ManageSLO', () => {
|
||||
let mockRepository: jest.Mocked<SLORepository>;
|
||||
let mockTransformManager: jest.Mocked<TransformManager>;
|
||||
let mockSummaryTransformManager: jest.Mocked<TransformManager>;
|
||||
let manageSLO: ManageSLO;
|
||||
|
||||
beforeEach(() => {
|
||||
mockRepository = createSLORepositoryMock();
|
||||
mockTransformManager = createTransformManagerMock();
|
||||
manageSLO = new ManageSLO(mockRepository, mockTransformManager);
|
||||
mockSummaryTransformManager = createSummaryTransformManagerMock();
|
||||
|
||||
manageSLO = new ManageSLO(mockRepository, mockTransformManager, mockSummaryTransformManager);
|
||||
});
|
||||
|
||||
describe('Enable', () => {
|
||||
|
@ -30,16 +37,18 @@ describe('ManageSLO', () => {
|
|||
await manageSLO.enable(slo.id);
|
||||
|
||||
expect(mockTransformManager.start).not.toHaveBeenCalled();
|
||||
expect(mockSummaryTransformManager.start).not.toHaveBeenCalled();
|
||||
expect(mockRepository.save).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('enables the slo when disabled', async () => {
|
||||
const slo = createSLO({ enabled: false });
|
||||
const slo = createSLO({ id: 'irrelevant', enabled: false });
|
||||
mockRepository.findById.mockResolvedValue(slo);
|
||||
|
||||
await manageSLO.enable(slo.id);
|
||||
|
||||
expect(mockTransformManager.start).toHaveBeenCalled();
|
||||
expect(mockTransformManager.start).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.start).toMatchSnapshot();
|
||||
expect(mockRepository.save).toHaveBeenCalledWith(expect.objectContaining({ enabled: true }));
|
||||
});
|
||||
});
|
||||
|
@ -52,16 +61,18 @@ describe('ManageSLO', () => {
|
|||
await manageSLO.disable(slo.id);
|
||||
|
||||
expect(mockTransformManager.stop).not.toHaveBeenCalled();
|
||||
expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled();
|
||||
expect(mockRepository.save).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the slo when enabled', async () => {
|
||||
const slo = createSLO({ enabled: true });
|
||||
const slo = createSLO({ id: 'irrelevant', enabled: true });
|
||||
mockRepository.findById.mockResolvedValue(slo);
|
||||
|
||||
await manageSLO.disable(slo.id);
|
||||
|
||||
expect(mockTransformManager.stop).toHaveBeenCalled();
|
||||
expect(mockTransformManager.stop).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.stop).toMatchSnapshot();
|
||||
expect(mockRepository.save).toHaveBeenCalledWith(expect.objectContaining({ enabled: false }));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,12 +5,16 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getSLOTransformId } from '../../../common/slo/constants';
|
||||
import { getSLOSummaryTransformId, getSLOTransformId } from '../../../common/slo/constants';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
export class ManageSLO {
|
||||
constructor(private repository: SLORepository, private transformManager: TransformManager) {}
|
||||
constructor(
|
||||
private repository: SLORepository,
|
||||
private transformManager: TransformManager,
|
||||
private summaryTransformManager: TransformManager
|
||||
) {}
|
||||
|
||||
async enable(sloId: string) {
|
||||
const slo = await this.repository.findById(sloId);
|
||||
|
@ -18,6 +22,7 @@ export class ManageSLO {
|
|||
return;
|
||||
}
|
||||
|
||||
await this.summaryTransformManager.start(getSLOSummaryTransformId(slo.id, slo.revision));
|
||||
await this.transformManager.start(getSLOTransformId(slo.id, slo.revision));
|
||||
slo.enabled = true;
|
||||
slo.updatedAt = new Date();
|
||||
|
@ -30,6 +35,7 @@ export class ManageSLO {
|
|||
return;
|
||||
}
|
||||
|
||||
await this.summaryTransformManager.stop(getSLOSummaryTransformId(slo.id, slo.revision));
|
||||
await this.transformManager.stop(getSLOTransformId(slo.id, slo.revision));
|
||||
slo.enabled = false;
|
||||
slo.updatedAt = new Date();
|
||||
|
|
|
@ -10,7 +10,6 @@ import { SLIClient } from '../sli_client';
|
|||
import { SLORepository } from '../slo_repository';
|
||||
import { SummaryClient } from '../summary_client';
|
||||
import { SummarySearchClient } from '../summary_search_client';
|
||||
import { SummaryTransformInstaller } from '../summary_transform/summary_transform_installer';
|
||||
import { TransformManager } from '../transform_manager';
|
||||
|
||||
const createResourceInstallerMock = (): jest.Mocked<ResourceInstaller> => {
|
||||
|
@ -19,13 +18,17 @@ const createResourceInstallerMock = (): jest.Mocked<ResourceInstaller> => {
|
|||
};
|
||||
};
|
||||
|
||||
const createSummaryTransformInstallerMock = (): jest.Mocked<SummaryTransformInstaller> => {
|
||||
const createTransformManagerMock = (): jest.Mocked<TransformManager> => {
|
||||
return {
|
||||
installAndStart: jest.fn(),
|
||||
install: jest.fn(),
|
||||
preview: jest.fn(),
|
||||
uninstall: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
const createTransformManagerMock = (): jest.Mocked<TransformManager> => {
|
||||
const createSummaryTransformManagerMock = (): jest.Mocked<TransformManager> => {
|
||||
return {
|
||||
install: jest.fn(),
|
||||
preview: jest.fn(),
|
||||
|
@ -65,8 +68,8 @@ const createSLIClientMock = (): jest.Mocked<SLIClient> => {
|
|||
|
||||
export {
|
||||
createResourceInstallerMock,
|
||||
createSummaryTransformInstallerMock,
|
||||
createTransformManagerMock,
|
||||
createSummaryTransformManagerMock,
|
||||
createSLORepositoryMock,
|
||||
createSummaryClientMock,
|
||||
createSummarySearchClientMock,
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks';
|
||||
import { MockedLogger } from '@kbn/logging-mocks';
|
||||
|
||||
import { SLO_MODEL_VERSION } from '../../../common/slo/constants';
|
||||
import { createSLO } from './fixtures/slo';
|
||||
import {
|
||||
createSLORepositoryMock,
|
||||
createSummaryTransformManagerMock,
|
||||
createTransformManagerMock,
|
||||
} from './mocks';
|
||||
import { ResetSLO } from './reset_slo';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
const TEST_DATE = new Date('2023-01-01T00:00:00.000Z');
|
||||
|
||||
describe('ResetSLO', () => {
|
||||
let mockRepository: jest.Mocked<SLORepository>;
|
||||
let mockTransformManager: jest.Mocked<TransformManager>;
|
||||
let mockSummaryTransformManager: jest.Mocked<TransformManager>;
|
||||
let mockEsClient: jest.Mocked<ElasticsearchClient>;
|
||||
let loggerMock: jest.Mocked<MockedLogger>;
|
||||
let resetSLO: ResetSLO;
|
||||
|
||||
beforeEach(() => {
|
||||
loggerMock = loggingSystemMock.createLogger();
|
||||
mockRepository = createSLORepositoryMock();
|
||||
mockTransformManager = createTransformManagerMock();
|
||||
mockEsClient = elasticsearchServiceMock.createElasticsearchClient();
|
||||
mockSummaryTransformManager = createSummaryTransformManagerMock();
|
||||
resetSLO = new ResetSLO(
|
||||
mockEsClient,
|
||||
mockRepository,
|
||||
mockTransformManager,
|
||||
mockSummaryTransformManager,
|
||||
loggerMock,
|
||||
'some-space'
|
||||
);
|
||||
jest.useFakeTimers().setSystemTime(TEST_DATE);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('resets all associated resources', async () => {
|
||||
const slo = createSLO({ id: 'irrelevant', version: 1 });
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
mockRepository.save.mockImplementation((v) => Promise.resolve(v));
|
||||
|
||||
await resetSLO.execute(slo.id);
|
||||
|
||||
// delete existing resources and data
|
||||
expect(mockSummaryTransformManager.stop).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.uninstall).toMatchSnapshot();
|
||||
|
||||
expect(mockTransformManager.stop).toMatchSnapshot();
|
||||
expect(mockTransformManager.uninstall).toMatchSnapshot();
|
||||
|
||||
expect(mockEsClient.deleteByQuery).toMatchSnapshot();
|
||||
|
||||
// install resources
|
||||
expect(mockSummaryTransformManager.install).toMatchSnapshot();
|
||||
expect(mockSummaryTransformManager.start).toMatchSnapshot();
|
||||
|
||||
expect(mockEsClient.ingest.putPipeline).toMatchSnapshot();
|
||||
|
||||
expect(mockTransformManager.install).toMatchSnapshot();
|
||||
expect(mockTransformManager.start).toMatchSnapshot();
|
||||
|
||||
expect(mockEsClient.index).toMatchSnapshot();
|
||||
|
||||
expect(mockRepository.save).toHaveBeenCalledWith({
|
||||
...slo,
|
||||
version: SLO_MODEL_VERSION,
|
||||
updatedAt: expect.anything(),
|
||||
});
|
||||
});
|
||||
});
|
130
x-pack/plugins/observability/server/services/slo/reset_slo.ts
Normal file
130
x-pack/plugins/observability/server/services/slo/reset_slo.ts
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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, Logger } from '@kbn/core/server';
|
||||
import { resetSLOResponseSchema } from '@kbn/slo-schema';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
getSLOTransformId,
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_MODEL_VERSION,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_TEMP_INDEX_NAME,
|
||||
} from '../../../common/slo/constants';
|
||||
import { getSLOSummaryPipelineTemplate } from '../../assets/ingest_templates/slo_summary_pipeline_template';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
import { SLORepository } from './slo_repository';
|
||||
import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
export class ResetSLO {
|
||||
constructor(
|
||||
private esClient: ElasticsearchClient,
|
||||
private repository: SLORepository,
|
||||
private transformManager: TransformManager,
|
||||
private summaryTransformManager: TransformManager,
|
||||
private logger: Logger,
|
||||
private spaceId: string
|
||||
) {}
|
||||
|
||||
public async execute(sloId: string) {
|
||||
const slo = await this.repository.findById(sloId);
|
||||
|
||||
const summaryTransformId = getSLOSummaryTransformId(slo.id, slo.revision);
|
||||
await this.summaryTransformManager.stop(summaryTransformId);
|
||||
await this.summaryTransformManager.uninstall(summaryTransformId);
|
||||
|
||||
const rollupTransformId = getSLOTransformId(slo.id, slo.revision);
|
||||
await this.transformManager.stop(rollupTransformId);
|
||||
await this.transformManager.uninstall(rollupTransformId);
|
||||
|
||||
await Promise.all([this.deleteRollupData(slo.id), this.deleteSummaryData(slo.id)]);
|
||||
|
||||
try {
|
||||
await this.transformManager.install(slo);
|
||||
await this.transformManager.start(rollupTransformId);
|
||||
await retryTransientEsErrors(
|
||||
() => this.esClient.ingest.putPipeline(getSLOSummaryPipelineTemplate(slo, this.spaceId)),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
|
||||
await this.summaryTransformManager.install(slo);
|
||||
await this.summaryTransformManager.start(summaryTransformId);
|
||||
|
||||
await retryTransientEsErrors(
|
||||
() =>
|
||||
this.esClient.index({
|
||||
index: SLO_SUMMARY_TEMP_INDEX_NAME,
|
||||
id: `slo-${slo.id}`,
|
||||
document: createTempSummaryDocument(slo, this.spaceId),
|
||||
refresh: true,
|
||||
}),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(
|
||||
`Cannot reset the SLO [id: ${slo.id}, revision: ${slo.revision}]. Rolling back.`
|
||||
);
|
||||
|
||||
await this.summaryTransformManager.stop(summaryTransformId);
|
||||
await this.summaryTransformManager.uninstall(summaryTransformId);
|
||||
await this.transformManager.stop(rollupTransformId);
|
||||
await this.transformManager.uninstall(rollupTransformId);
|
||||
await this.esClient.ingest.deletePipeline(
|
||||
{ id: getSLOSummaryPipelineId(slo.id, slo.revision) },
|
||||
{ ignore: [404] }
|
||||
);
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
const updatedSlo = await this.repository.save({
|
||||
...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 } }],
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ import {
|
|||
SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME,
|
||||
SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME,
|
||||
SLO_SUMMARY_INDEX_TEMPLATE_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
} from '../../../common/slo/constants';
|
||||
import { DefaultResourceInstaller } from './resource_installer';
|
||||
|
||||
|
@ -54,14 +53,10 @@ describe('resourceInstaller', () => {
|
|||
expect.objectContaining({ name: SLO_SUMMARY_INDEX_TEMPLATE_NAME })
|
||||
);
|
||||
|
||||
expect(mockClusterClient.ingest.putPipeline).toHaveBeenCalledTimes(2);
|
||||
expect(mockClusterClient.ingest.putPipeline).toHaveBeenCalledTimes(1);
|
||||
expect(mockClusterClient.ingest.putPipeline).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({ id: SLO_INGEST_PIPELINE_NAME })
|
||||
);
|
||||
expect(mockClusterClient.ingest.putPipeline).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({ id: SLO_SUMMARY_INGEST_PIPELINE_NAME })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -28,13 +28,11 @@ import {
|
|||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INDEX_TEMPLATE_NAME,
|
||||
SLO_SUMMARY_INDEX_TEMPLATE_PATTERN,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TEMP_INDEX_NAME,
|
||||
} from '../../../common/slo/constants';
|
||||
import { getSLOIndexTemplate } from '../../assets/index_templates/slo_index_templates';
|
||||
import { getSLOSummaryIndexTemplate } from '../../assets/index_templates/slo_summary_index_templates';
|
||||
import { getSLOPipelineTemplate } from '../../assets/ingest_templates/slo_pipeline_template';
|
||||
import { getSLOSummaryPipelineTemplate } from '../../assets/ingest_templates/slo_summary_pipeline_template';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
|
||||
export interface ResourceInstaller {
|
||||
|
@ -87,10 +85,6 @@ export class DefaultResourceInstaller implements ResourceInstaller {
|
|||
await this.createOrUpdateIngestPipelineTemplate(
|
||||
getSLOPipelineTemplate(SLO_INGEST_PIPELINE_NAME, SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX)
|
||||
);
|
||||
|
||||
await this.createOrUpdateIngestPipelineTemplate(
|
||||
getSLOSummaryPipelineTemplate(SLO_SUMMARY_INGEST_PIPELINE_NAME)
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(`Error installing resources shared for SLO: ${err.message}`);
|
||||
throw err;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { loggingSystemMock } from '@kbn/core/server/mocks';
|
||||
import { MockedLogger } from '@kbn/logging-mocks';
|
||||
import { createResourceInstallerMock, createSummaryTransformInstallerMock } from './mocks';
|
||||
import { createResourceInstallerMock } from './mocks';
|
||||
import { DefaultSLOInstaller } from './slo_installer';
|
||||
|
||||
describe('SLO Installer', () => {
|
||||
|
@ -19,16 +19,10 @@ describe('SLO Installer', () => {
|
|||
|
||||
it.skip('handles concurrent installation', async () => {
|
||||
const resourceInstaller = createResourceInstallerMock();
|
||||
const summaryTransformInstaller = createSummaryTransformInstallerMock();
|
||||
const service = new DefaultSLOInstaller(
|
||||
resourceInstaller,
|
||||
summaryTransformInstaller,
|
||||
loggerMock
|
||||
);
|
||||
const service = new DefaultSLOInstaller(resourceInstaller, loggerMock);
|
||||
|
||||
await Promise.all([service.install(), service.install()]);
|
||||
|
||||
expect(resourceInstaller.ensureCommonResourcesInstalled).toHaveBeenCalledTimes(1);
|
||||
expect(summaryTransformInstaller.installAndStart).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { Logger } from '@kbn/core/server';
|
||||
import { ResourceInstaller, SummaryTransformInstaller } from '.';
|
||||
import { ResourceInstaller } from '.';
|
||||
|
||||
export interface SLOInstaller {
|
||||
install(): Promise<void>;
|
||||
|
@ -15,11 +15,7 @@ export interface SLOInstaller {
|
|||
export class DefaultSLOInstaller implements SLOInstaller {
|
||||
private isInstalling: boolean = false;
|
||||
|
||||
constructor(
|
||||
private sloResourceInstaller: ResourceInstaller,
|
||||
private sloSummaryInstaller: SummaryTransformInstaller,
|
||||
private logger: Logger
|
||||
) {}
|
||||
constructor(private sloResourceInstaller: ResourceInstaller, private logger: Logger) {}
|
||||
|
||||
public async install() {
|
||||
if (this.isInstalling) {
|
||||
|
@ -32,9 +28,8 @@ export class DefaultSLOInstaller implements SLOInstaller {
|
|||
installTimeout = setTimeout(() => (this.isInstalling = false), 60000);
|
||||
|
||||
await this.sloResourceInstaller.ensureCommonResourcesInstalled();
|
||||
await this.sloSummaryInstaller.installAndStart();
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to install SLO common resources and summary transforms');
|
||||
this.logger.error('Failed to install SLO common resources');
|
||||
} finally {
|
||||
this.isInstalling = false;
|
||||
clearTimeout(installTimeout);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
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 '../../../common/slo/constants';
|
||||
import { SLO, StoredSLO } from '../../domain/models';
|
||||
import { SLOIdConflict, SLONotFound } from '../../errors';
|
||||
import { SO_SLO_TYPE } from '../../saved_objects';
|
||||
|
@ -164,19 +165,42 @@ describe('KibanaSavedObjectsSLORepository', () => {
|
|||
expect(soClientMock.delete).toHaveBeenCalledWith(SO_SLO_TYPE, SOME_SLO.id);
|
||||
});
|
||||
|
||||
it('searches by name', async () => {
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
|
||||
soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO]));
|
||||
describe('search', () => {
|
||||
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);
|
||||
const results = await repository.search(SOME_SLO.name, { page: 1, perPage: 100 });
|
||||
|
||||
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'],
|
||||
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}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
|
||||
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
|
||||
import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-server';
|
||||
import { sloSchema } from '@kbn/slo-schema';
|
||||
import { Paginated, Pagination, 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 '../../../common/slo/constants';
|
||||
import { SLO, StoredSLO } from '../../domain/models';
|
||||
import { SLOIdConflict, SLONotFound } from '../../errors';
|
||||
import { SO_SLO_TYPE } from '../../saved_objects';
|
||||
|
@ -20,7 +21,11 @@ export interface SLORepository {
|
|||
findAllByIds(ids: string[]): Promise<SLO[]>;
|
||||
findById(id: string): Promise<SLO>;
|
||||
deleteById(id: string): Promise<void>;
|
||||
search(search: string): Promise<SLO[]>;
|
||||
search(
|
||||
search: string,
|
||||
pagination: Pagination,
|
||||
options?: { includeOutdatedOnly?: boolean }
|
||||
): Promise<Paginated<SLO>>;
|
||||
}
|
||||
|
||||
export class KibanaSavedObjectsSLORepository implements SLORepository {
|
||||
|
@ -99,19 +104,28 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +135,13 @@ function toStoredSLO(slo: SLO): StoredSLO {
|
|||
|
||||
function toSLO(storedSLO: StoredSLO): SLO {
|
||||
return pipe(
|
||||
sloSchema.decode(storedSLO),
|
||||
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,
|
||||
}),
|
||||
fold(() => {
|
||||
throw new Error('Invalid Stored SLO');
|
||||
}, t.identity)
|
||||
|
|
|
@ -7,17 +7,13 @@
|
|||
|
||||
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,
|
||||
Pagination,
|
||||
Sort,
|
||||
SummarySearchClient,
|
||||
} from './summary_search_client';
|
||||
import { DefaultSummarySearchClient, Sort, SummarySearchClient } from './summary_search_client';
|
||||
|
||||
const defaultSort: Sort = {
|
||||
field: 'sli_value',
|
||||
|
@ -34,7 +30,7 @@ describe('Summary Search Client', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
esClientMock = elasticsearchServiceMock.createElasticsearchClient();
|
||||
service = new DefaultSummarySearchClient(esClientMock, loggerMock.create());
|
||||
service = new DefaultSummarySearchClient(esClientMock, loggerMock.create(), 'some-space');
|
||||
});
|
||||
|
||||
it('returns an empty response on error', async () => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
import { ALL_VALUE } from '@kbn/slo-schema';
|
||||
import { ALL_VALUE, Paginated, Pagination } from '@kbn/slo-schema';
|
||||
import { assertNever } from '@kbn/std';
|
||||
import _ from 'lodash';
|
||||
import { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types';
|
||||
|
@ -31,13 +31,6 @@ interface EsSummaryDocument {
|
|||
isTempDoc: boolean;
|
||||
}
|
||||
|
||||
export interface Paginated<T> {
|
||||
total: number;
|
||||
page: number;
|
||||
perPage: number;
|
||||
results: T[];
|
||||
}
|
||||
|
||||
export interface SLOSummary {
|
||||
id: SLOId;
|
||||
instanceId: string;
|
||||
|
@ -50,17 +43,16 @@ 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>>;
|
||||
}
|
||||
|
||||
export class DefaultSummarySearchClient implements SummarySearchClient {
|
||||
constructor(private esClient: ElasticsearchClient, private logger: Logger) {}
|
||||
constructor(
|
||||
private esClient: ElasticsearchClient,
|
||||
private logger: Logger,
|
||||
private spaceId: string
|
||||
) {}
|
||||
|
||||
async search(
|
||||
kqlQuery: string,
|
||||
|
@ -71,7 +63,11 @@ export class DefaultSummarySearchClient implements SummarySearchClient {
|
|||
const summarySearch = await this.esClient.search<EsSummaryDocument>({
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
|
||||
track_total_hits: true,
|
||||
query: getElastichsearchQueryOrThrow(kqlQuery),
|
||||
query: {
|
||||
bool: {
|
||||
filter: [{ term: { spaceId: this.spaceId } }, getElastichsearchQueryOrThrow(kqlQuery)],
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
// non-temp first, then temp documents
|
||||
isTempDoc: {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,103 +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 {
|
||||
ElasticsearchClientMock,
|
||||
elasticsearchServiceMock,
|
||||
loggingSystemMock,
|
||||
} from '@kbn/core/server/mocks';
|
||||
import { MockedLogger } from '@kbn/logging-mocks';
|
||||
import { DefaultSummaryTransformInstaller } from './summary_transform_installer';
|
||||
import { ALL_TRANSFORM_TEMPLATES } from './templates';
|
||||
|
||||
describe('Summary Transform Installer', () => {
|
||||
let esClientMock: ElasticsearchClientMock;
|
||||
let loggerMock: jest.Mocked<MockedLogger>;
|
||||
|
||||
beforeEach(() => {
|
||||
esClientMock = elasticsearchServiceMock.createElasticsearchClient();
|
||||
loggerMock = loggingSystemMock.createLogger();
|
||||
});
|
||||
|
||||
it('skips the installation when latest version already installed', async () => {
|
||||
esClientMock.transform.getTransform.mockResolvedValue({
|
||||
count: ALL_TRANSFORM_TEMPLATES.length,
|
||||
// @ts-ignore
|
||||
transforms: ALL_TRANSFORM_TEMPLATES.map((transform) => ({
|
||||
id: transform.transform_id,
|
||||
_meta: transform._meta,
|
||||
})),
|
||||
});
|
||||
const installer = new DefaultSummaryTransformInstaller(esClientMock, loggerMock);
|
||||
|
||||
await installer.installAndStart();
|
||||
|
||||
expect(esClientMock.transform.stopTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.deleteTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.putTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.startTransform).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('installs every summary transforms when none are already installed', async () => {
|
||||
esClientMock.transform.getTransform.mockResolvedValue({ count: 0, transforms: [] });
|
||||
const installer = new DefaultSummaryTransformInstaller(esClientMock, loggerMock);
|
||||
|
||||
await installer.installAndStart();
|
||||
|
||||
const nbOfTransforms = ALL_TRANSFORM_TEMPLATES.length;
|
||||
|
||||
expect(esClientMock.transform.stopTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.deleteTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
});
|
||||
|
||||
it('desinstalls previous summary transforms prior to installing the new ones', async () => {
|
||||
esClientMock.transform.getTransform.mockResolvedValue({
|
||||
count: ALL_TRANSFORM_TEMPLATES.length,
|
||||
// @ts-ignore
|
||||
transforms: ALL_TRANSFORM_TEMPLATES.map((transform) => ({
|
||||
id: transform.transform_id,
|
||||
_meta: { ...transform._meta, version: -1 },
|
||||
})),
|
||||
});
|
||||
const installer = new DefaultSummaryTransformInstaller(esClientMock, loggerMock);
|
||||
|
||||
await installer.installAndStart();
|
||||
|
||||
const nbOfTransforms = ALL_TRANSFORM_TEMPLATES.length;
|
||||
|
||||
expect(esClientMock.transform.stopTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
expect(esClientMock.transform.deleteTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
});
|
||||
|
||||
it('installs only the missing summary transforms', async () => {
|
||||
const occurrencesSummaryTransforms = ALL_TRANSFORM_TEMPLATES.filter((transform) =>
|
||||
transform.transform_id.includes('-occurrences-')
|
||||
);
|
||||
esClientMock.transform.getTransform.mockResolvedValue({
|
||||
count: occurrencesSummaryTransforms.length,
|
||||
// @ts-ignore
|
||||
transforms: occurrencesSummaryTransforms.map((transform) => ({
|
||||
id: transform.transform_id,
|
||||
_meta: transform._meta,
|
||||
})),
|
||||
});
|
||||
const installer = new DefaultSummaryTransformInstaller(esClientMock, loggerMock);
|
||||
|
||||
await installer.installAndStart();
|
||||
|
||||
const nbOfTransforms = ALL_TRANSFORM_TEMPLATES.length - occurrencesSummaryTransforms.length;
|
||||
|
||||
expect(esClientMock.transform.stopTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.deleteTransform).not.toHaveBeenCalled();
|
||||
expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(nbOfTransforms);
|
||||
expect(esClientMock.transform.putTransform.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,105 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
import {
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../common/slo/constants';
|
||||
import { retryTransientEsErrors } from '../../../utils/retry';
|
||||
import { ALL_TRANSFORM_TEMPLATES } from './templates';
|
||||
|
||||
export interface SummaryTransformInstaller {
|
||||
installAndStart(): Promise<void>;
|
||||
}
|
||||
|
||||
export class DefaultSummaryTransformInstaller implements SummaryTransformInstaller {
|
||||
constructor(private esClient: ElasticsearchClient, private logger: Logger) {}
|
||||
|
||||
public async installAndStart(): Promise<void> {
|
||||
const allTransformIds = ALL_TRANSFORM_TEMPLATES.map((transform) => transform.transform_id);
|
||||
const summaryTransforms = await this.execute(() =>
|
||||
this.esClient.transform.getTransform(
|
||||
{ transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}*`, allow_no_match: true },
|
||||
{ ignore: [404] }
|
||||
)
|
||||
);
|
||||
const alreadyInstalled =
|
||||
summaryTransforms.count === allTransformIds.length &&
|
||||
summaryTransforms.transforms.every(
|
||||
(transform) => transform._meta?.version === SLO_SUMMARY_TRANSFORMS_VERSION
|
||||
) &&
|
||||
summaryTransforms.transforms.every((transform) => allTransformIds.includes(transform.id));
|
||||
|
||||
if (alreadyInstalled) {
|
||||
this.logger.info(`SLO summary transforms already installed - skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const transformTemplate of ALL_TRANSFORM_TEMPLATES) {
|
||||
const transformId = transformTemplate.transform_id;
|
||||
const transform = summaryTransforms.transforms.find((t) => t.id === transformId);
|
||||
|
||||
const transformAlreadyInstalled =
|
||||
!!transform && transform._meta?.version === SLO_SUMMARY_TRANSFORMS_VERSION;
|
||||
const previousTransformAlreadyInstalled =
|
||||
!!transform && transform._meta?.version !== SLO_SUMMARY_TRANSFORMS_VERSION;
|
||||
|
||||
if (transformAlreadyInstalled) {
|
||||
this.logger.info(`SLO summary transform [${transformId}] already installed - skipping`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (previousTransformAlreadyInstalled) {
|
||||
await this.deletePreviousTransformVersion(transformId);
|
||||
}
|
||||
|
||||
await this.installTransform(transformId, transformTemplate);
|
||||
await this.startTransform(transformId);
|
||||
}
|
||||
|
||||
this.logger.info(`SLO summary transforms installed and started`);
|
||||
}
|
||||
|
||||
private async installTransform(
|
||||
transformId: string,
|
||||
transformTemplate: TransformPutTransformRequest
|
||||
) {
|
||||
this.logger.info(`Installing SLO summary transform [${transformId}]`);
|
||||
await this.execute(() =>
|
||||
this.esClient.transform.putTransform(transformTemplate, { ignore: [409] })
|
||||
);
|
||||
}
|
||||
|
||||
private async deletePreviousTransformVersion(transformId: string) {
|
||||
this.logger.info(`Deleting previous SLO summary transform [${transformId}]`);
|
||||
await this.execute(() =>
|
||||
this.esClient.transform.stopTransform(
|
||||
{ transform_id: transformId, allow_no_match: true, force: true },
|
||||
{ ignore: [409, 404] }
|
||||
)
|
||||
);
|
||||
await this.execute(() =>
|
||||
this.esClient.transform.deleteTransform(
|
||||
{ transform_id: transformId, force: true },
|
||||
{ ignore: [409, 404] }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private async startTransform(transformId: string) {
|
||||
this.logger.info(`Starting SLO summary transform [${transformId}]`);
|
||||
await this.execute(() =>
|
||||
this.esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] })
|
||||
);
|
||||
}
|
||||
|
||||
private async execute<T>(esCall: () => Promise<T>): Promise<T> {
|
||||
return await retryTransientEsErrors(esCall, { logger: this.logger });
|
||||
}
|
||||
}
|
|
@ -1,100 +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 const groupBy = {
|
||||
'slo.id': {
|
||||
terms: {
|
||||
field: 'slo.id',
|
||||
},
|
||||
},
|
||||
'slo.revision': {
|
||||
terms: {
|
||||
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',
|
||||
},
|
||||
},
|
||||
'slo.timeWindow.duration': {
|
||||
terms: {
|
||||
field: 'slo.timeWindow.duration',
|
||||
},
|
||||
},
|
||||
'slo.timeWindow.type': {
|
||||
terms: {
|
||||
field: 'slo.timeWindow.type',
|
||||
},
|
||||
},
|
||||
errorBudgetEstimated: {
|
||||
terms: {
|
||||
field: 'errorBudgetEstimated',
|
||||
},
|
||||
},
|
||||
// Differentiate the temporary document from the summary one
|
||||
isTempDoc: {
|
||||
terms: {
|
||||
field: 'isTempDoc',
|
||||
},
|
||||
},
|
||||
// optional fields: only specified for APM indicators. Must include missing_bucket:true
|
||||
'service.name': {
|
||||
terms: {
|
||||
field: 'service.name',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
'service.environment': {
|
||||
terms: {
|
||||
field: 'service.environment',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
'transaction.name': {
|
||||
terms: {
|
||||
field: 'transaction.name',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
'transaction.type': {
|
||||
terms: {
|
||||
field: 'transaction.type',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,30 +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 { SUMMARY_OCCURRENCES_7D_ROLLING } from './summary_occurrences_7d_rolling';
|
||||
import { SUMMARY_OCCURRENCES_30D_ROLLING } from './summary_occurrences_30d_rolling';
|
||||
import { SUMMARY_OCCURRENCES_90D_ROLLING } from './summary_occurrences_90d_rolling';
|
||||
import { SUMMARY_TIMESLICES_7D_ROLLING } from './summary_timeslices_7d_rolling';
|
||||
import { SUMMARY_TIMESLICES_30D_ROLLING } from './summary_timeslices_30d_rolling';
|
||||
import { SUMMARY_TIMESLICES_90D_ROLLING } from './summary_timeslices_90d_rolling';
|
||||
import { SUMMARY_OCCURRENCES_WEEKLY_ALIGNED } from './summary_occurrences_weekly_aligned';
|
||||
import { SUMMARY_OCCURRENCES_MONTHLY_ALIGNED } from './summary_occurrences_monthly_aligned';
|
||||
import { SUMMARY_TIMESLICES_WEEKLY_ALIGNED } from './summary_timeslices_weekly_aligned';
|
||||
import { SUMMARY_TIMESLICES_MONTHLY_ALIGNED } from './summary_timeslices_monthly_aligned';
|
||||
|
||||
export const ALL_TRANSFORM_TEMPLATES = [
|
||||
SUMMARY_OCCURRENCES_7D_ROLLING,
|
||||
SUMMARY_OCCURRENCES_30D_ROLLING,
|
||||
SUMMARY_OCCURRENCES_90D_ROLLING,
|
||||
SUMMARY_OCCURRENCES_WEEKLY_ALIGNED,
|
||||
SUMMARY_OCCURRENCES_MONTHLY_ALIGNED,
|
||||
SUMMARY_TIMESLICES_7D_ROLLING,
|
||||
SUMMARY_TIMESLICES_30D_ROLLING,
|
||||
SUMMARY_TIMESLICES_90D_ROLLING,
|
||||
SUMMARY_TIMESLICES_WEEKLY_ALIGNED,
|
||||
SUMMARY_TIMESLICES_MONTHLY_ALIGNED,
|
||||
];
|
|
@ -1,153 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_OCCURRENCES_30D_ROLLING: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}occurrences-30d-rolling`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now-30d/m',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'occurrences',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'rolling',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '30d',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.numerator',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
sum: {
|
||||
field: 'slo.denominator',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objectiveTarget',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsummed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsummed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objectiveTarget) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with occurrences budgeting method and a 30 days rolling time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,153 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_OCCURRENCES_7D_ROLLING: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}occurrences-7d-rolling`,
|
||||
dest: {
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now-7d/m',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'occurrences',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'rolling',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '7d',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.numerator',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
sum: {
|
||||
field: 'slo.denominator',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objectiveTarget',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsummed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsummed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objectiveTarget) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with occurrences budgeting method and a 7 days rolling time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,153 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_OCCURRENCES_90D_ROLLING: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}occurrences-90d-rolling`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now-90d/m',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'occurrences',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'rolling',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '90d',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.numerator',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
sum: {
|
||||
field: 'slo.denominator',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objectiveTarget',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsummed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsummed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objectiveTarget) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with occurrences budgeting method and a 90 days rolling time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,151 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_OCCURRENCES_MONTHLY_ALIGNED: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}occurrences-monthly-aligned`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(true)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now/M',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'occurrences',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'calendarAligned',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '1M',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.numerator',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
sum: {
|
||||
field: 'slo.denominator',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objective: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objective',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objective: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with occurrences budgeting method and a monthly calendar aligned time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,151 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_OCCURRENCES_WEEKLY_ALIGNED: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}occurrences-weekly-aligned`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(true)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now/w',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'occurrences',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'calendarAligned',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '1w',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.numerator',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
sum: {
|
||||
field: 'slo.denominator',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objective: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objective',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objective: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with occurrences budgeting method and a weekly calendar aligned time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,153 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_TIMESLICES_30D_ROLLING: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}timeslices-30d-rolling`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now-30d/m',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'timeslices',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'rolling',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '30d',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objectiveTarget',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsummed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsummed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objectiveTarget) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with timeslices budgeting method and a 30 days rolling time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,153 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_TIMESLICES_7D_ROLLING: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}timeslices-7d-rolling`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now-7d/m',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'timeslices',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'rolling',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '7d',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objectiveTarget',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsummed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsummed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objectiveTarget) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with timeslices budgeting method and a 7 days rolling time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,153 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_TIMESLICES_90D_ROLLING: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}timeslices-90d-rolling`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now-90d/m',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'timeslices',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'rolling',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '90d',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objectiveTarget',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsummed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsummed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objectiveTarget: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objectiveTarget) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with timeslices budgeting method and a 90 days rolling time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,181 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_TIMESLICES_MONTHLY_ALIGNED: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}timeslices-monthly-aligned`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now/M',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'timeslices',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'calendarAligned',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '1M',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
_sliceDurationInSeconds: {
|
||||
max: {
|
||||
field: 'slo.objective.sliceDurationInSeconds',
|
||||
},
|
||||
},
|
||||
_totalSlicesInPeriod: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliceDurationInSeconds: '_sliceDurationInSeconds',
|
||||
},
|
||||
script: {
|
||||
source: `
|
||||
Date d = new Date();
|
||||
Instant instant = Instant.ofEpochMilli(d.getTime());
|
||||
LocalDateTime now = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
|
||||
LocalDateTime startOfMonth = now
|
||||
.withDayOfMonth(1)
|
||||
.withHour(0)
|
||||
.withMinute(0)
|
||||
.withSecond(0);
|
||||
LocalDateTime startOfNextMonth = startOfMonth.plusMonths(1);
|
||||
double sliceDurationInMinutes = params.sliceDurationInSeconds / 60;
|
||||
|
||||
return Math.ceil(Duration.between(startOfMonth, startOfNextMonth).toMinutes() / sliceDurationInMinutes);
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objective: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objective',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
totalSlicesInPeriod: '_totalSlicesInPeriod',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return 0 } else { return (params.totalEvents - params.goodEvents) / (params.totalSlicesInPeriod * params.errorBudgetInitial) }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objective: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with timeslices budgeting method and a monthly calendar aligned time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -1,166 +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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
SLO_SUMMARY_TRANSFORM_NAME_PREFIX,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { groupBy } from './common';
|
||||
|
||||
export const SUMMARY_TIMESLICES_WEEKLY_ALIGNED: TransformPutTransformRequest = {
|
||||
transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}timeslices-weekly-aligned`,
|
||||
dest: {
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
pipeline: SLO_SUMMARY_INGEST_PIPELINE_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
runtime_mappings: {
|
||||
errorBudgetEstimated: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
isTempDoc: {
|
||||
type: 'boolean',
|
||||
script: 'emit(false)',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: 'now/w',
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.budgetingMethod': 'timeslices',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.type': 'calendarAligned',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.timeWindow.duration': '1w',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: groupBy,
|
||||
aggregations: {
|
||||
_sliceDurationInSeconds: {
|
||||
max: {
|
||||
field: 'slo.objective.sliceDurationInSeconds',
|
||||
},
|
||||
},
|
||||
_totalSlicesInPeriod: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliceDurationInSeconds: '_sliceDurationInSeconds',
|
||||
},
|
||||
script: 'Math.ceil(7 * 24 * 60 * 60 / params.sliceDurationInSeconds)',
|
||||
},
|
||||
},
|
||||
_objectiveTarget: {
|
||||
max: {
|
||||
field: 'slo.objective.target',
|
||||
},
|
||||
},
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
objective: '_objectiveTarget',
|
||||
},
|
||||
script: '1 - params.objective',
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
totalSlicesInPeriod: '_totalSlicesInPeriod',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return 0 } else { return (params.totalEvents - params.goodEvents) / (params.totalSlicesInPeriod * params.errorBudgetInitial) }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
objective: '_objectiveTarget',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else if (params.sliValue >= params.objective) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Summarize every SLO with timeslices budgeting method and a weekly calendar aligned time window',
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: '@timestamp',
|
||||
delay: '125s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_SUMMARY_TRANSFORMS_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 { ALL_VALUE } from '@kbn/slo-schema';
|
||||
import { SLO } from '../../../../domain/models/slo';
|
||||
|
||||
export const getGroupBy = (slo: SLO) => {
|
||||
const groupings =
|
||||
slo.groupBy !== '' && slo.groupBy !== ALL_VALUE
|
||||
? [slo.groupBy].flat().reduce((acc, field) => {
|
||||
return {
|
||||
...acc,
|
||||
[`slo.groupings.${field}`]: {
|
||||
terms: {
|
||||
field: `slo.groupings.${field}`,
|
||||
},
|
||||
},
|
||||
};
|
||||
}, {})
|
||||
: {};
|
||||
|
||||
return {
|
||||
'slo.id': {
|
||||
terms: {
|
||||
field: 'slo.id',
|
||||
},
|
||||
},
|
||||
'slo.revision': {
|
||||
terms: {
|
||||
field: 'slo.revision',
|
||||
},
|
||||
},
|
||||
'slo.instanceId': {
|
||||
terms: {
|
||||
field: 'slo.instanceId',
|
||||
},
|
||||
},
|
||||
...groupings,
|
||||
// optional fields: only specified for APM indicators. Must include missing_bucket:true
|
||||
'service.name': {
|
||||
terms: {
|
||||
field: 'service.name',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
'service.environment': {
|
||||
terms: {
|
||||
field: 'service.environment',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
'transaction.name': {
|
||||
terms: {
|
||||
field: 'transaction.name',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
'transaction.type': {
|
||||
terms: {
|
||||
field: 'transaction.type',
|
||||
missing_bucket: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { SLO } from '../../../../domain/models';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_RESOURCES_VERSION,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { getGroupBy } from './common';
|
||||
|
||||
export function generateSummaryTransformForOccurrences(slo: SLO): TransformPutTransformRequest {
|
||||
return {
|
||||
transform_id: getSLOSummaryTransformId(slo.id, slo.revision),
|
||||
dest: {
|
||||
pipeline: getSLOSummaryPipelineId(slo.id, slo.revision),
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: `now-${slo.timeWindow.duration.format()}/m`,
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.id': slo.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.revision': slo.revision,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: getGroupBy(slo),
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.numerator',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
sum: {
|
||||
field: 'slo.denominator',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {},
|
||||
script: `1 - ${slo.objective.target}`,
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source: `if (params.sliValue == -1) { return 0 } else if (params.sliValue >= ${slo.objective.target}) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }`,
|
||||
},
|
||||
},
|
||||
},
|
||||
latestSliTimestamp: {
|
||||
max: {
|
||||
field: '@timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description: `Summarise the rollup data of SLO: ${slo.name} [id: ${slo.id}, revision: ${slo.revision}].`,
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: 'event.ingested',
|
||||
delay: '65s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_RESOURCES_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { DurationUnit, SLO } from '../../../../domain/models';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_RESOURCES_VERSION,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { getGroupBy } from './common';
|
||||
|
||||
export function generateSummaryTransformForTimeslicesAndCalendarAligned(
|
||||
slo: SLO
|
||||
): TransformPutTransformRequest {
|
||||
const isWeeklyAligned = slo.timeWindow.duration.unit === DurationUnit.Week;
|
||||
const sliceDurationInSeconds = slo.objective.timesliceWindow!.asSeconds();
|
||||
|
||||
return {
|
||||
transform_id: getSLOSummaryTransformId(slo.id, slo.revision),
|
||||
dest: {
|
||||
pipeline: getSLOSummaryPipelineId(slo.id, slo.revision),
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: isWeeklyAligned ? `now/w` : `now/M`,
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.id': slo.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.revision': slo.revision,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: getGroupBy(slo),
|
||||
aggregations: {
|
||||
_totalSlicesInPeriod: {
|
||||
bucket_script: {
|
||||
buckets_path: {},
|
||||
script: {
|
||||
source: `
|
||||
if (${isWeeklyAligned} == true) {
|
||||
return Math.ceil(7 * 24 * 60 * 60 / ${sliceDurationInSeconds});
|
||||
} else {
|
||||
Date d = new Date();
|
||||
Instant instant = Instant.ofEpochMilli(d.getTime());
|
||||
LocalDateTime now = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
|
||||
LocalDateTime startOfMonth = now
|
||||
.withDayOfMonth(1)
|
||||
.withHour(0)
|
||||
.withMinute(0)
|
||||
.withSecond(0);
|
||||
LocalDateTime startOfNextMonth = startOfMonth.plusMonths(1);
|
||||
double sliceDurationInMinutes = ${sliceDurationInSeconds} / 60;
|
||||
|
||||
return Math.ceil(Duration.between(startOfMonth, startOfNextMonth).toMinutes() / sliceDurationInMinutes);
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {},
|
||||
script: `1 - ${slo.objective.target}`,
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
totalSlicesInPeriod: '_totalSlicesInPeriod',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return 0 } else { return (params.totalEvents - params.goodEvents) / (params.totalSlicesInPeriod * params.errorBudgetInitial) }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: `if (params.sliValue == -1) { return 0 } else if (params.sliValue >= ${slo.objective.target}) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }`,
|
||||
},
|
||||
},
|
||||
latestSliTimestamp: {
|
||||
max: {
|
||||
field: '@timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description: `Summarise the rollup data of SLO: ${slo.name} [id: ${slo.id}, revision: ${slo.revision}].`,
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: 'event.ingested',
|
||||
delay: '65s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_RESOURCES_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { SLO } from '../../../../domain/models';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
SLO_DESTINATION_INDEX_PATTERN,
|
||||
SLO_RESOURCES_VERSION,
|
||||
SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
} from '../../../../../common/slo/constants';
|
||||
import { getGroupBy } from './common';
|
||||
|
||||
export function generateSummaryTransformForTimeslicesAndRolling(
|
||||
slo: SLO
|
||||
): TransformPutTransformRequest {
|
||||
return {
|
||||
transform_id: getSLOSummaryTransformId(slo.id, slo.revision),
|
||||
dest: {
|
||||
pipeline: getSLOSummaryPipelineId(slo.id, slo.revision),
|
||||
index: SLO_SUMMARY_DESTINATION_INDEX_NAME,
|
||||
},
|
||||
source: {
|
||||
index: SLO_DESTINATION_INDEX_PATTERN,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
gte: `now-${slo.timeWindow.duration.format()}/m`,
|
||||
lte: 'now/m',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.id': slo.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'slo.revision': slo.revision,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
pivot: {
|
||||
group_by: getGroupBy(slo),
|
||||
aggregations: {
|
||||
goodEvents: {
|
||||
sum: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
totalEvents: {
|
||||
value_count: {
|
||||
field: 'slo.isGoodSlice',
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
goodEvents: 'goodEvents',
|
||||
totalEvents: 'totalEvents',
|
||||
},
|
||||
script:
|
||||
'if (params.totalEvents == 0) { return -1 } else if (params.goodEvents >= params.totalEvents) { return 1 } else { return params.goodEvents / params.totalEvents }',
|
||||
},
|
||||
},
|
||||
errorBudgetInitial: {
|
||||
bucket_script: {
|
||||
buckets_path: {},
|
||||
script: `1 - ${slo.objective.target}`,
|
||||
},
|
||||
},
|
||||
errorBudgetConsumed: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetInitial: 'errorBudgetInitial',
|
||||
},
|
||||
script:
|
||||
'if (params.sliValue == -1) { return 0 } else { return (1 - params.sliValue) / params.errorBudgetInitial }',
|
||||
},
|
||||
},
|
||||
errorBudgetRemaining: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
errorBudgetConsumed: 'errorBudgetConsumed',
|
||||
},
|
||||
script: '1 - params.errorBudgetConsumed',
|
||||
},
|
||||
},
|
||||
statusCode: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
sliValue: 'sliValue',
|
||||
errorBudgetRemaining: 'errorBudgetRemaining',
|
||||
},
|
||||
script: {
|
||||
source: `if (params.sliValue == -1) { return 0 } else if (params.sliValue >= ${slo.objective.target}) { return 4 } else if (params.errorBudgetRemaining > 0) { return 2 } else { return 1 }`,
|
||||
},
|
||||
},
|
||||
},
|
||||
latestSliTimestamp: {
|
||||
max: {
|
||||
field: '@timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
description: `Summarise the rollup data of SLO: ${slo.name} [id: ${slo.id}, revision: ${slo.revision}].`,
|
||||
frequency: '1m',
|
||||
sync: {
|
||||
time: {
|
||||
field: 'event.ingested',
|
||||
delay: '65s',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
deduce_mappings: false,
|
||||
unattended: true,
|
||||
},
|
||||
_meta: {
|
||||
version: SLO_RESOURCES_VERSION,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
import { ALL_VALUE } from '@kbn/slo-schema';
|
||||
import { SLO } from '../../../../domain/models';
|
||||
|
||||
export function createTempSummaryDocument(slo: SLO) {
|
||||
export function createTempSummaryDocument(slo: SLO, spaceId: string) {
|
||||
return {
|
||||
service: {
|
||||
environment: null,
|
||||
|
@ -33,6 +33,11 @@ export function createTempSummaryDocument(slo: SLO) {
|
|||
id: slo.id,
|
||||
budgetingMethod: slo.budgetingMethod,
|
||||
revision: slo.revision,
|
||||
objective: {
|
||||
target: slo.objective.target,
|
||||
timesliceTarget: slo.objective.timesliceTarget ?? null,
|
||||
timesliceWindow: slo.objective.timesliceWindow?.format() ?? null,
|
||||
},
|
||||
tags: slo.tags,
|
||||
},
|
||||
goodEvents: 0,
|
||||
|
@ -45,5 +50,6 @@ export function createTempSummaryDocument(slo: SLO) {
|
|||
statusCode: 0,
|
||||
status: 'NO_DATA',
|
||||
isTempDoc: true,
|
||||
spaceId,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { SLO } from '../../../domain/models';
|
||||
import { generateSummaryTransformForOccurrences } from './generators/occurrences';
|
||||
import { generateSummaryTransformForTimeslicesAndRolling } from './generators/timeslices_rolling';
|
||||
import { generateSummaryTransformForTimeslicesAndCalendarAligned } from './generators/timeslices_calendar_aligned';
|
||||
|
||||
export interface SummaryTransformGenerator {
|
||||
generate(slo: SLO): TransformPutTransformRequest;
|
||||
}
|
||||
|
||||
export class DefaultSummaryTransformGenerator implements SummaryTransformGenerator {
|
||||
public generate(slo: SLO): TransformPutTransformRequest {
|
||||
if (slo.budgetingMethod === 'occurrences') {
|
||||
return generateSummaryTransformForOccurrences(slo);
|
||||
} else if (slo.budgetingMethod === 'timeslices' && slo.timeWindow.type === 'rolling') {
|
||||
return generateSummaryTransformForTimeslicesAndRolling(slo);
|
||||
} else if (slo.budgetingMethod === 'timeslices' && slo.timeWindow.type === 'calendarAligned') {
|
||||
return generateSummaryTransformForTimeslicesAndCalendarAligned(slo);
|
||||
}
|
||||
|
||||
throw new Error('Not supported SLO');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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, Logger } from '@kbn/core/server';
|
||||
|
||||
import { SLO } from '../../domain/models';
|
||||
import { SecurityException } from '../../errors';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
import { SummaryTransformGenerator } from './summary_transform_generator/summary_transform_generator';
|
||||
import { TransformManager } from './transform_manager';
|
||||
|
||||
type TransformId = string;
|
||||
|
||||
export class DefaultSummaryTransformManager implements TransformManager {
|
||||
constructor(
|
||||
private generator: SummaryTransformGenerator,
|
||||
private esClient: ElasticsearchClient,
|
||||
private logger: Logger
|
||||
) {}
|
||||
|
||||
async install(slo: SLO): Promise<TransformId> {
|
||||
const transformParams = this.generator.generate(slo);
|
||||
try {
|
||||
await retryTransientEsErrors(() => this.esClient.transform.putTransform(transformParams), {
|
||||
logger: this.logger,
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.error(`Cannot create summary transform for SLO [${slo.id}]`);
|
||||
if (err.meta?.body?.error?.type === 'security_exception') {
|
||||
throw new SecurityException(err.meta.body.error.reason);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
return transformParams.transform_id;
|
||||
}
|
||||
|
||||
async preview(transformId: string): Promise<void> {
|
||||
try {
|
||||
await retryTransientEsErrors(
|
||||
() => this.esClient.transform.previewTransform({ transform_id: transformId }),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(`Cannot preview SLO summary transform [${transformId}]`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async start(transformId: TransformId): Promise<void> {
|
||||
try {
|
||||
await retryTransientEsErrors(
|
||||
() =>
|
||||
this.esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(`Cannot start SLO summary transform [${transformId}]`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async stop(transformId: TransformId): Promise<void> {
|
||||
try {
|
||||
await retryTransientEsErrors(
|
||||
() =>
|
||||
this.esClient.transform.stopTransform(
|
||||
{ transform_id: transformId, wait_for_completion: true, force: true },
|
||||
{ ignore: [404] }
|
||||
),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(`Cannot stop SLO summary transform [${transformId}]`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async uninstall(transformId: TransformId): Promise<void> {
|
||||
try {
|
||||
await retryTransientEsErrors(
|
||||
() =>
|
||||
this.esClient.transform.deleteTransform(
|
||||
{ transform_id: transformId, force: true },
|
||||
{ ignore: [404] }
|
||||
),
|
||||
{ logger: this.logger }
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error(`Cannot delete SLO summary transform [${transformId}]`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -190,66 +190,21 @@ 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",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -304,66 +259,21 @@ 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",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -413,66 +323,21 @@ 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",
|
||||
|
@ -527,66 +392,21 @@ 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",
|
||||
|
@ -600,12 +420,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -660,71 +480,21 @@ 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",
|
||||
|
@ -794,33 +564,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -830,48 +576,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -880,7 +590,7 @@ Object {
|
|||
"field": "@timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -889,12 +599,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -940,66 +650,21 @@ 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",
|
||||
|
@ -1069,33 +734,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -1105,42 +746,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -1149,6 +760,6 @@ Object {
|
|||
"field": "@timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -178,66 +178,21 @@ 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",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -288,66 +243,21 @@ 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",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -393,66 +303,21 @@ 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",
|
||||
|
@ -503,66 +368,21 @@ 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",
|
||||
|
@ -576,12 +396,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -629,71 +449,21 @@ 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",
|
||||
|
@ -759,33 +529,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -795,48 +541,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -845,7 +555,7 @@ Object {
|
|||
"field": "@timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -854,12 +564,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -898,66 +608,21 @@ 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",
|
||||
|
@ -1023,33 +688,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -1059,42 +700,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -1103,6 +714,6 @@ Object {
|
|||
"field": "@timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -77,12 +77,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -151,71 +151,21 @@ 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 {
|
||||
|
@ -253,33 +203,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -289,48 +215,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -339,7 +229,7 @@ Object {
|
|||
"field": "log_timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -348,12 +238,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -413,66 +303,21 @@ 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 {
|
||||
|
@ -510,33 +355,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -546,42 +367,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -590,6 +381,6 @@ Object {
|
|||
"field": "log_timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -118,12 +118,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -166,71 +166,21 @@ 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 {
|
||||
|
@ -268,33 +218,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -304,48 +230,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -354,7 +244,7 @@ Object {
|
|||
"field": "log_timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -363,12 +253,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -402,66 +292,21 @@ 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 {
|
||||
|
@ -499,33 +344,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -535,42 +356,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -579,6 +370,6 @@ Object {
|
|||
"field": "log_timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -117,12 +117,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -203,71 +203,21 @@ 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 {
|
||||
|
@ -305,33 +255,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -341,48 +267,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -391,7 +281,7 @@ Object {
|
|||
"field": "log_timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -400,12 +290,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -477,66 +367,21 @@ 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 {
|
||||
|
@ -574,33 +419,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -610,42 +431,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -654,7 +445,7 @@ Object {
|
|||
"field": "log_timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -33,12 +33,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -173,71 +173,21 @@ 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 {
|
||||
|
@ -272,33 +222,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -308,48 +234,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -358,7 +248,7 @@ Object {
|
|||
"field": "@timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -367,12 +257,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
},
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant",
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v2",
|
||||
"pipeline": ".slo-observability.sli.pipeline",
|
||||
"index": ".slo-observability.sli-v3",
|
||||
"pipeline": ".slo-observability.sli.pipeline-v3",
|
||||
},
|
||||
"frequency": "1m",
|
||||
"pivot": Object {
|
||||
|
@ -507,71 +397,21 @@ 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 {
|
||||
|
@ -606,33 +446,9 @@ 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')",
|
||||
"source": "emit('irrelevant')",
|
||||
},
|
||||
"type": "keyword",
|
||||
},
|
||||
|
@ -642,48 +458,12 @@ Object {
|
|||
},
|
||||
"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 {
|
||||
|
@ -692,6 +472,6 @@ Object {
|
|||
"field": "@timestamp",
|
||||
},
|
||||
},
|
||||
"transform_id": Any<String>,
|
||||
"transform_id": "slo-irrelevant-1",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -17,32 +17,20 @@ const generator = new ApmTransactionDurationTransformGenerator();
|
|||
|
||||
describe('APM Transaction Duration Transform Generator', () => {
|
||||
it('returns the expected transform params with every specified indicator params', () => {
|
||||
const slo = createSLO({ indicator: createAPMTransactionDurationIndicator() });
|
||||
const slo = createSLO({ id: 'irrelevant', indicator: createAPMTransactionDurationIndicator() });
|
||||
const transform = generator.getTransformParams(slo);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform.transform_id).toEqual(`slo-${slo.id}-${slo.revision}`);
|
||||
expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({
|
||||
script: { source: `emit('${slo.id}')` },
|
||||
});
|
||||
expect(transform.source.runtime_mappings!['slo.revision']).toMatchObject({
|
||||
script: { source: `emit(${slo.revision})` },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns the expected transform params for timeslices slo', () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod({
|
||||
id: 'irrelevant',
|
||||
indicator: createAPMTransactionDurationIndicator(),
|
||||
});
|
||||
const transform = generator.getTransformParams(slo);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not include the query filter when params are '*'", () => {
|
||||
|
|
|
@ -17,32 +17,23 @@ const generator = new ApmTransactionErrorRateTransformGenerator();
|
|||
|
||||
describe('APM Transaction Error Rate Transform Generator', () => {
|
||||
it('returns the expected transform params with every specified indicator params', async () => {
|
||||
const slo = createSLO({ indicator: createAPMTransactionErrorRateIndicator() });
|
||||
const transform = generator.getTransformParams(slo);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform.transform_id).toEqual(`slo-${slo.id}-${slo.revision}`);
|
||||
expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({
|
||||
script: { source: `emit('${slo.id}')` },
|
||||
});
|
||||
expect(transform.source.runtime_mappings!['slo.revision']).toMatchObject({
|
||||
script: { source: `emit(${slo.revision})` },
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the expected transform params for timeslices slo', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod({
|
||||
const slo = createSLO({
|
||||
id: 'irrelevant',
|
||||
indicator: createAPMTransactionErrorRateIndicator(),
|
||||
});
|
||||
const transform = generator.getTransformParams(slo);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns the expected transform params for timeslices slo', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod({
|
||||
id: 'irrelevant',
|
||||
indicator: createAPMTransactionErrorRateIndicator(),
|
||||
});
|
||||
const transform = generator.getTransformParams(slo);
|
||||
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not include the query filter when params are '*'", async () => {
|
||||
|
|
|
@ -30,6 +30,7 @@ describe('Histogram Transform Generator', () => {
|
|||
});
|
||||
expect(() => generator.getTransformParams(anSLO)).toThrow(/Invalid KQL: foo:/);
|
||||
});
|
||||
|
||||
it('throws when the total filter is invalid', () => {
|
||||
const anSLO = createSLO({
|
||||
indicator: createHistogramIndicator({
|
||||
|
@ -42,6 +43,7 @@ describe('Histogram Transform Generator', () => {
|
|||
});
|
||||
expect(() => generator.getTransformParams(anSLO)).toThrow(/Invalid KQL: foo:/);
|
||||
});
|
||||
|
||||
it('throws when the query_filter is invalid', () => {
|
||||
const anSLO = createSLO({
|
||||
indicator: createHistogramIndicator({ filter: '{ kql.query: invalid' }),
|
||||
|
@ -51,32 +53,20 @@ describe('Histogram Transform Generator', () => {
|
|||
});
|
||||
|
||||
it('returns the expected transform params with every specified indicator params', async () => {
|
||||
const anSLO = createSLO({ indicator: createHistogramIndicator() });
|
||||
const anSLO = createSLO({ id: 'irrelevant', indicator: createHistogramIndicator() });
|
||||
const transform = generator.getTransformParams(anSLO);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform.transform_id).toEqual(`slo-${anSLO.id}-${anSLO.revision}`);
|
||||
expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({
|
||||
script: { source: `emit('${anSLO.id}')` },
|
||||
});
|
||||
expect(transform.source.runtime_mappings!['slo.revision']).toMatchObject({
|
||||
script: { source: `emit(${anSLO.revision})` },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns the expected transform params for timeslices slo', async () => {
|
||||
const anSLO = createSLOWithTimeslicesBudgetingMethod({
|
||||
id: 'irrelevant',
|
||||
indicator: createHistogramIndicator(),
|
||||
});
|
||||
const transform = generator.getTransformParams(anSLO);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('filters the source using the kql query', async () => {
|
||||
|
|
|
@ -37,32 +37,20 @@ describe('KQL Custom Transform Generator', () => {
|
|||
});
|
||||
|
||||
it('returns the expected transform params with every specified indicator params', async () => {
|
||||
const anSLO = createSLO({ indicator: createKQLCustomIndicator() });
|
||||
const anSLO = createSLO({ id: 'irrelevant', indicator: createKQLCustomIndicator() });
|
||||
const transform = generator.getTransformParams(anSLO);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform.transform_id).toEqual(`slo-${anSLO.id}-${anSLO.revision}`);
|
||||
expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({
|
||||
script: { source: `emit('${anSLO.id}')` },
|
||||
});
|
||||
expect(transform.source.runtime_mappings!['slo.revision']).toMatchObject({
|
||||
script: { source: `emit(${anSLO.revision})` },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns the expected transform params for timeslices slo', async () => {
|
||||
const anSLO = createSLOWithTimeslicesBudgetingMethod({
|
||||
id: 'irrelevant',
|
||||
indicator: createKQLCustomIndicator(),
|
||||
});
|
||||
const transform = generator.getTransformParams(anSLO);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('filters the source using the kql query', async () => {
|
||||
|
|
|
@ -69,32 +69,20 @@ describe('Metric Custom Transform Generator', () => {
|
|||
});
|
||||
|
||||
it('returns the expected transform params with every specified indicator params', async () => {
|
||||
const anSLO = createSLO({ indicator: createMetricCustomIndicator() });
|
||||
const anSLO = createSLO({ id: 'irrelevant', indicator: createMetricCustomIndicator() });
|
||||
const transform = generator.getTransformParams(anSLO);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform.transform_id).toEqual(`slo-${anSLO.id}-${anSLO.revision}`);
|
||||
expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({
|
||||
script: { source: `emit('${anSLO.id}')` },
|
||||
});
|
||||
expect(transform.source.runtime_mappings!['slo.revision']).toMatchObject({
|
||||
script: { source: `emit(${anSLO.revision})` },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns the expected transform params for timeslices slo', async () => {
|
||||
const anSLO = createSLOWithTimeslicesBudgetingMethod({
|
||||
id: 'irrelevant',
|
||||
indicator: createMetricCustomIndicator(),
|
||||
});
|
||||
const transform = generator.getTransformParams(anSLO);
|
||||
|
||||
expect(transform).toMatchSnapshot({
|
||||
transform_id: expect.any(String),
|
||||
source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } },
|
||||
});
|
||||
expect(transform).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('filters the source using the kql query', async () => {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue