mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
feat(composite_slo): create schemas and route boilerplates (#158381)
This commit is contained in:
parent
43d751e37d
commit
0d2a1083c0
16 changed files with 384 additions and 9 deletions
|
@ -2097,6 +2097,32 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"composite-slo": {
|
||||
"dynamic": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"type": "text"
|
||||
},
|
||||
"budgetingMethod": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"compositeMethod": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"sources": {
|
||||
"properties": {
|
||||
"id": { "type": "keyword" },
|
||||
"revision": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"observability-onboarding-state": {
|
||||
"properties": {
|
||||
"state": {
|
||||
|
|
139
packages/kbn-slo-schema/src/rest_specs/composite_slo.ts
Normal file
139
packages/kbn-slo-schema/src/rest_specs/composite_slo.ts
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import {
|
||||
budgetingMethodSchema,
|
||||
compositeSloIdSchema,
|
||||
dateType,
|
||||
rollingTimeWindowSchema,
|
||||
summarySchema,
|
||||
tagsSchema,
|
||||
targetSchema,
|
||||
weightedAverageCompositeMethodSchema,
|
||||
weightedAverageSourceSchema,
|
||||
} from '../schema';
|
||||
|
||||
const createCompositeSLOParamsSchema = t.type({
|
||||
body: t.intersection([
|
||||
t.type({
|
||||
name: t.string,
|
||||
timeWindow: rollingTimeWindowSchema,
|
||||
budgetingMethod: budgetingMethodSchema,
|
||||
objective: targetSchema,
|
||||
compositeMethod: weightedAverageCompositeMethodSchema,
|
||||
sources: t.array(weightedAverageSourceSchema),
|
||||
}),
|
||||
t.partial({ id: compositeSloIdSchema, tags: tagsSchema }),
|
||||
]),
|
||||
});
|
||||
|
||||
const createCompositeSLOResponseSchema = t.type({
|
||||
id: compositeSloIdSchema,
|
||||
});
|
||||
|
||||
const compositeSLOResponseSchema = t.type({
|
||||
id: compositeSloIdSchema,
|
||||
name: t.string,
|
||||
timeWindow: rollingTimeWindowSchema,
|
||||
budgetingMethod: budgetingMethodSchema,
|
||||
objective: targetSchema,
|
||||
compositeMethod: weightedAverageCompositeMethodSchema,
|
||||
sources: t.array(weightedAverageSourceSchema),
|
||||
tags: tagsSchema,
|
||||
createdAt: dateType,
|
||||
updatedAt: dateType,
|
||||
});
|
||||
|
||||
const compositeSLOWithSummaryResponseSchema = t.intersection([
|
||||
compositeSLOResponseSchema,
|
||||
t.type({ summary: summarySchema }),
|
||||
]);
|
||||
|
||||
const updateCompositeSLOParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: compositeSloIdSchema,
|
||||
}),
|
||||
body: t.partial({
|
||||
name: t.string,
|
||||
compositeMethod: weightedAverageCompositeMethodSchema,
|
||||
sources: t.array(weightedAverageSourceSchema),
|
||||
timeWindow: rollingTimeWindowSchema,
|
||||
budgetingMethod: budgetingMethodSchema,
|
||||
objective: targetSchema,
|
||||
tags: tagsSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
const updateCompositeSLOResponseSchema = compositeSLOResponseSchema;
|
||||
|
||||
const deleteCompositeSLOParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: compositeSloIdSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
const getCompositeSLOParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: compositeSloIdSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
const getCompositeSLOResponseSchema = compositeSLOWithSummaryResponseSchema;
|
||||
|
||||
const sortDirectionSchema = t.union([t.literal('asc'), t.literal('desc')]);
|
||||
const sortBySchema = t.literal('creationTime');
|
||||
const findCompositeSLOParamsSchema = t.partial({
|
||||
query: t.partial({
|
||||
name: t.string,
|
||||
page: t.string,
|
||||
perPage: t.string,
|
||||
sortBy: sortBySchema,
|
||||
sortDirection: sortDirectionSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
const findCompositeSLOResponseSchema = t.type({
|
||||
page: t.number,
|
||||
perPage: t.number,
|
||||
total: t.number,
|
||||
results: t.array(compositeSLOWithSummaryResponseSchema),
|
||||
});
|
||||
|
||||
type CreateCompositeSLOInput = t.OutputOf<typeof createCompositeSLOParamsSchema.props.body>; // Raw payload sent by the frontend
|
||||
type CreateCompositeSLOParams = t.TypeOf<typeof createCompositeSLOParamsSchema.props.body>; // Parsed payload used by the backend
|
||||
type CreateCompositeSLOResponse = t.TypeOf<typeof createCompositeSLOResponseSchema>; // Raw response sent to the frontend
|
||||
|
||||
type GetCompositeSLOResponse = t.OutputOf<typeof getCompositeSLOResponseSchema>;
|
||||
|
||||
type FindCompositeSLOParams = t.TypeOf<typeof findCompositeSLOParamsSchema.props.query>;
|
||||
type FindCompositeSLOResponse = t.OutputOf<typeof findCompositeSLOResponseSchema>;
|
||||
|
||||
type UpdateCompositeSLOInput = t.OutputOf<typeof updateCompositeSLOParamsSchema.props.body>;
|
||||
type UpdateCompositeSLOParams = t.TypeOf<typeof updateCompositeSLOParamsSchema.props.body>;
|
||||
type UpdateCompositeSLOResponse = t.TypeOf<typeof updateCompositeSLOResponseSchema>;
|
||||
|
||||
export {
|
||||
createCompositeSLOParamsSchema,
|
||||
deleteCompositeSLOParamsSchema,
|
||||
findCompositeSLOParamsSchema,
|
||||
getCompositeSLOParamsSchema,
|
||||
updateCompositeSLOParamsSchema,
|
||||
};
|
||||
|
||||
export type {
|
||||
CreateCompositeSLOInput,
|
||||
CreateCompositeSLOParams,
|
||||
CreateCompositeSLOResponse,
|
||||
FindCompositeSLOParams,
|
||||
FindCompositeSLOResponse,
|
||||
GetCompositeSLOResponse,
|
||||
UpdateCompositeSLOInput,
|
||||
UpdateCompositeSLOParams,
|
||||
UpdateCompositeSLOResponse,
|
||||
};
|
|
@ -6,4 +6,5 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './composite_slo';
|
||||
export * from './slo';
|
||||
|
|
42
packages/kbn-slo-schema/src/schema/composite_slo.ts
Normal file
42
packages/kbn-slo-schema/src/schema/composite_slo.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
import { dateType } from './common';
|
||||
import { budgetingMethodSchema, sloIdSchema, tagsSchema, targetSchema } from './slo';
|
||||
import { rollingTimeWindowSchema } from './time_window';
|
||||
|
||||
const compositeSloIdSchema = t.string;
|
||||
|
||||
const weightedAverageCompositeMethodSchema = t.literal('weightedAverage');
|
||||
const weightedAverageSourceSchema = t.type({
|
||||
id: sloIdSchema,
|
||||
revision: t.number,
|
||||
weight: t.number,
|
||||
});
|
||||
|
||||
const compositeSloSchema = t.type({
|
||||
id: compositeSloIdSchema,
|
||||
name: t.string,
|
||||
timeWindow: rollingTimeWindowSchema,
|
||||
budgetingMethod: budgetingMethodSchema,
|
||||
compositeMethod: weightedAverageCompositeMethodSchema,
|
||||
objective: targetSchema,
|
||||
sources: t.array(weightedAverageSourceSchema),
|
||||
tags: tagsSchema,
|
||||
createdAt: dateType,
|
||||
updatedAt: dateType,
|
||||
});
|
||||
|
||||
export {
|
||||
weightedAverageSourceSchema,
|
||||
weightedAverageCompositeMethodSchema,
|
||||
compositeSloIdSchema,
|
||||
compositeSloSchema,
|
||||
};
|
|
@ -6,8 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './slo';
|
||||
export * from './common';
|
||||
export * from './indicators';
|
||||
export * from './composite_slo';
|
||||
export * from './duration';
|
||||
export * from './indicators';
|
||||
export * from './time_window';
|
||||
export * from './slo';
|
||||
|
|
|
@ -20,8 +20,10 @@ const budgetingMethodSchema = t.union([
|
|||
timeslicesBudgetingMethodSchema,
|
||||
]);
|
||||
|
||||
const targetSchema = t.type({ target: t.number });
|
||||
|
||||
const objectiveSchema = t.intersection([
|
||||
t.type({ target: t.number }),
|
||||
targetSchema,
|
||||
t.partial({ timesliceTarget: t.number, timesliceWindow: durationType }),
|
||||
]);
|
||||
|
||||
|
@ -64,5 +66,6 @@ export {
|
|||
sloSchema,
|
||||
sloWithSummarySchema,
|
||||
tagsSchema,
|
||||
targetSchema,
|
||||
timeslicesBudgetingMethodSchema,
|
||||
};
|
||||
|
|
|
@ -75,6 +75,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
|
|||
"cases-connector-mappings": "f9d1ac57e484e69506c36a8051e4d61f4a8cfd25",
|
||||
"cases-telemetry": "f219eb7e26772884342487fc9602cfea07b3cedc",
|
||||
"cases-user-actions": "483f10db9b3bd1617948d7032a98b7791bf87414",
|
||||
"composite-slo": "d771c24af50d7ca5667a046b63ed024a4bfd819d",
|
||||
"config": "179b3e2bc672626aafce3cf92093a113f456af38",
|
||||
"config-global": "8e8a134a2952df700d7d4ec51abb794bbd4cf6da",
|
||||
"connector_token": "5a9ac29fe9c740eb114e9c40517245c71706b005",
|
||||
|
|
|
@ -190,6 +190,7 @@ describe('split .kibana index into multiple system indices', () => {
|
|||
"cases-connector-mappings",
|
||||
"cases-telemetry",
|
||||
"cases-user-actions",
|
||||
"composite-slo",
|
||||
"config",
|
||||
"config-global",
|
||||
"connector_token",
|
||||
|
|
|
@ -38,6 +38,7 @@ const previouslyRegisteredTypes = [
|
|||
'config',
|
||||
'config-global',
|
||||
'connector_token',
|
||||
'composite-slo',
|
||||
'core-usage-stats',
|
||||
'csp-rule-template',
|
||||
'csp_rule',
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
import { compositeSloSchema, compositeSloIdSchema } from '@kbn/slo-schema';
|
||||
|
||||
type CompositeSLO = t.TypeOf<typeof compositeSloSchema>;
|
||||
type CompositeSLOId = t.TypeOf<typeof compositeSloIdSchema>;
|
||||
type StoredCompositeSLO = t.OutputOf<typeof compositeSloSchema>;
|
||||
|
||||
export type { CompositeSLO, CompositeSLOId, StoredCompositeSLO };
|
|
@ -41,7 +41,7 @@ import { uiSettings } from './ui_settings';
|
|||
import { registerRoutes } from './routes/register_routes';
|
||||
import { getObservabilityServerRouteRepository } from './routes/get_global_observability_server_route_repository';
|
||||
import { casesFeatureId, observabilityFeatureId, sloFeatureId } from '../common';
|
||||
import { slo, SO_SLO_TYPE } from './saved_objects';
|
||||
import { compositeSlo, slo, SO_COMPOSITE_SLO_TYPE, SO_SLO_TYPE } from './saved_objects';
|
||||
import { SLO_RULE_REGISTRATION_CONTEXT } from './common/constants';
|
||||
import { registerRuleTypes } from './lib/rules/register_rule_types';
|
||||
import { SLO_BURN_RATE_RULE_ID } from '../common/constants';
|
||||
|
@ -187,7 +187,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
catalogue: [sloFeatureId, 'observability'],
|
||||
api: ['slo_write', 'slo_read', 'rac'],
|
||||
savedObject: {
|
||||
all: [SO_SLO_TYPE],
|
||||
all: [SO_SLO_TYPE, SO_COMPOSITE_SLO_TYPE],
|
||||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
|
@ -206,7 +206,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
api: ['slo_read', 'rac'],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [SO_SLO_TYPE],
|
||||
read: [SO_SLO_TYPE, SO_COMPOSITE_SLO_TYPE],
|
||||
},
|
||||
alerting: {
|
||||
rule: {
|
||||
|
@ -222,6 +222,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
});
|
||||
|
||||
core.savedObjects.registerType(slo);
|
||||
core.savedObjects.registerType(compositeSlo);
|
||||
|
||||
const ruleDataClient = ruleDataService.initializeIndex({
|
||||
feature: sloFeatureId,
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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 { badRequest, notImplemented } from '@hapi/boom';
|
||||
import {
|
||||
createCompositeSLOParamsSchema,
|
||||
deleteCompositeSLOParamsSchema,
|
||||
findCompositeSLOParamsSchema,
|
||||
getCompositeSLOParamsSchema,
|
||||
updateCompositeSLOParamsSchema,
|
||||
} from '@kbn/slo-schema';
|
||||
|
||||
import { ObservabilityRequestHandlerContext } from '../../types';
|
||||
import { createObservabilityServerRoute } from '../create_observability_server_route';
|
||||
|
||||
const assertLicenseAtLeastPlatinum = async (context: ObservabilityRequestHandlerContext) => {
|
||||
const { license } = await context.licensing;
|
||||
if (!license.hasAtLeast('platinum')) {
|
||||
throw badRequest('Platinum license or higher is needed to make use of this feature.');
|
||||
}
|
||||
};
|
||||
|
||||
const createCompositeSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'POST /api/observability/composite_slos 2023-05-24',
|
||||
options: {
|
||||
tags: ['access:slo_write'],
|
||||
},
|
||||
params: createCompositeSLOParamsSchema,
|
||||
handler: async ({ context }) => {
|
||||
await assertLicenseAtLeastPlatinum(context);
|
||||
|
||||
throw notImplemented();
|
||||
},
|
||||
});
|
||||
|
||||
const updateCompositeSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'PUT /api/observability/composite_slos/{id} 2023-05-24',
|
||||
options: {
|
||||
tags: ['access:slo_write'],
|
||||
},
|
||||
params: updateCompositeSLOParamsSchema,
|
||||
handler: async ({ context }) => {
|
||||
await assertLicenseAtLeastPlatinum(context);
|
||||
|
||||
throw notImplemented();
|
||||
},
|
||||
});
|
||||
|
||||
const deleteCompositeSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'DELETE /api/observability/composite_slos/{id} 2023-05-24',
|
||||
options: {
|
||||
tags: ['access:slo_write'],
|
||||
},
|
||||
params: deleteCompositeSLOParamsSchema,
|
||||
handler: async ({ context }) => {
|
||||
await assertLicenseAtLeastPlatinum(context);
|
||||
|
||||
throw notImplemented();
|
||||
},
|
||||
});
|
||||
|
||||
const getCompositeSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'GET /api/observability/composite_slos/{id} 2023-05-24',
|
||||
options: {
|
||||
tags: ['access:slo_read'],
|
||||
},
|
||||
params: getCompositeSLOParamsSchema,
|
||||
handler: async ({ context }) => {
|
||||
await assertLicenseAtLeastPlatinum(context);
|
||||
|
||||
throw notImplemented();
|
||||
},
|
||||
});
|
||||
|
||||
const findCompositeSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'GET /api/observability/composite_slos 2023-05-24',
|
||||
options: {
|
||||
tags: ['access:slo_read'],
|
||||
},
|
||||
params: findCompositeSLOParamsSchema,
|
||||
handler: async ({ context }) => {
|
||||
await assertLicenseAtLeastPlatinum(context);
|
||||
|
||||
throw notImplemented();
|
||||
},
|
||||
});
|
||||
|
||||
export const compositeSloRouteRepository = {
|
||||
...createCompositeSLORoute,
|
||||
...updateCompositeSLORoute,
|
||||
...deleteCompositeSLORoute,
|
||||
...getCompositeSLORoute,
|
||||
...findCompositeSLORoute,
|
||||
};
|
|
@ -5,13 +5,15 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { compositeSloRouteRepository } from './composite_slo/route';
|
||||
import { rulesRouteRepository } from './rules/route';
|
||||
import { slosRouteRepository } from './slo/route';
|
||||
import { sloRouteRepository } from './slo/route';
|
||||
|
||||
export function getObservabilityServerRouteRepository() {
|
||||
const repository = {
|
||||
...rulesRouteRepository,
|
||||
...slosRouteRepository,
|
||||
...sloRouteRepository,
|
||||
...compositeSloRouteRepository,
|
||||
};
|
||||
return repository;
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ const getSloDiagnosisRoute = createObservabilityServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
export const slosRouteRepository = {
|
||||
export const sloRouteRepository = {
|
||||
...createSLORoute,
|
||||
...deleteSLORoute,
|
||||
...disableSLORoute,
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SavedObjectsType } from '@kbn/core-saved-objects-server';
|
||||
import { SavedObject } from '@kbn/core/server';
|
||||
|
||||
import { StoredCompositeSLO } from '../domain/models/composite_slo';
|
||||
|
||||
export const SO_COMPOSITE_SLO_TYPE = 'composite-slo';
|
||||
|
||||
export const compositeSlo: SavedObjectsType = {
|
||||
name: SO_COMPOSITE_SLO_TYPE,
|
||||
hidden: false,
|
||||
namespaceType: 'multiple-isolated',
|
||||
mappings: {
|
||||
dynamic: false,
|
||||
properties: {
|
||||
id: { type: 'keyword' },
|
||||
name: { type: 'text' },
|
||||
budgetingMethod: { type: 'keyword' },
|
||||
compositeMethod: { type: 'keyword' },
|
||||
sources: {
|
||||
properties: {
|
||||
id: { type: 'keyword' },
|
||||
revision: { type: 'integer' },
|
||||
},
|
||||
},
|
||||
tags: { type: 'keyword' },
|
||||
},
|
||||
},
|
||||
management: {
|
||||
displayName: 'Composite SLO',
|
||||
importableAndExportable: true,
|
||||
getTitle(compositeSloSavedObject: SavedObject<StoredCompositeSLO>) {
|
||||
return `Composite SLO: [${compositeSloSavedObject.attributes.name}]`;
|
||||
},
|
||||
},
|
||||
};
|
|
@ -6,3 +6,4 @@
|
|||
*/
|
||||
|
||||
export { slo, SO_SLO_TYPE } from './slo';
|
||||
export { compositeSlo, SO_COMPOSITE_SLO_TYPE } from './composite_slo';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue