Skip to content

Commit

Permalink
[SLOs] Added createdBy and updatedBy fields in summary documents !! (#…
Browse files Browse the repository at this point in the history
…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>
(cherry picked from commit 39119b5)

# Conflicts:
#	x-pack/solutions/observability/plugins/slo/tsconfig.json
  • Loading branch information
shahzad31 committed Jan 20, 2025
1 parent dfd8921 commit 4c8e993
Show file tree
Hide file tree
Showing 41 changed files with 393 additions and 143 deletions.
40 changes: 23 additions & 17 deletions x-pack/platform/packages/shared/kbn-slo-schema/src/schema/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43208,7 +43208,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",
Expand All @@ -43232,8 +43231,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 :",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43062,7 +43062,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を作成",
Expand All @@ -43086,8 +43085,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 {変換は} }正常ではない状態です。",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43160,7 +43160,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",
Expand All @@ -43184,8 +43183,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 {转换}}处于运行不正常状态:",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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>
&nbsp;
{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>
&nbsp;
{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',
});
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}]`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ describe('slo transform template', () => {
},
defer_validation: true,
_meta: {
version: 3.3,
version: 3.4,
managed: true,
managed_by: 'observability',
},
Expand Down Expand Up @@ -247,7 +247,7 @@ describe('slo transform template', () => {
},
defer_validation: true,
_meta: {
version: 3.3,
version: 3.4,
managed: true,
managed_by: 'observability',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -127,7 +128,8 @@ const createSLORoute = createSloServerRoute({
summaryTransformManager,
logger,
spaceId,
basePath
basePath,
userId
);

return await executeWithErrorHandler(() => createSLO.execute(params.body));
Expand All @@ -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);
Expand Down Expand Up @@ -181,7 +184,8 @@ const inspectSLORoute = createSloServerRoute({
summaryTransformManager,
logger,
spaceId,
basePath
basePath,
username
);

return await executeWithErrorHandler(() => createSLO.inspect(params.body));
Expand All @@ -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);
Expand Down Expand Up @@ -236,7 +242,8 @@ const updateSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
basePath
basePath,
userId
);

return await executeWithErrorHandler(() => updateSLO.execute(params.path.id, params.body));
Expand Down Expand Up @@ -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)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4c8e993

Please sign in to comment.