mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[SLOs] Added createdBy and updatedBy fields in summary documents !! (#205784)
## Summary Added createdBy and updatedBy fields in summary documents !! This will make easier to identify which user have added the SLO and which user last updated the SLO. It's especially helpful where there are 100s of SLOs defined. <img width="1728" alt="image" src="https://github.com/user-attachments/assets/ee7bb4d4-a8ea-40c4-8d91-06c32c9b0ba6" /> --------- Co-authored-by: Kevin Delemme <kdelemme@gmail.com> Co-authored-by: Kevin Delemme <kevin.delemme@elastic.co>
This commit is contained in:
parent
a555d57261
commit
39119b553e
41 changed files with 391 additions and 142 deletions
|
@ -77,23 +77,29 @@ function isValidId(id: string): boolean {
|
|||
return validLength && /^[a-z0-9-_]+$/.test(id);
|
||||
}
|
||||
|
||||
const sloDefinitionSchema = t.type({
|
||||
id: sloIdSchema,
|
||||
name: t.string,
|
||||
description: t.string,
|
||||
indicator: indicatorSchema,
|
||||
timeWindow: timeWindowSchema,
|
||||
budgetingMethod: budgetingMethodSchema,
|
||||
objective: objectiveSchema,
|
||||
settings: settingsSchema,
|
||||
revision: t.number,
|
||||
enabled: t.boolean,
|
||||
tags: tagsSchema,
|
||||
createdAt: dateType,
|
||||
updatedAt: dateType,
|
||||
groupBy: groupBySchema,
|
||||
version: t.number,
|
||||
});
|
||||
const sloDefinitionSchema = t.intersection([
|
||||
t.type({
|
||||
id: sloIdSchema,
|
||||
name: t.string,
|
||||
description: t.string,
|
||||
indicator: indicatorSchema,
|
||||
timeWindow: timeWindowSchema,
|
||||
budgetingMethod: budgetingMethodSchema,
|
||||
objective: objectiveSchema,
|
||||
settings: settingsSchema,
|
||||
revision: t.number,
|
||||
enabled: t.boolean,
|
||||
tags: tagsSchema,
|
||||
createdAt: dateType,
|
||||
updatedAt: dateType,
|
||||
groupBy: groupBySchema,
|
||||
version: t.number,
|
||||
}),
|
||||
t.partial({
|
||||
createdBy: t.string,
|
||||
updatedBy: t.string,
|
||||
}),
|
||||
]);
|
||||
|
||||
export {
|
||||
budgetingMethodSchema,
|
||||
|
|
|
@ -41104,7 +41104,6 @@
|
|||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel": "{numOfSlos, number} {numOfSlos, plural, other {SLO}} inclus",
|
||||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.instancesCount": "({count, number} {count, plural, one {Instance} other {Instances}})",
|
||||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.withInstances": "{numOfSlos, number} {numOfSlos, plural, other {SLO}}{instances} inclus",
|
||||
"xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel": "{status}, dernière mise à jour : {value}",
|
||||
"xpack.slo.sloCardItemBadges.remoteBadgeLabel": "Distant",
|
||||
"xpack.slo.sloConfiguration.euiSwitch.showAllGroupByLabel": "Afficher toutes les instances de regroupement associées ",
|
||||
"xpack.slo.sloCreatePageTitle": "Créer un nouveau SLO",
|
||||
|
@ -41128,8 +41127,6 @@
|
|||
"xpack.slo.sloDetails.headerControl.manageRules": "Gérer {count, plural, one {règle} other {règles}} du taux d'avancement",
|
||||
"xpack.slo.sloDetails.headerTitle.calloutDescription": "Il s'agit d'un SLO distant qui appartient à une autre instance Kibana. Il est extrait du cluster distant : {remoteName} avec l'URL Kibana {kibanaUrl}.",
|
||||
"xpack.slo.sloDetails.headerTitle.calloutMessage": "SLO distant",
|
||||
"xpack.slo.sloDetails.headerTitle.createdMessage": "Créé le",
|
||||
"xpack.slo.sloDetails.headerTitle.lastUpdatedMessage": "Dernière mise à jour le",
|
||||
"xpack.slo.sloDetails.healthCallout.buttonTransformLabel": "Inspecter la transformation",
|
||||
"xpack.slo.sloDetails.healthCallout.copyToClipboard": "Copier dans le presse-papiers",
|
||||
"xpack.slo.sloDetails.healthCallout.description": "{count, plural, one {La transformation suivante est} other {Les transformations suivantes sont} } dans un état défectueux :",
|
||||
|
|
|
@ -40961,7 +40961,6 @@
|
|||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel": "{numOfSlos, number} {numOfSlos, plural, other {SLO}}が含まれます",
|
||||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.instancesCount": "({count, number} {count, plural, other {インスタンス}})",
|
||||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.withInstances": "{numOfSlos, number} {numOfSlos, plural, other {SLO}}{instances}が含まれます",
|
||||
"xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel": "{status}、前回更新日:{value}",
|
||||
"xpack.slo.sloCardItemBadges.remoteBadgeLabel": "リモート",
|
||||
"xpack.slo.sloConfiguration.euiSwitch.showAllGroupByLabel": "インスタンス別にすべての関連するグループを表示",
|
||||
"xpack.slo.sloCreatePageTitle": "新規SLOを作成",
|
||||
|
@ -40985,8 +40984,6 @@
|
|||
"xpack.slo.sloDetails.headerControl.manageRules": "バーンレート{count, plural, other {ルール}}を管理",
|
||||
"xpack.slo.sloDetails.headerTitle.calloutDescription": "これは別のKibanaインスタンスに属するリモートSLOです。リモートクラスターから取得されます:Kibana URL {kibanaUrl}の{remoteName}。",
|
||||
"xpack.slo.sloDetails.headerTitle.calloutMessage": "リモートSLO",
|
||||
"xpack.slo.sloDetails.headerTitle.createdMessage": "作成日時",
|
||||
"xpack.slo.sloDetails.headerTitle.lastUpdatedMessage": "最終更新日",
|
||||
"xpack.slo.sloDetails.healthCallout.buttonTransformLabel": "変換を検査",
|
||||
"xpack.slo.sloDetails.healthCallout.copyToClipboard": "クリップボードにコピー",
|
||||
"xpack.slo.sloDetails.healthCallout.description": "次の{count, plural, other {変換は} }正常ではない状態です。",
|
||||
|
|
|
@ -40375,7 +40375,6 @@
|
|||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel": "已包括 {numOfSlos, number} 个 {numOfSlos, plural, other {SLO}}",
|
||||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.instancesCount": "({count, number} 个{count, plural, other {实例}})",
|
||||
"xpack.slo.sloAlertsWrapper.sLOsIncludedFlexItemLabel.withInstances": "已包括 {numOfSlos, number} 个 {numOfSlos, plural, other {SLO}}{instances}",
|
||||
"xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel": "{status},上次更新时间:{value}",
|
||||
"xpack.slo.sloCardItemBadges.remoteBadgeLabel": "远程",
|
||||
"xpack.slo.sloConfiguration.euiSwitch.showAllGroupByLabel": "显示所有相关分组依据实例",
|
||||
"xpack.slo.sloCreatePageTitle": "创建新 SLO",
|
||||
|
@ -40399,8 +40398,6 @@
|
|||
"xpack.slo.sloDetails.headerControl.manageRules": "管理消耗速度{count, plural, other {规则}}",
|
||||
"xpack.slo.sloDetails.headerTitle.calloutDescription": "这是一个远程 SLO,它属于其他 Kibana 实例。它是使用 Kibana URL {kibanaUrl} 从远程集群 {remoteName} 提取的。",
|
||||
"xpack.slo.sloDetails.headerTitle.calloutMessage": "远程 SLO",
|
||||
"xpack.slo.sloDetails.headerTitle.createdMessage": "创建日期",
|
||||
"xpack.slo.sloDetails.headerTitle.lastUpdatedMessage": "上次更新时间",
|
||||
"xpack.slo.sloDetails.healthCallout.buttonTransformLabel": "检查转换",
|
||||
"xpack.slo.sloDetails.healthCallout.copyToClipboard": "复制到剪贴板",
|
||||
"xpack.slo.sloDetails.healthCallout.description": "以下{count, plural, other {转换}}处于运行不正常状态:",
|
||||
|
|
|
@ -54,7 +54,7 @@ export const SUPPRESSED_PRIORITY_ACTION = {
|
|||
};
|
||||
|
||||
export const SLO_MODEL_VERSION = 2;
|
||||
export const SLO_RESOURCES_VERSION = 3.3;
|
||||
export const SLO_RESOURCES_VERSION = 3.4;
|
||||
export const SLO_RESOURCES_VERSION_MAJOR = 3;
|
||||
|
||||
export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSkeletonText, EuiText } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiMarkdownFormat, EuiSkeletonText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import moment from 'moment';
|
||||
|
@ -37,30 +37,43 @@ export function HeaderTitle({ isLoading, slo }: Props) {
|
|||
<SloStatusBadge slo={slo} />
|
||||
<SloStateBadge slo={slo} />
|
||||
<SloRemoteBadge slo={slo} />
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText color="subdued" size="xs">
|
||||
<strong>
|
||||
{i18n.translate('xpack.slo.sloDetails.headerTitle.lastUpdatedMessage', {
|
||||
defaultMessage: 'Last updated on',
|
||||
<EuiFlexGroup
|
||||
direction="row"
|
||||
gutterSize="m"
|
||||
alignItems="center"
|
||||
justifyContent="flexStart"
|
||||
responsive={false}
|
||||
wrap={true}
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiMarkdownFormat textSize="xs" color="subdued">
|
||||
{i18n.translate('xpack.slo.sloDetails.headerTitle.lastUpdatedLabel', {
|
||||
defaultMessage: '**Last updated by** {updatedBy} **on** {updatedAt}',
|
||||
values: {
|
||||
updatedBy: slo.updatedBy ?? NOT_AVAILABLE_LABEL,
|
||||
updatedAt: moment(slo.updatedAt).format('ll'),
|
||||
},
|
||||
})}
|
||||
</strong>
|
||||
|
||||
{moment(slo.updatedAt).format('ll')}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText color="subdued" size="xs">
|
||||
<strong>
|
||||
{i18n.translate('xpack.slo.sloDetails.headerTitle.createdMessage', {
|
||||
defaultMessage: 'Created on',
|
||||
</EuiMarkdownFormat>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiMarkdownFormat textSize="xs" color="subdued">
|
||||
{i18n.translate('xpack.slo.sloDetails.headerTitle.createdLabel', {
|
||||
defaultMessage: '**Created by** {createdBy} **on** {createdAt}',
|
||||
values: {
|
||||
createdBy: slo.createdBy ?? NOT_AVAILABLE_LABEL,
|
||||
createdAt: moment(slo.createdAt).format('ll'),
|
||||
},
|
||||
})}
|
||||
</strong>
|
||||
|
||||
{moment(slo.createdAt).format('ll')}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiMarkdownFormat>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexGroup>
|
||||
<SLOGroupings slo={slo} />
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const NOT_AVAILABLE_LABEL = i18n.translate('xpack.slo.sloDetails.headerTitle.notAvailableLabel', {
|
||||
defaultMessage: 'n/a',
|
||||
});
|
||||
|
|
|
@ -149,8 +149,8 @@ export function SloCardItem({ slo, rules, activeAlerts, historicalSummary, refet
|
|||
`}
|
||||
title={
|
||||
slo.summary.summaryUpdatedAt
|
||||
? i18n.translate('xpack.slo.sloCardItem.euiPanel.lastUpdatedLabel', {
|
||||
defaultMessage: '{status}, Last updated: {value}',
|
||||
? i18n.translate('xpack.slo.sloCardItem.euiPanel.lastSummaryUpdatedLabel', {
|
||||
defaultMessage: '{status}, Last summary updated: {value}',
|
||||
values: {
|
||||
status: slo.summary.status,
|
||||
value: moment(slo.summary.summaryUpdatedAt).fromNow(),
|
||||
|
|
|
@ -41,7 +41,7 @@ export function SLOCardItemInstanceBadge({ slo }: Props) {
|
|||
data-test-subj="o11ySlosSeeAllInstanceIdsBadge"
|
||||
>
|
||||
{`${i18n.translate('xpack.slo.extraInstanceIds.badge', {
|
||||
defaultMessage: '+{count, plural, one {# more instance} other {# more instances}}',
|
||||
defaultMessage: '+{count, plural, one {# instance} other {# instances}}',
|
||||
values: {
|
||||
count: entries.length - 1,
|
||||
},
|
||||
|
|
|
@ -68,7 +68,7 @@ export function SLOGroupings({ slo, direction = 'row', gutterSize = 's', truncat
|
|||
<EuiButtonEmpty data-test-subj="accordion" flush="left">
|
||||
{`(${i18n.translate('xpack.slo.andLabel', {
|
||||
defaultMessage:
|
||||
'and {count, plural, one {# more instance} other {# more instances}}',
|
||||
'and {count, plural, one {# instance} other {# instances}}',
|
||||
values: {
|
||||
count: rest.length,
|
||||
},
|
||||
|
|
|
@ -135,6 +135,20 @@ export const getSLOSummaryMappingsTemplate = (
|
|||
},
|
||||
},
|
||||
},
|
||||
createdAt: {
|
||||
type: 'date',
|
||||
format: 'date_optional_time||epoch_millis',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'date',
|
||||
format: 'date_optional_time||epoch_millis',
|
||||
},
|
||||
createdBy: {
|
||||
type: 'keyword',
|
||||
},
|
||||
updatedBy: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
sliValue: {
|
||||
|
|
|
@ -234,6 +234,21 @@ export const getSLOSummaryPipelineTemplate = (
|
|||
source: getBurnRateSource('oneDayBurnRate'),
|
||||
},
|
||||
},
|
||||
// >= 8.18: add updatedBy, createdBy
|
||||
{
|
||||
set: {
|
||||
field: 'slo.updatedBy',
|
||||
value: slo.updatedBy,
|
||||
ignore_failure: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
set: {
|
||||
field: 'slo.createdBy',
|
||||
value: slo.createdBy,
|
||||
ignore_failure: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
_meta: {
|
||||
description: `Ingest pipeline for SLO summary data [id: ${slo.id}, revision: ${slo.revision}]`,
|
||||
|
|
|
@ -143,7 +143,7 @@ describe('slo transform template', () => {
|
|||
},
|
||||
defer_validation: true,
|
||||
_meta: {
|
||||
version: 3.3,
|
||||
version: 3.4,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
|
@ -247,7 +247,7 @@ describe('slo transform template', () => {
|
|||
},
|
||||
defer_validation: true,
|
||||
_meta: {
|
||||
version: 3.3,
|
||||
version: 3.4,
|
||||
managed: true,
|
||||
managed_by: 'observability',
|
||||
},
|
||||
|
|
|
@ -86,12 +86,13 @@ const createSLORoute = createSloServerRoute({
|
|||
},
|
||||
},
|
||||
params: createSLOParamsSchema,
|
||||
handler: async ({ context, response, params, logger, request, plugins, corePlugins }) => {
|
||||
handler: async ({ context, params, logger, request, plugins, corePlugins }) => {
|
||||
await assertPlatinumLicense(plugins);
|
||||
|
||||
const sloContext = await context.slo;
|
||||
const dataViews = await plugins.dataViews.start();
|
||||
const core = await context.core;
|
||||
const userId = core.security.authc.getCurrentUser()?.username!;
|
||||
const scopedClusterClient = core.elasticsearch.client;
|
||||
const esClient = core.elasticsearch.client.asCurrentUser;
|
||||
const soClient = core.savedObjects.client;
|
||||
|
@ -127,7 +128,8 @@ const createSLORoute = createSloServerRoute({
|
|||
summaryTransformManager,
|
||||
logger,
|
||||
spaceId,
|
||||
basePath
|
||||
basePath,
|
||||
userId
|
||||
);
|
||||
|
||||
return await executeWithErrorHandler(() => createSLO.execute(params.body));
|
||||
|
@ -153,6 +155,7 @@ const inspectSLORoute = createSloServerRoute({
|
|||
const core = await context.core;
|
||||
const scopedClusterClient = core.elasticsearch.client;
|
||||
const esClient = core.elasticsearch.client.asCurrentUser;
|
||||
const username = core.security.authc.getCurrentUser()?.username!;
|
||||
const soClient = core.savedObjects.client;
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient, logger);
|
||||
const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient);
|
||||
|
@ -181,7 +184,8 @@ const inspectSLORoute = createSloServerRoute({
|
|||
summaryTransformManager,
|
||||
logger,
|
||||
spaceId,
|
||||
basePath
|
||||
basePath,
|
||||
username
|
||||
);
|
||||
|
||||
return await executeWithErrorHandler(() => createSLO.inspect(params.body));
|
||||
|
@ -208,6 +212,8 @@ const updateSLORoute = createSloServerRoute({
|
|||
const core = await context.core;
|
||||
const scopedClusterClient = core.elasticsearch.client;
|
||||
const esClient = core.elasticsearch.client.asCurrentUser;
|
||||
const userId = core.security.authc.getCurrentUser()?.username!;
|
||||
|
||||
const soClient = core.savedObjects.client;
|
||||
const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient);
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient, logger);
|
||||
|
@ -236,7 +242,8 @@ const updateSLORoute = createSloServerRoute({
|
|||
scopedClusterClient,
|
||||
logger,
|
||||
spaceId,
|
||||
basePath
|
||||
basePath,
|
||||
userId
|
||||
);
|
||||
|
||||
return await executeWithErrorHandler(() => updateSLO.execute(params.path.id, params.body));
|
||||
|
@ -320,8 +327,8 @@ const getSLORoute = createSloServerRoute({
|
|||
const repository = new KibanaSavedObjectsSLORepository(soClient, logger);
|
||||
const burnRatesClient = new DefaultBurnRatesClient(esClient);
|
||||
const summaryClient = new DefaultSummaryClient(esClient, burnRatesClient);
|
||||
const defintionClient = new SloDefinitionClient(repository, esClient, logger);
|
||||
const getSLO = new GetSLO(defintionClient, summaryClient);
|
||||
const definitionClient = new SloDefinitionClient(repository, esClient, logger);
|
||||
const getSLO = new GetSLO(definitionClient, summaryClient);
|
||||
|
||||
return await executeWithErrorHandler(() =>
|
||||
getSLO.execute(params.path.id, spaceId, params.query)
|
||||
|
|
|
@ -7,7 +7,7 @@ Array [
|
|||
"description": "Ingest pipeline for SLO rollup data",
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"description": "Ingest pipeline for SLO rollup data [id: unique-id, revision: 1]",
|
||||
"id": ".slo-observability.sli.pipeline-unique-id-1",
|
||||
|
@ -45,7 +45,7 @@ Array [
|
|||
],
|
||||
"date_rounding": "M",
|
||||
"field": "@timestamp",
|
||||
"index_name_prefix": ".slo-observability.sli-v3.3.",
|
||||
"index_name_prefix": ".slo-observability.sli-v3.4.",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
|
@ -120,6 +120,7 @@ Array [
|
|||
"slo": Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"createdBy": "some-user-id",
|
||||
"description": "irrelevant",
|
||||
"groupBy": "*",
|
||||
"groupings": Object {},
|
||||
|
@ -148,6 +149,7 @@ Array [
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z",
|
||||
"updatedBy": "some-user-id",
|
||||
},
|
||||
"spaceId": "some-space",
|
||||
"status": "NO_DATA",
|
||||
|
@ -160,7 +162,7 @@ Array [
|
|||
},
|
||||
},
|
||||
"id": "slo-unique-id",
|
||||
"index": ".slo-observability.summary-v3.3.temp",
|
||||
"index": ".slo-observability.summary-v3.4.temp",
|
||||
"refresh": true,
|
||||
},
|
||||
]
|
||||
|
|
|
@ -122,6 +122,7 @@ exports[`ResetSLO happy path resets all associated resources 6`] = `
|
|||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2023-01-01T00:00:00.000Z,
|
||||
"createdBy": "irrelevant",
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
|
@ -165,6 +166,7 @@ exports[`ResetSLO happy path resets all associated resources 6`] = `
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2023-01-01T00:00:00.000Z,
|
||||
"updatedBy": "irrelevant",
|
||||
"version": 1,
|
||||
},
|
||||
],
|
||||
|
@ -203,7 +205,7 @@ exports[`ResetSLO happy path resets all associated resources 8`] = `
|
|||
"description": "Ingest pipeline for SLO rollup data",
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"description": "Ingest pipeline for SLO rollup data [id: irrelevant, revision: 1]",
|
||||
"id": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
|
@ -241,7 +243,7 @@ exports[`ResetSLO happy path resets all associated resources 8`] = `
|
|||
],
|
||||
"date_rounding": "M",
|
||||
"field": "@timestamp",
|
||||
"index_name_prefix": ".slo-observability.sli-v3.3.",
|
||||
"index_name_prefix": ".slo-observability.sli-v3.4.",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
|
@ -275,7 +277,7 @@ exports[`ResetSLO happy path resets all associated resources 8`] = `
|
|||
"description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]",
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]",
|
||||
"id": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
|
@ -525,6 +527,20 @@ exports[`ResetSLO happy path resets all associated resources 8`] = `
|
|||
}",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"field": "slo.updatedBy",
|
||||
"ignore_failure": true,
|
||||
"value": "irrelevant",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"set": Object {
|
||||
"field": "slo.createdBy",
|
||||
"ignore_failure": true,
|
||||
"value": "irrelevant",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -549,6 +565,7 @@ exports[`ResetSLO happy path resets all associated resources 9`] = `
|
|||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2023-01-01T00:00:00.000Z,
|
||||
"createdBy": "irrelevant",
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
|
@ -592,6 +609,7 @@ exports[`ResetSLO happy path resets all associated resources 9`] = `
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2023-01-01T00:00:00.000Z,
|
||||
"updatedBy": "irrelevant",
|
||||
"version": 1,
|
||||
},
|
||||
],
|
||||
|
@ -668,6 +686,7 @@ exports[`ResetSLO happy path resets all associated resources 11`] = `
|
|||
"slo": Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": "2023-01-01T00:00:00.000Z",
|
||||
"createdBy": "irrelevant",
|
||||
"description": "irrelevant",
|
||||
"groupBy": "*",
|
||||
"groupings": Object {},
|
||||
|
@ -700,6 +719,7 @@ exports[`ResetSLO happy path resets all associated resources 11`] = `
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": "2023-01-01T00:00:00.000Z",
|
||||
"updatedBy": "irrelevant",
|
||||
},
|
||||
"spaceId": "some-space",
|
||||
"status": "NO_DATA",
|
||||
|
@ -712,7 +732,7 @@ exports[`ResetSLO happy path resets all associated resources 11`] = `
|
|||
},
|
||||
},
|
||||
"id": "slo-irrelevant",
|
||||
"index": ".slo-observability.summary-v3.3.temp",
|
||||
"index": ".slo-observability.summary-v3.4.temp",
|
||||
"refresh": true,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -9,6 +9,7 @@ Object {
|
|||
"slo": Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2024-01-01T00:00:00.000Z,
|
||||
"createdBy": "irrelevant",
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
|
@ -54,6 +55,7 @@ Object {
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2024-01-01T00:00:00.000Z,
|
||||
"updatedBy": "irrelevant",
|
||||
"version": 1,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -51,7 +51,8 @@ describe('CreateSLO', () => {
|
|||
mockSummaryTransformManager,
|
||||
mockLogger,
|
||||
'some-space',
|
||||
httpServiceMock.createStartContract().basePath
|
||||
httpServiceMock.createStartContract().basePath,
|
||||
'some-user-id'
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@ export class CreateSLO {
|
|||
private summaryTransformManager: TransformManager,
|
||||
private logger: Logger,
|
||||
private spaceId: string,
|
||||
private basePath: IBasePath
|
||||
private basePath: IBasePath,
|
||||
private username: string
|
||||
) {}
|
||||
|
||||
public async execute(params: CreateSLOParams): Promise<CreateSLOResponse> {
|
||||
|
@ -217,6 +218,8 @@ export class CreateSLO {
|
|||
tags: params.tags ?? [],
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
createdBy: this.username,
|
||||
updatedBy: this.username,
|
||||
groupBy: !!params.groupBy ? params.groupBy : ALL_VALUE,
|
||||
version: SLO_MODEL_VERSION,
|
||||
};
|
||||
|
|
|
@ -58,6 +58,8 @@ describe('FindSLO', () => {
|
|||
id: slo.id,
|
||||
name: 'irrelevant',
|
||||
description: 'irrelevant',
|
||||
createdBy: 'irrelevant',
|
||||
updatedBy: 'irrelevant',
|
||||
budgetingMethod: 'occurrences',
|
||||
indicator: {
|
||||
params: {
|
||||
|
|
|
@ -206,6 +206,8 @@ export const createSLO = (params: Partial<SLODefinition> = {}): SLODefinition =>
|
|||
revision: 1,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
createdBy: 'irrelevant',
|
||||
updatedBy: 'irrelevant',
|
||||
version: SLO_MODEL_VERSION,
|
||||
...params,
|
||||
});
|
||||
|
|
|
@ -63,6 +63,8 @@ describe('GetSLO', () => {
|
|||
name: 'irrelevant',
|
||||
description: 'irrelevant',
|
||||
budgetingMethod: 'occurrences',
|
||||
createdBy: 'irrelevant',
|
||||
updatedBy: 'irrelevant',
|
||||
indicator: {
|
||||
params: {
|
||||
environment: 'irrelevant',
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
|
||||
import { SavedObject, SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
|
||||
import { Logger } from '@kbn/core/server';
|
||||
import { ALL_VALUE, Paginated, Pagination, sloDefinitionSchema } from '@kbn/slo-schema';
|
||||
import { isLeft } from 'fp-ts/lib/Either';
|
||||
|
@ -79,7 +79,7 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
|
|||
throw new SLONotFound(`SLO [${id}] not found`);
|
||||
}
|
||||
|
||||
const slo = this.toSLO(response.saved_objects[0].attributes);
|
||||
const slo = this.toSLO(response.saved_objects[0]);
|
||||
if (slo === undefined) {
|
||||
throw new Error('Invalid stored SLO');
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
|
|||
});
|
||||
|
||||
return response.saved_objects
|
||||
.map((slo) => this.toSLO(slo.attributes))
|
||||
.map((slo) => this.toSLO(slo))
|
||||
.filter((slo) => slo !== undefined) as SLODefinition[];
|
||||
}
|
||||
|
||||
|
@ -141,12 +141,13 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
|
|||
perPage: response.per_page,
|
||||
page: response.page,
|
||||
results: response.saved_objects
|
||||
.map((savedObject) => this.toSLO(savedObject.attributes))
|
||||
.map((savedObject) => this.toSLO(savedObject))
|
||||
.filter((slo) => slo !== undefined) as SLODefinition[],
|
||||
};
|
||||
}
|
||||
|
||||
toSLO(storedSLO: StoredSLODefinition): SLODefinition | undefined {
|
||||
toSLO(storedSLOObject: SavedObject<StoredSLODefinition>): SLODefinition | undefined {
|
||||
const storedSLO = storedSLOObject.attributes;
|
||||
const result = sloDefinitionSchema.decode({
|
||||
...storedSLO,
|
||||
// groupBy was added in 8.10.0
|
||||
|
@ -160,6 +161,8 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
|
|||
{ preventInitialBackfill: false, syncDelay: '1m', frequency: '1m' },
|
||||
storedSLO.settings
|
||||
),
|
||||
createdBy: storedSLO.createdBy ?? storedSLOObject.created_by,
|
||||
updatedBy: storedSLO.updatedBy ?? storedSLOObject.updated_by,
|
||||
});
|
||||
|
||||
if (isLeft(result)) {
|
||||
|
|
|
@ -5,12 +5,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.summary-v3.3",
|
||||
"index": ".slo-observability.summary-v3.4",
|
||||
"pipeline": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -212,7 +212,7 @@ Object {
|
|||
"unattended": true,
|
||||
},
|
||||
"source": Object {
|
||||
"index": ".slo-observability.sli-v3.3*",
|
||||
"index": ".slo-observability.sli-v3.4*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
@ -253,12 +253,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.summary-v3.3",
|
||||
"index": ".slo-observability.summary-v3.4",
|
||||
"pipeline": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -460,7 +460,7 @@ Object {
|
|||
"unattended": true,
|
||||
},
|
||||
"source": Object {
|
||||
"index": ".slo-observability.sli-v3.3*",
|
||||
"index": ".slo-observability.sli-v3.4*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
@ -501,12 +501,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.summary-v3.3",
|
||||
"index": ".slo-observability.summary-v3.4",
|
||||
"pipeline": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -708,7 +708,7 @@ Object {
|
|||
"unattended": true,
|
||||
},
|
||||
"source": Object {
|
||||
"index": ".slo-observability.sli-v3.3*",
|
||||
"index": ".slo-observability.sli-v3.4*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
|
|
@ -5,12 +5,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.summary-v3.3",
|
||||
"index": ".slo-observability.summary-v3.4",
|
||||
"pipeline": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -236,7 +236,7 @@ Object {
|
|||
"unattended": true,
|
||||
},
|
||||
"source": Object {
|
||||
"index": ".slo-observability.sli-v3.3*",
|
||||
"index": ".slo-observability.sli-v3.4*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
|
|
@ -5,12 +5,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Summarise the rollup data of SLO: irrelevant [id: irrelevant, revision: 1].",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.summary-v3.3",
|
||||
"index": ".slo-observability.summary-v3.4",
|
||||
"pipeline": ".slo-observability.summary.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -212,7 +212,7 @@ Object {
|
|||
"unattended": true,
|
||||
},
|
||||
"source": Object {
|
||||
"index": ".slo-observability.sli-v3.3*",
|
||||
"index": ".slo-observability.sli-v3.4*",
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
|
|
|
@ -31,7 +31,7 @@ export interface EsSummaryDocument {
|
|||
};
|
||||
name: string | null;
|
||||
};
|
||||
// common fields
|
||||
// SLO definition
|
||||
slo: {
|
||||
// >= 8.14: Add indicator.params on the temporary summary as well as real summary through summary pipeline
|
||||
indicator: { type: IndicatorTypes } | Indicator;
|
||||
|
@ -48,6 +48,8 @@ export interface EsSummaryDocument {
|
|||
tags: string[];
|
||||
createdAt?: string; // >= 8.14
|
||||
updatedAt?: string; // >= 8.14
|
||||
createdBy?: string; // >= 8.18
|
||||
updatedBy?: string; // >= 8.18
|
||||
};
|
||||
goodEvents: number;
|
||||
totalEvents: number;
|
||||
|
@ -132,6 +134,9 @@ export function createTempSummaryDocument(
|
|||
tags: slo.tags,
|
||||
createdAt: slo.createdAt.toISOString(), // added in 8.14, i.e. might be undefined
|
||||
updatedAt: slo.updatedAt.toISOString(), // added in 8.14, i.e. might be undefined
|
||||
// Added in 8.18
|
||||
createdBy: slo.createdBy,
|
||||
updatedBy: slo.updatedBy,
|
||||
},
|
||||
goodEvents: 0,
|
||||
totalEvents: 0,
|
||||
|
|
|
@ -360,12 +360,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -508,12 +508,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -656,12 +656,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -336,12 +336,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -471,12 +471,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -606,12 +606,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -77,12 +77,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -206,12 +206,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -335,12 +335,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -118,12 +118,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -220,12 +220,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -322,12 +322,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -117,12 +117,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -257,12 +257,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -5,12 +5,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -33,12 +33,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
@ -224,12 +224,12 @@ Object {
|
|||
"_meta": Object {
|
||||
"managed": true,
|
||||
"managed_by": "observability",
|
||||
"version": 3.3,
|
||||
"version": 3.4,
|
||||
},
|
||||
"defer_validation": true,
|
||||
"description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]",
|
||||
"dest": Object {
|
||||
"index": ".slo-observability.sli-v3.3",
|
||||
"index": ".slo-observability.sli-v3.4",
|
||||
"pipeline": ".slo-observability.sli.pipeline-irrelevant-1",
|
||||
},
|
||||
"frequency": "1m",
|
||||
|
|
|
@ -4,6 +4,7 @@ exports[`FromRemoteSummaryDocToSlo with kibana < v8.14 fallbacks to dummy indica
|
|||
Object {
|
||||
"budgetingMethod": "timeslices",
|
||||
"createdAt": 2024-01-01T00:00:00.000Z,
|
||||
"createdBy": undefined,
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
|
@ -49,6 +50,7 @@ Object {
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2024-01-01T00:00:00.000Z,
|
||||
"updatedBy": undefined,
|
||||
"version": 1,
|
||||
}
|
||||
`;
|
||||
|
@ -57,6 +59,7 @@ exports[`FromRemoteSummaryDocToSlo with kibana >= v8.14 uses the stringified ind
|
|||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2024-02-01T00:00:00.000Z,
|
||||
"createdBy": undefined,
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
|
@ -99,6 +102,59 @@ Object {
|
|||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2024-02-01T00:00:00.000Z,
|
||||
"updatedBy": undefined,
|
||||
"version": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`FromRemoteSummaryDocToSlo with kibana >= v8.18 uses the provided updatedBy and createdBy 1`] = `
|
||||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"createdAt": 2024-02-01T00:00:00.000Z,
|
||||
"createdBy": "john",
|
||||
"description": "irrelevant",
|
||||
"enabled": true,
|
||||
"groupBy": "*",
|
||||
"id": "irrelevant",
|
||||
"indicator": Object {
|
||||
"params": Object {
|
||||
"good": "irrelevant",
|
||||
"index": "irrelvant",
|
||||
"timestampField": "irrelevant",
|
||||
"total": "irrelevant",
|
||||
},
|
||||
"type": "sli.kql.custom",
|
||||
},
|
||||
"name": "irrelevant",
|
||||
"objective": Object {
|
||||
"target": 0.9999,
|
||||
"timesliceTarget": undefined,
|
||||
"timesliceWindow": undefined,
|
||||
},
|
||||
"revision": 1,
|
||||
"settings": Object {
|
||||
"frequency": Duration {
|
||||
"unit": "m",
|
||||
"value": 1,
|
||||
},
|
||||
"preventInitialBackfill": false,
|
||||
"syncDelay": Duration {
|
||||
"unit": "m",
|
||||
"value": 1,
|
||||
},
|
||||
},
|
||||
"tags": Array [
|
||||
"prod",
|
||||
],
|
||||
"timeWindow": Object {
|
||||
"duration": Duration {
|
||||
"unit": "d",
|
||||
"value": 7,
|
||||
},
|
||||
"type": "rolling",
|
||||
},
|
||||
"updatedAt": 2024-02-01T00:00:00.000Z,
|
||||
"updatedBy": "jane",
|
||||
"version": 1,
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -154,4 +154,79 @@ describe('FromRemoteSummaryDocToSlo', () => {
|
|||
expect(slo).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with kibana >= v8.18', () => {
|
||||
it('uses the provided updatedBy and createdBy', () => {
|
||||
const slo = fromRemoteSummaryDocumentToSloDefinition(
|
||||
{
|
||||
service: {
|
||||
environment: null,
|
||||
name: null,
|
||||
},
|
||||
transaction: {
|
||||
name: null,
|
||||
type: null,
|
||||
},
|
||||
monitor: {
|
||||
name: null,
|
||||
config_id: null,
|
||||
},
|
||||
observer: {
|
||||
name: null,
|
||||
geo: {
|
||||
name: null,
|
||||
},
|
||||
},
|
||||
slo: {
|
||||
indicator: {
|
||||
type: 'sli.kql.custom',
|
||||
params: {
|
||||
index: 'irrelvant',
|
||||
good: 'irrelevant',
|
||||
total: 'irrelevant',
|
||||
timestampField: 'irrelevant',
|
||||
}, // added in 8.14
|
||||
},
|
||||
timeWindow: {
|
||||
duration: '7d',
|
||||
type: 'rolling',
|
||||
},
|
||||
groupBy: ALL_VALUE,
|
||||
groupings: {},
|
||||
instanceId: ALL_VALUE,
|
||||
name: 'irrelevant',
|
||||
description: 'irrelevant',
|
||||
id: 'irrelevant',
|
||||
budgetingMethod: 'occurrences',
|
||||
revision: 1,
|
||||
objective: {
|
||||
target: 0.9999,
|
||||
},
|
||||
tags: ['prod'],
|
||||
createdAt: '2024-02-01T00:00:00.000Z', // added in 8.14
|
||||
updatedAt: '2024-02-01T00:00:00.000Z', // added in 8.14
|
||||
createdBy: 'john',
|
||||
updatedBy: 'jane',
|
||||
},
|
||||
goodEvents: 0,
|
||||
totalEvents: 0,
|
||||
errorBudgetEstimated: false,
|
||||
errorBudgetRemaining: 1,
|
||||
errorBudgetConsumed: 0,
|
||||
errorBudgetInitial: 1 - 0.9999,
|
||||
sliValue: -1,
|
||||
statusCode: 0,
|
||||
status: 'NO_DATA',
|
||||
isTempDoc: true,
|
||||
spaceId: 'irrelevant',
|
||||
kibanaUrl: 'http://kibana.com/base-path', // added in 8.14
|
||||
summaryUpdatedAt: null,
|
||||
latestSliTimestamp: null,
|
||||
},
|
||||
loggerMock
|
||||
);
|
||||
|
||||
expect(slo).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -42,6 +42,8 @@ export function fromRemoteSummaryDocumentToSloDefinition(
|
|||
updatedAt: summaryDoc.slo.updatedAt ?? '2024-01-01T00:00:00.000Z', // fallback prior 8.14
|
||||
groupBy: summaryDoc.slo.groupBy,
|
||||
version: 1,
|
||||
createdBy: summaryDoc.slo.createdBy,
|
||||
updatedBy: summaryDoc.slo.updatedBy,
|
||||
});
|
||||
|
||||
if (isLeft(res)) {
|
||||
|
|
|
@ -65,7 +65,8 @@ describe('UpdateSLO', () => {
|
|||
mockScopedClusterClient,
|
||||
mockLogger,
|
||||
'some-space',
|
||||
httpServiceMock.createStartContract().basePath
|
||||
httpServiceMock.createStartContract().basePath,
|
||||
'some-user-id'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -246,6 +247,7 @@ describe('UpdateSLO', () => {
|
|||
name: 'updated name',
|
||||
revision: 2,
|
||||
updatedAt: expect.anything(),
|
||||
updatedBy: 'some-user-id',
|
||||
})
|
||||
);
|
||||
expectInstallationOfUpdatedSLOResources();
|
||||
|
@ -262,7 +264,7 @@ describe('UpdateSLO', () => {
|
|||
mockSummaryTransformManager.getVersion.mockResolvedValue(SLO_RESOURCES_VERSION);
|
||||
});
|
||||
|
||||
it('consideres a settings change as a breaking change', async () => {
|
||||
it('considers a settings change as a breaking change', async () => {
|
||||
const slo = createSLO();
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -275,17 +277,12 @@ describe('UpdateSLO', () => {
|
|||
|
||||
expectDeletionOfOriginalSLOResources(slo);
|
||||
expect(mockRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
...slo,
|
||||
settings: newSettings,
|
||||
revision: 2,
|
||||
updatedAt: expect.anything(),
|
||||
})
|
||||
expect.objectContaining({ settings: newSettings, revision: 2 })
|
||||
);
|
||||
expectInstallationOfUpdatedSLOResources();
|
||||
});
|
||||
|
||||
it('consideres a budgeting method change as a breaking change', async () => {
|
||||
it('considers a budgeting method change as a breaking change', async () => {
|
||||
const slo = createSLO({ budgetingMethod: 'occurrences' });
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -302,7 +299,7 @@ describe('UpdateSLO', () => {
|
|||
expectDeletionOfOriginalSLOResources(slo);
|
||||
});
|
||||
|
||||
it('consideres a timeWindow change as a breaking change', async () => {
|
||||
it('considers a timeWindow change as a breaking change', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod();
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -314,7 +311,7 @@ describe('UpdateSLO', () => {
|
|||
expectDeletionOfOriginalSLOResources(slo);
|
||||
});
|
||||
|
||||
it('consideres a timeslice target change as a breaking change', async () => {
|
||||
it('considers a timeslice target change as a breaking change', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod();
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -330,7 +327,7 @@ describe('UpdateSLO', () => {
|
|||
expectDeletionOfOriginalSLOResources(slo);
|
||||
});
|
||||
|
||||
it('consideres a timeslice window change as a breaking change', async () => {
|
||||
it('considers a timeslice window change as a breaking change', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod();
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -346,7 +343,7 @@ describe('UpdateSLO', () => {
|
|||
expectDeletionOfOriginalSLOResources(slo);
|
||||
});
|
||||
|
||||
it('consideres an indicator change as a breaking change', async () => {
|
||||
it('considers an indicator change as a breaking change', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod();
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -358,7 +355,7 @@ describe('UpdateSLO', () => {
|
|||
expectDeletionOfOriginalSLOResources(slo);
|
||||
});
|
||||
|
||||
it('consideres a groupBy change as a breaking change', async () => {
|
||||
it('considers a groupBy change as a breaking change', async () => {
|
||||
const slo = createSLOWithTimeslicesBudgetingMethod();
|
||||
mockRepository.findById.mockResolvedValueOnce(slo);
|
||||
|
||||
|
@ -450,6 +447,30 @@ describe('UpdateSLO', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Update also updates updatedBy field', () => {
|
||||
beforeEach(() => {
|
||||
mockEsClient.security.hasPrivileges.mockResolvedValue({
|
||||
has_all_requested: true,
|
||||
} as SecurityHasPrivilegesResponse);
|
||||
});
|
||||
|
||||
it('updates the updatedBy field with the user id', async () => {
|
||||
const originalSlo = createSLO({
|
||||
id: 'original-id',
|
||||
indicator: createAPMTransactionErrorRateIndicator({ environment: 'development' }),
|
||||
});
|
||||
mockRepository.findById.mockResolvedValueOnce(originalSlo);
|
||||
|
||||
const newIndicator = createAPMTransactionErrorRateIndicator({ environment: 'production' });
|
||||
|
||||
await updateSLO.execute(originalSlo.id, { indicator: newIndicator });
|
||||
|
||||
expect(mockRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ updatedBy: 'some-user-id' })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function expectInstallationOfUpdatedSLOResources() {
|
||||
expect(mockTransformManager.install).toHaveBeenCalled();
|
||||
expect(mockTransformManager.start).toHaveBeenCalled();
|
||||
|
|
|
@ -39,7 +39,8 @@ export class UpdateSLO {
|
|||
private scopedClusterClient: IScopedClusterClient,
|
||||
private logger: Logger,
|
||||
private spaceId: string,
|
||||
private basePath: IBasePath
|
||||
private basePath: IBasePath,
|
||||
private userId: string
|
||||
) {}
|
||||
|
||||
public async execute(sloId: string, params: UpdateSLOParams): Promise<UpdateSLOResponse> {
|
||||
|
@ -58,6 +59,7 @@ export class UpdateSLO {
|
|||
|
||||
updatedSlo = Object.assign(updatedSlo, {
|
||||
updatedAt: new Date(),
|
||||
updatedBy: this.userId,
|
||||
revision: requireRevisionBump ? originalSlo.revision + 1 : originalSlo.revision,
|
||||
});
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
TaskManagerStartContract,
|
||||
} from '@kbn/task-manager-plugin/server';
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
|
||||
import { SecurityPluginStart } from '@kbn/security-plugin/server';
|
||||
import type { KibanaRequest } from '@kbn/core/server';
|
||||
import type { SloClient } from './client';
|
||||
|
||||
|
@ -44,6 +45,7 @@ export interface SLOPluginSetupDependencies {
|
|||
usageCollection: UsageCollectionSetup;
|
||||
licensing: LicensingPluginSetup;
|
||||
dataViews: DataViewsServerPluginStart;
|
||||
security: SecurityPluginStart;
|
||||
}
|
||||
|
||||
export interface SLOPluginStartDependencies {
|
||||
|
|
|
@ -102,5 +102,6 @@
|
|||
"@kbn/server-route-repository-client",
|
||||
"@kbn/security-plugin-types-public",
|
||||
"@kbn/core-test-helpers-kbn-server",
|
||||
"@kbn/security-plugin",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
|||
expect(definitions.results[0]).eql({
|
||||
budgetingMethod: 'occurrences',
|
||||
updatedAt: definitions.results[0].updatedAt,
|
||||
updatedBy: 'elastic_admin',
|
||||
createdAt: definitions.results[0].createdAt,
|
||||
createdBy: 'elastic_admin',
|
||||
description: 'Fixture for api integration tests',
|
||||
enabled: true,
|
||||
groupBy: 'tags',
|
||||
|
@ -98,7 +100,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
|||
const rollUpTransformResponse = await transformHelper.assertExist(getSLOTransformId(id, 1));
|
||||
expect(rollUpTransformResponse.transforms[0].source.index).eql(['kbn-data-forge*']);
|
||||
expect(rollUpTransformResponse.transforms[0].dest).eql({
|
||||
index: '.slo-observability.sli-v3.3',
|
||||
index: '.slo-observability.sli-v3.4',
|
||||
pipeline: `.slo-observability.sli.pipeline-${id}-1`,
|
||||
});
|
||||
expect(rollUpTransformResponse.transforms[0].pivot.group_by).eql({
|
||||
|
@ -110,10 +112,10 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
|||
getSLOSummaryTransformId(id, 1)
|
||||
);
|
||||
expect(summaryTransformResponse.transforms[0].source.index).eql([
|
||||
'.slo-observability.sli-v3.3*',
|
||||
'.slo-observability.sli-v3.4*',
|
||||
]);
|
||||
expect(summaryTransformResponse.transforms[0].dest).eql({
|
||||
index: '.slo-observability.summary-v3.3',
|
||||
index: '.slo-observability.summary-v3.4',
|
||||
pipeline: `.slo-observability.summary.pipeline-${id}-1`,
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue