chore(slo): update telemetry data (#206135)

This commit is contained in:
Kevin Delemme 2025-01-14 13:29:25 -05:00 committed by GitHub
parent b8cda36aa8
commit 9618e42548
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 293 additions and 60 deletions

View file

@ -7251,7 +7251,39 @@
"total": {
"type": "long",
"_meta": {
"description": "The total number of slos in the cluster"
"description": "The total number of SLOs in the cluster"
}
},
"definitions": {
"properties": {
"total": {
"type": "long",
"_meta": {
"description": "The total number of SLO definitions in the cluster"
}
},
"total_with_ccs": {
"type": "long",
"_meta": {
"description": "The total number of SLO definitions using CCS in the cluster"
}
},
"total_with_groups": {
"type": "long",
"_meta": {
"description": "The total number of SLO definitions using groups in the cluster"
}
}
}
},
"instances": {
"properties": {
"total": {
"type": "long",
"_meta": {
"description": "The total number of SLO instances in the cluster"
}
}
}
},
"by_status": {
@ -7259,13 +7291,13 @@
"enabled": {
"type": "long",
"_meta": {
"description": "The number of enabled slos in the cluster"
"description": "The number of enabled SLOs in the cluster"
}
},
"disabled": {
"type": "long",
"_meta": {
"description": "The number of disabled slos in the cluster"
"description": "The number of disabled SLOs in the cluster"
}
}
}
@ -7275,7 +7307,7 @@
"DYNAMIC_KEY": {
"type": "long",
"_meta": {
"description": "The number of slos by sli type in the cluster"
"description": "The number of SLOs by sli type in the cluster"
}
}
}
@ -7285,7 +7317,7 @@
"DYNAMIC_KEY": {
"type": "long",
"_meta": {
"description": "The number of slos by rolling duration in the cluster"
"description": "The number of SLOs by rolling duration in the cluster"
}
}
}
@ -7295,7 +7327,7 @@
"DYNAMIC_KEY": {
"type": "long",
"_meta": {
"description": "The number of slos by calendar aligned duration in the cluster"
"description": "The number of SLOs by calendar aligned duration in the cluster"
}
}
}
@ -7305,13 +7337,13 @@
"occurrences": {
"type": "long",
"_meta": {
"description": "The number of slos by timeslices budgeting method in the cluster"
"description": "The number of SLOs by timeslices budgeting method in the cluster"
}
},
"timeslices": {
"type": "long",
"_meta": {
"description": "The number of slos by occurrences budgeting method in the cluster"
"description": "The number of SLOs by occurrences budgeting method in the cluster"
}
}
}

View file

@ -0,0 +1,12 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test/jest_integration',
rootDir: '../../../../..',
roots: ['<rootDir>/x-pack/solutions/observability/plugins/slo'],
};

View file

@ -1,42 +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 { savedObjectsRepositoryMock, ElasticsearchClientMock } from '@kbn/core/server/mocks';
import { CollectorFetchContext } from '@kbn/usage-collection-plugin/server';
import { fetcher } from './fetcher';
let savedObjectClient: ReturnType<typeof savedObjectsRepositoryMock.create>;
let closeMock: jest.Mock;
let esClient: ElasticsearchClientMock;
describe('SLO usage collector fetcher', () => {
beforeEach(() => {
savedObjectClient = savedObjectsRepositoryMock.create();
closeMock = jest.fn();
});
it('without any existing slo', async () => {
savedObjectClient.createPointInTimeFinder.mockReturnValue({
find: async function* find() {
return {
[Symbol.asyncIterator]: async () => {},
next: () => {},
};
},
close: closeMock,
});
const results = await fetcher({
soClient: savedObjectClient,
esClient,
} as CollectorFetchContext);
expect(closeMock).toHaveBeenCalled();
expect(results.slo.total).toEqual(0);
});
});

View file

@ -4,10 +4,13 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { isCCSRemoteIndexName } from '@kbn/es-query';
import { ALL_VALUE } from '@kbn/slo-schema';
import { CollectorFetchContext } from '@kbn/usage-collection-plugin/server';
import { StoredSLODefinition } from '../../domain/models';
import { SO_SLO_TYPE } from '../../saved_objects';
import { Usage } from './type';
import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants';
export const fetcher = async (context: CollectorFetchContext) => {
const finder = context.soClient.createPointInTimeFinder<StoredSLODefinition>({
@ -15,8 +18,31 @@ export const fetcher = async (context: CollectorFetchContext) => {
perPage: 100,
});
const totalInstances = await context.esClient.count({
index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
query: {
bool: {
filter: [
{
term: {
isTempDoc: false,
},
},
],
},
},
});
let usage: Usage['slo'] = {
total: 0,
definitions: {
total: 0,
total_with_ccs: 0,
total_with_groups: 0,
},
instances: {
total: totalInstances?.count ?? 0,
},
by_status: {
enabled: 0,
disabled: 0,
@ -34,7 +60,16 @@ export const fetcher = async (context: CollectorFetchContext) => {
usage = response.saved_objects.reduce((acc, so) => {
return {
...acc,
total: acc.total + 1,
total: acc.total + 1, // deprecated in favor of definitions.total
definitions: {
total: acc.definitions.total + 1,
total_with_ccs: isCCSRemoteIndexName(so.attributes.indicator.params.index)
? acc.definitions.total_with_ccs + 1
: acc.definitions.total_with_ccs,
total_with_groups: [so.attributes.groupBy].flat().includes(ALL_VALUE)
? acc.definitions.total_with_groups
: acc.definitions.total_with_groups + 1,
},
by_status: {
...acc.by_status,
...(so.attributes.enabled && { enabled: acc.by_status.enabled + 1 }),

View file

@ -0,0 +1,159 @@
/*
* 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 {
createTestServers,
type TestElasticsearchUtils,
type TestKibanaUtils,
} from '@kbn/core-test-helpers-kbn-server';
import {
SavedObjectsClient,
type ElasticsearchClient,
type Logger,
type SavedObjectsClientContract,
} from '@kbn/core/server';
import { KibanaSavedObjectsSLORepository, SLORepository } from '../../../services';
import {
createAPMTransactionDurationIndicator,
createAPMTransactionErrorRateIndicator,
createKQLCustomIndicator,
createMetricCustomIndicator,
createSLO,
createSLOWithTimeslicesBudgetingMethod,
createSyntheticsAvailabilityIndicator,
createTimesliceMetricIndicator,
} from '../../../services/fixtures/slo';
import { fetcher } from '../fetcher';
const createLoggerMock = (): jest.Mocked<Logger> => {
const logger = {
debug: jest.fn(),
info: jest.fn(),
error: jest.fn(),
get: jest.fn(),
} as unknown as jest.Mocked<Logger>;
logger.get.mockReturnValue(logger);
return logger;
};
describe('SLO usage collector fetcher', () => {
let esServer: TestElasticsearchUtils;
let esClient: ElasticsearchClient;
let soClient: SavedObjectsClientContract;
let kibanaServer: TestKibanaUtils;
let sloRepository: SLORepository;
let loggerMock: jest.Mocked<Logger>;
beforeAll(async () => {
await createServers();
});
afterAll(async () => {
await stopServers();
});
describe('with some SLOs', () => {
beforeEach(async () => {
await Promise.all([
sloRepository.create(createSLO({ indicator: createAPMTransactionErrorRateIndicator() })),
sloRepository.create(createSLO({ indicator: createAPMTransactionDurationIndicator() })),
sloRepository.create(createSLO({ indicator: createSyntheticsAvailabilityIndicator() })),
sloRepository.create(createSLO({ indicator: createKQLCustomIndicator() })),
sloRepository.create(
createSLOWithTimeslicesBudgetingMethod({ indicator: createMetricCustomIndicator() })
),
sloRepository.create(
createSLOWithTimeslicesBudgetingMethod({ indicator: createTimesliceMetricIndicator() })
),
sloRepository.create(
createSLO({ groupBy: ['host.name'], indicator: createKQLCustomIndicator() })
),
sloRepository.create(
createSLO({ groupBy: 'host.name', indicator: createKQLCustomIndicator() })
),
]);
});
it('returns the correct metrics', async () => {
const results = await fetcher({ soClient, esClient });
expect(results.slo).toMatchInlineSnapshot(`
Object {
"by_budgeting_method": Object {
"occurrences": 6,
"timeslices": 2,
},
"by_calendar_aligned_duration": Object {},
"by_rolling_duration": Object {
"7d": 8,
},
"by_sli_type": Object {
"sli.apm.transactionDuration": 1,
"sli.apm.transactionErrorRate": 1,
"sli.kql.custom": 3,
"sli.metric.custom": 1,
"sli.metric.timeslice": 1,
"sli.synthetics.availability": 1,
},
"by_status": Object {
"disabled": 0,
"enabled": 8,
},
"definitions": Object {
"total": 8,
"total_with_ccs": 0,
"total_with_groups": 2,
},
"instances": Object {
"total": 0,
},
"total": 8,
}
`);
});
});
async function createServers() {
const { startES, startKibana } = createTestServers({
adjustTimeout: jest.setTimeout,
settings: {
es: {
license: 'trial',
},
kbn: {
cliArgs: {
oss: false,
},
},
},
});
esServer = await startES();
kibanaServer = await startKibana();
esClient = kibanaServer.coreStart.elasticsearch.client.asInternalUser;
soClient = new SavedObjectsClient(
kibanaServer.coreStart.savedObjects.createInternalRepository()
);
loggerMock = createLoggerMock();
sloRepository = new KibanaSavedObjectsSLORepository(soClient, loggerMock);
}
async function stopServers() {
if (kibanaServer) {
await kibanaServer.stop();
}
if (esServer) {
await esServer.stop();
}
jest.clearAllMocks();
}
});

View file

@ -21,20 +21,48 @@ export function registerSloUsageCollector(usageCollection?: UsageCollectionSetup
total: {
type: 'long',
_meta: {
description: 'The total number of slos in the cluster',
description: 'The total number of SLOs in the cluster',
},
},
definitions: {
total: {
type: 'long',
_meta: {
description: 'The total number of SLO definitions in the cluster',
},
},
total_with_ccs: {
type: 'long',
_meta: {
description: 'The total number of SLO definitions using CCS in the cluster',
},
},
total_with_groups: {
type: 'long',
_meta: {
description: 'The total number of SLO definitions using groups in the cluster',
},
},
},
instances: {
total: {
type: 'long',
_meta: {
description: 'The total number of SLO instances in the cluster',
},
},
},
by_status: {
enabled: {
type: 'long',
_meta: {
description: 'The number of enabled slos in the cluster',
description: 'The number of enabled SLOs in the cluster',
},
},
disabled: {
type: 'long',
_meta: {
description: 'The number of disabled slos in the cluster',
description: 'The number of disabled SLOs in the cluster',
},
},
},
@ -42,7 +70,7 @@ export function registerSloUsageCollector(usageCollection?: UsageCollectionSetup
DYNAMIC_KEY: {
type: 'long',
_meta: {
description: 'The number of slos by sli type in the cluster',
description: 'The number of SLOs by sli type in the cluster',
},
},
},
@ -50,7 +78,7 @@ export function registerSloUsageCollector(usageCollection?: UsageCollectionSetup
DYNAMIC_KEY: {
type: 'long',
_meta: {
description: 'The number of slos by rolling duration in the cluster',
description: 'The number of SLOs by rolling duration in the cluster',
},
},
},
@ -58,7 +86,7 @@ export function registerSloUsageCollector(usageCollection?: UsageCollectionSetup
DYNAMIC_KEY: {
type: 'long',
_meta: {
description: 'The number of slos by calendar aligned duration in the cluster',
description: 'The number of SLOs by calendar aligned duration in the cluster',
},
},
},
@ -66,13 +94,13 @@ export function registerSloUsageCollector(usageCollection?: UsageCollectionSetup
occurrences: {
type: 'long',
_meta: {
description: 'The number of slos by timeslices budgeting method in the cluster',
description: 'The number of SLOs by timeslices budgeting method in the cluster',
},
},
timeslices: {
type: 'long',
_meta: {
description: 'The number of slos by occurrences budgeting method in the cluster',
description: 'The number of SLOs by occurrences budgeting method in the cluster',
},
},
},

View file

@ -7,7 +7,15 @@
export interface Usage {
slo: {
total: number;
total: number; // deprecated
definitions: {
total: number;
total_with_ccs: number;
total_with_groups: number;
};
instances: {
total: number;
};
by_status: {
enabled: number;
disabled: number;

View file

@ -101,5 +101,6 @@
"@kbn/discover-shared-plugin",
"@kbn/server-route-repository-client",
"@kbn/security-plugin-types-public",
"@kbn/core-test-helpers-kbn-server",
]
}