[Core][Usage Collector] Saved objects usage collection to not include hidden types (#171189)

This commit is contained in:
Ahmad Bamieh 2023-11-16 11:53:29 +03:00 committed by GitHub
parent 232c1ca6ff
commit 96ff9a96bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 13 deletions

View file

@ -34,6 +34,7 @@ describe('getSavedObjectsCounts', () => {
await getSavedObjectsCounts(soClient, ['type-a', 'type_2']);
expect(soClient.find).toHaveBeenCalledWith({
type: ['type-a', 'type_2'],
namespaces: ['*'],
perPage: 0,
aggs: {
types: {
@ -49,9 +50,10 @@ describe('getSavedObjectsCounts', () => {
test('should apply the terms query and aggregation with the size matching the length of the list when `exclusive === true`', async () => {
soClient.find.mockResolvedValueOnce(soEmptyResponse);
await getSavedObjectsCounts(soClient, ['type_one', 'type_two'], true);
await getSavedObjectsCounts(soClient, ['type_one', 'type_two'], { exclusive: true });
expect(soClient.find).toHaveBeenCalledWith({
type: ['type_one', 'type_two'],
namespaces: ['*'],
perPage: 0,
aggs: { types: { terms: { field: 'type', size: 2 } } },
});

View file

@ -41,17 +41,24 @@ export interface SavedObjectsCounts {
*
* @param soClient The {@link SavedObjectsClientContract} to use when performing the aggregation.
* @param soTypes The SO types we want to know about.
* @param exclusive If `true`, the results will only contain the breakdown for the specified `soTypes`. Otherwise, it'll also return `missing` and `others` bucket.
* @param options.exclusive If `true`, the results will only contain the breakdown for the specified `soTypes`. Otherwise, it'll also return `missing` and `others` bucket.
* @param options.namespaces array of namespaces to search. Otherwise it'll default to all namespaces ['*'].
* @returns {@link SavedObjectsCounts}
*/
export async function getSavedObjectsCounts(
soClient: SavedObjectsClientContract,
soTypes: string[],
exclusive: boolean = false
options?: {
exclusive?: boolean;
namespaces?: string[];
}
): Promise<SavedObjectsCounts> {
const { exclusive = false, namespaces = ['*'] } = options || {};
const body = await soClient.find<void, { types: estypes.AggregationsStringTermsAggregate }>({
type: soTypes,
perPage: 0,
namespaces,
aggs: {
types: {
terms: {

View file

@ -97,7 +97,7 @@ describe('getKibanaSavedObjectCounts', () => {
expect(getSavedObjectsCountsMock).toHaveBeenCalledWith(
soClient,
['dashboard', 'visualization', 'search', 'index-pattern', 'graph-workspace'],
true
{ exclusive: true }
);
});
});

View file

@ -28,7 +28,7 @@ const TYPES = ['dashboard', 'visualization', 'search', 'index-pattern', 'graph-w
export async function getKibanaSavedObjectCounts(
soClient: SavedObjectsClientContract
): Promise<KibanaSavedObjectCounts> {
const { per_type: buckets } = await getSavedObjectsCounts(soClient, TYPES, true);
const { per_type: buckets } = await getSavedObjectsCounts(soClient, TYPES, { exclusive: true });
const allZeros = Object.fromEntries(
TYPES.map((type) => [snakeCase(type), { total: 0 }])

View file

@ -16,15 +16,21 @@ import { registerSavedObjectsCountUsageCollector } from './saved_objects_count_c
describe('saved_objects_count_collector', () => {
const usageCollectionMock = createUsageCollectionSetupMock();
const fetchContextMock = createCollectorFetchContextMock();
const mockGetSoClientWithHiddenIndices = jest.fn().mockResolvedValue(fetchContextMock.soClient);
beforeAll(() =>
registerSavedObjectsCountUsageCollector(usageCollectionMock, () =>
Promise.resolve(['type_one', 'type_two', 'type-three', 'type-four'])
registerSavedObjectsCountUsageCollector(
usageCollectionMock,
() => Promise.resolve(['type_one', 'type_two', 'type-three', 'type-four']),
mockGetSoClientWithHiddenIndices
)
);
afterAll(() => jest.clearAllTimers());
afterEach(() => getSavedObjectsCountsMock.mockReset());
afterEach(() => {
getSavedObjectsCountsMock.mockReset();
mockGetSoClientWithHiddenIndices.mockClear();
});
test('registered collector is set', () => {
expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalled();
@ -48,6 +54,8 @@ describe('saved_objects_count_collector', () => {
non_registered_types: [],
others: 0,
});
expect(mockGetSoClientWithHiddenIndices).toBeCalledTimes(1);
});
test('should return some values when the aggregations return something', async () => {
@ -78,10 +86,11 @@ describe('saved_objects_count_collector', () => {
total: 153,
});
expect(mockGetSoClientWithHiddenIndices).toBeCalledTimes(1);
expect(getSavedObjectsCountsMock).toHaveBeenCalledWith(
fetchContextMock.soClient,
['type_one', 'type_two', 'type-three', 'type-four'],
false
{ exclusive: false, namespaces: ['*'] }
);
});
});

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
import { getSavedObjectsCounts } from './get_saved_object_counts';
@ -23,7 +24,8 @@ interface SavedObjectsCountUsage {
export function registerSavedObjectsCountUsageCollector(
usageCollection: UsageCollectionSetup,
getAllSavedObjectTypes: () => Promise<string[]>
getAllSavedObjectTypes: () => Promise<string[]>,
getSoClientWithHiddenIndices: () => Promise<SavedObjectsClientContract>
) {
usageCollection.registerCollector(
usageCollection.makeUsageCollector<SavedObjectsCountUsage>({
@ -67,14 +69,19 @@ export function registerSavedObjectsCountUsageCollector(
},
},
},
async fetch({ soClient }) {
async fetch() {
const soClient = await getSoClientWithHiddenIndices();
const allRegisteredSOTypes = await getAllSavedObjectTypes();
const namespaces = ['*'];
const {
total,
per_type: buckets,
non_expected_types: nonRegisteredTypes,
others,
} = await getSavedObjectsCounts(soClient, allRegisteredSOTypes, false);
} = await getSavedObjectsCounts(soClient, allRegisteredSOTypes, {
namespaces,
exclusive: false,
});
return {
total,
by_type: buckets.map(({ key: type, doc_count: count }) => ({ type, count })),

View file

@ -152,7 +152,19 @@ export class KibanaUsageCollectionPlugin implements Plugin {
.getAllTypes()
.map(({ name }) => name);
};
registerSavedObjectsCountUsageCollector(usageCollection, getAllSavedObjectTypes);
const getSoClientWithHiddenIndices = async () => {
const coreStart = await coreStartPromise;
const allSoTypes = await getAllSavedObjectTypes();
return coreStart.savedObjects.createInternalRepository(allSoTypes);
};
registerSavedObjectsCountUsageCollector(
usageCollection,
getAllSavedObjectTypes,
getSoClientWithHiddenIndices
);
registerManagementUsageCollector(usageCollection, getUiSettingsClient);
registerUiMetricUsageCollector(usageCollection, registerType, getSavedObjectsClient);
registerApplicationUsageCollector(