Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dot-kibana-split' into dot-kib…
Browse files Browse the repository at this point in the history
…ana-split-analyst-experience
  • Loading branch information
pgayvallet committed Apr 19, 2023
2 parents 0bb42a6 + 93e96aa commit 5dc558a
Show file tree
Hide file tree
Showing 55 changed files with 354 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
setSecurityExtension: deps.savedObjects.setSecurityExtension,
setSpacesExtension: deps.savedObjects.setSpacesExtension,
registerType: deps.savedObjects.registerType,
getKibanaIndex: deps.savedObjects.getKibanaIndex,
getDefaultIndex: deps.savedObjects.getDefaultIndex,
getAllIndices: deps.savedObjects.getAllIndices,
},
status: {
core$: deps.status.core$,
Expand Down Expand Up @@ -313,6 +314,10 @@ export function createPluginStartContext<TPlugin, TPluginDependencies>(
createExporter: deps.savedObjects.createExporter,
createImporter: deps.savedObjects.createImporter,
getTypeRegistry: deps.savedObjects.getTypeRegistry,
getDefaultIndex: deps.savedObjects.getDefaultIndex,
getIndexForType: deps.savedObjects.getIndexForType,
getIndicesForTypes: deps.savedObjects.getIndicesForTypes,
getAllIndices: deps.savedObjects.getAllIndices,
},
metrics: {
collectionInterval: deps.metrics.collectionInterval,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { type RawPackageInfo, Env } from '@kbn/config';
import { ByteSizeValue } from '@kbn/config-schema';
import { REPO_ROOT } from '@kbn/repo-info';
import { getEnvOptions } from '@kbn/config-mocks';
import { SavedObjectsType, MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
import { docLinksServiceMock } from '@kbn/core-doc-links-server-mocks';
import { nodeServiceMock } from '@kbn/core-node-server-mocks';
import { mockCoreContext } from '@kbn/core-base-server-mocks';
Expand Down Expand Up @@ -55,6 +56,14 @@ import { getSavedObjectsDeprecationsProvider } from './deprecations';
jest.mock('./object_types');
jest.mock('./deprecations');

const createType = (parts: Partial<SavedObjectsType>): SavedObjectsType => ({
name: 'test-type',
hidden: false,
namespaceType: 'single',
mappings: { properties: {} },
...parts,
});

describe('SavedObjectsService', () => {
let deprecationsSetup: ReturnType<typeof createDeprecationRegistryProviderMock>;

Expand Down Expand Up @@ -630,5 +639,85 @@ describe('SavedObjectsService', () => {
expect(includedHiddenTypes).toEqual(['someHiddenType']);
});
});

describe('index retrieval APIs', () => {
let soService: SavedObjectsService;

beforeEach(async () => {
const coreContext = createCoreContext({ skipMigration: false });
soService = new SavedObjectsService(coreContext);

typeRegistryInstanceMock.getType.mockImplementation((type: string) => {
if (type === 'dashboard') {
return createType({
name: 'dashboard',
});
} else if (type === 'foo') {
return createType({
name: 'foo',
indexPattern: '.kibana_foo',
});
} else if (type === 'bar') {
return createType({
name: 'bar',
indexPattern: '.kibana_bar',
});
} else if (type === 'bar_too') {
return createType({
name: 'bar_too',
indexPattern: '.kibana_bar',
});
} else {
return undefined;
}
});

await soService.setup(createSetupDeps());
});

describe('#getDefaultIndex', () => {
it('return the default index', async () => {
const { getDefaultIndex } = await soService.start(createStartDeps());
expect(getDefaultIndex()).toEqual(MAIN_SAVED_OBJECT_INDEX);
});
});

describe('#getIndexForType', () => {
it('return the correct index for type specifying its indexPattern', async () => {
const { getIndexForType } = await soService.start(createStartDeps());
expect(getIndexForType('bar')).toEqual('.kibana_bar');
});
it('return the correct index for type not specifying its indexPattern', async () => {
const { getIndexForType } = await soService.start(createStartDeps());
expect(getIndexForType('dashboard')).toEqual(MAIN_SAVED_OBJECT_INDEX);
});
it('return the default index for unknown type', async () => {
const { getIndexForType } = await soService.start(createStartDeps());
expect(getIndexForType('unknown_type')).toEqual(MAIN_SAVED_OBJECT_INDEX);
});
});

describe('#getIndicesForTypes', () => {
it('return the correct indices for specified types', async () => {
const { getIndicesForTypes } = await soService.start(createStartDeps());
expect(getIndicesForTypes(['dashboard', 'foo', 'bar'])).toEqual([
MAIN_SAVED_OBJECT_INDEX,
'.kibana_foo',
'.kibana_bar',
]);
});
it('ignore duplicate indices', async () => {
const { getIndicesForTypes } = await soService.start(createStartDeps());
expect(getIndicesForTypes(['bar', 'bar_too'])).toEqual(['.kibana_bar']);
});
it('return the default index for unknown type', async () => {
const { getIndicesForTypes } = await soService.start(createStartDeps());
expect(getIndicesForTypes(['unknown', 'foo'])).toEqual([
MAIN_SAVED_OBJECT_INDEX,
'.kibana_foo',
]);
});
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import {
import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal';
import type { DeprecationRegistryProvider } from '@kbn/core-deprecations-server';
import type { NodeInfo } from '@kbn/core-node-server';
import { MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
import { MAIN_SAVED_OBJECT_INDEX, SavedObjectsIndexPatterns } from '@kbn/core-saved-objects-server';
import { registerRoutes } from './routes';
import { calculateStatus$ } from './status';
import { registerCoreObjectTypes } from './object_types';
Expand Down Expand Up @@ -197,7 +197,8 @@ export class SavedObjectsService
this.typeRegistry.registerType(type);
},
getTypeRegistry: () => this.typeRegistry,
getKibanaIndex: () => MAIN_SAVED_OBJECT_INDEX,
getDefaultIndex: () => MAIN_SAVED_OBJECT_INDEX,
getAllIndices: () => [...SavedObjectsIndexPatterns],
};
}

Expand Down Expand Up @@ -340,6 +341,21 @@ export class SavedObjectsService
importSizeLimit: options?.importSizeLimit ?? this.config!.maxImportExportSize,
}),
getTypeRegistry: () => this.typeRegistry,
getDefaultIndex: () => MAIN_SAVED_OBJECT_INDEX,
getIndexForType: (type: string) => {
const definition = this.typeRegistry.getType(type);
return definition?.indexPattern ?? MAIN_SAVED_OBJECT_INDEX;
},
getIndicesForTypes: (types: string[]) => {
const indices = new Set<string>();
types.forEach((type) => {
const definition = this.typeRegistry.getType(type);
const index = definition?.indexPattern ?? MAIN_SAVED_OBJECT_INDEX;
indices.add(index);
});
return [...indices];
},
getAllIndices: () => [...SavedObjectsIndexPatterns],
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const createStartContractMock = (typeRegistry?: jest.Mocked<ISavedObjectTypeRegi
createExporter: jest.fn(),
createImporter: jest.fn(),
getTypeRegistry: jest.fn(),
getDefaultIndex: jest.fn(),
getIndexForType: jest.fn(),
getIndicesForTypes: jest.fn(),
getAllIndices: jest.fn(),
};

startContrat.getScopedClient.mockReturnValue(savedObjectsClientMock.create());
Expand All @@ -50,6 +54,10 @@ const createStartContractMock = (typeRegistry?: jest.Mocked<ISavedObjectTypeRegi
startContrat.getTypeRegistry.mockReturnValue(typeRegistry ?? typeRegistryMock.create());
startContrat.createExporter.mockReturnValue(savedObjectsExporterMock.create());
startContrat.createImporter.mockReturnValue(savedObjectsImporterMock.create());
startContrat.getDefaultIndex.mockReturnValue(MAIN_SAVED_OBJECT_INDEX);
startContrat.getIndexForType.mockReturnValue(MAIN_SAVED_OBJECT_INDEX);
startContrat.getIndicesForTypes.mockReturnValue([MAIN_SAVED_OBJECT_INDEX]);
startContrat.getAllIndices.mockReturnValue([MAIN_SAVED_OBJECT_INDEX]);

return startContrat;
};
Expand All @@ -68,10 +76,12 @@ const createSetupContractMock = () => {
setSecurityExtension: jest.fn(),
setSpacesExtension: jest.fn(),
registerType: jest.fn(),
getKibanaIndex: jest.fn(),
getDefaultIndex: jest.fn(),
getAllIndices: jest.fn(),
};

setupContract.getKibanaIndex.mockReturnValue(MAIN_SAVED_OBJECT_INDEX);
setupContract.getDefaultIndex.mockReturnValue(MAIN_SAVED_OBJECT_INDEX);
setupContract.getAllIndices.mockReturnValue([MAIN_SAVED_OBJECT_INDEX]);

return setupContract;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,14 @@ export interface SavedObjectsServiceSetup {
/**
* Returns the default index used for saved objects.
*/
getKibanaIndex: () => string;
getDefaultIndex: () => string;

/**
* Returns all (aliases to) kibana system indices used for saved object storage.
*
* @deprecated use the `start` contract counterpart.
*/
getAllIndices: () => string[];
}

/**
Expand Down Expand Up @@ -209,4 +216,25 @@ export interface SavedObjectsServiceStart {
* {@link SavedObjectsType | saved object types}
*/
getTypeRegistry: () => ISavedObjectTypeRegistry;
/**
* Returns the (alias to the) index that the specified saved object type is stored in.
*
* @param type The SO type to retrieve the index/alias for.
*/
getIndexForType: (type: string) => string;
/**
* Returns the (alias to the) index that the specified saved object type is stored in.
*
* @remark if multiple types are living in the same index, duplicates will be removed.
* @param types The SO types to retrieve the index/alias for.
*/
getIndicesForTypes: (types: string[]) => string[];
/**
* Returns the default index used for saved objects.
*/
getDefaultIndex: () => string;
/**
* Returns all (aliases to) kibana system indices used for saved object storage.
*/
getAllIndices: () => string[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,14 @@ export function dashboardTaskRunner(logger: Logger, core: CoreSetup, embeddable:
return dashboardData;
};

const kibanaIndex = core.savedObjects.getKibanaIndex();
const dashboardIndex = await core
.getStartServices()
.then(([coreStart]) => coreStart.savedObjects.getIndexForType('dashboard'));
const pageSize = 50;

const searchParams = {
size: pageSize,
index: kibanaIndex,
index: dashboardIndex,
ignore_unavailable: true,
filter_path: ['hits.hits', '_scroll_id'],
body: { query: { bool: { filter: { term: { type: 'dashboard' } } } } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export class KqlTelemetryService implements Plugin<void> {

if (usageCollection) {
try {
makeKQLUsageCollector(usageCollection, savedObjects.getKibanaIndex());
const getIndexForType = (type: string) =>
getStartServices().then(([coreStart]) => coreStart.savedObjects.getIndexForType(type));
makeKQLUsageCollector(usageCollection, getIndexForType);
} catch (e) {
this.initializerContext.logger
.get('kql-telemetry')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function setupMockCallCluster(
describe('makeKQLUsageCollector', () => {
describe('fetch method', () => {
beforeEach(() => {
fetch = fetchProvider('.kibana');
fetch = fetchProvider(() => Promise.resolve('.kibana'));
});

it('should return opt in data from the .kibana/kql-telemetry doc', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ export interface Usage {
defaultQueryLanguage: string;
}

export function fetchProvider(index: string) {
export function fetchProvider(getIndexForType: (type: string) => Promise<string>) {
return async ({ esClient }: CollectorFetchContext): Promise<Usage> => {
const [response, config] = await Promise.all([
esClient.get(
{
index,
index: await getIndexForType('kql-telemetry'),
id: 'kql-telemetry:kql-telemetry',
},
{ ignore: [404] }
),
esClient.search(
{
index,
index: await getIndexForType('config'),
body: { query: { term: { type: 'config' } } },
},
{ ignore: [404] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
describe('makeKQLUsageCollector', () => {
let usageCollectionMock: jest.Mocked<UsageCollectionSetup>;

const getIndexForType = () => Promise.resolve('.kibana');

beforeEach(() => {
usageCollectionMock = {
makeUsageCollector: jest.fn(),
Expand All @@ -20,12 +22,12 @@ describe('makeKQLUsageCollector', () => {
});

it('should call registerCollector', () => {
makeKQLUsageCollector(usageCollectionMock as UsageCollectionSetup, '.kibana');
makeKQLUsageCollector(usageCollectionMock as UsageCollectionSetup, getIndexForType);
expect(usageCollectionMock.registerCollector).toHaveBeenCalledTimes(1);
});

it('should call makeUsageCollector with type = kql', () => {
makeKQLUsageCollector(usageCollectionMock as UsageCollectionSetup, '.kibana');
makeKQLUsageCollector(usageCollectionMock as UsageCollectionSetup, getIndexForType);
expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalledTimes(1);
expect(usageCollectionMock.makeUsageCollector.mock.calls[0][0].type).toBe('kql');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
import { fetchProvider, Usage } from './fetch';

export function makeKQLUsageCollector(usageCollection: UsageCollectionSetup, kibanaIndex: string) {
export function makeKQLUsageCollector(
usageCollection: UsageCollectionSetup,
getIndexForType: (type: string) => Promise<string>
) {
const kqlUsageCollector = usageCollection.makeUsageCollector<Usage>({
type: 'kql',
fetch: fetchProvider(kibanaIndex),
fetch: fetchProvider(getIndexForType),
isReady: () => true,
schema: {
optInCount: { type: 'long' },
Expand Down
5 changes: 3 additions & 2 deletions src/plugins/data/server/search/collectors/search/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ interface SearchTelemetry {
'search-telemetry': CollectedUsage;
}

export function fetchProvider(kibanaIndex: string) {
export function fetchProvider(getIndexForType: (type: string) => Promise<string>) {
return async ({ esClient }: CollectorFetchContext): Promise<ReportedUsage> => {
const searchIndex = await getIndexForType('search-telemetry');
const esResponse = await esClient.search<SearchTelemetry>(
{
index: kibanaIndex,
index: searchIndex,
body: {
query: { term: { type: { value: 'search-telemetry' } } },
},
Expand Down
7 changes: 5 additions & 2 deletions src/plugins/data/server/search/collectors/search/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ export interface ReportedUsage {
averageDuration: number | null;
}

export function registerUsageCollector(usageCollection: UsageCollectionSetup, kibanaIndex: string) {
export function registerUsageCollector(
usageCollection: UsageCollectionSetup,
getIndexForType: (type: string) => Promise<string>
) {
try {
const collector = usageCollection.makeUsageCollector<ReportedUsage>({
type: 'search',
isReady: () => true,
fetch: fetchProvider(kibanaIndex),
fetch: fetchProvider(getIndexForType),
schema: {
successCount: { type: 'long' },
errorCount: { type: 'long' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ describe('fetchProvider', () => {

beforeEach(async () => {
const kibanaIndex = '123';
const getIndexForType = () => Promise.resolve(kibanaIndex);
mockLogger = {
warn: jest.fn(),
debug: jest.fn(),
} as any;
esClient = elasticsearchServiceMock.createElasticsearchClient();
fetchFn = fetchProvider(kibanaIndex, mockLogger);
fetchFn = fetchProvider(getIndexForType, mockLogger);
});

test('returns when ES returns no results', async () => {
Expand Down
Loading

0 comments on commit 5dc558a

Please sign in to comment.