[telemetry] report config deprecations (#99887)

* return the list of changes config keys during deprecation

* gather changed config keys in the core

* adjust Security plugin deprecations tests

* update docs

* update interface

* update telemetry schema

* update spaces tests

* update tests in other x-pack plugins

* remove testing instruction

* improve tests. get rid of snapshots
This commit is contained in:
Mikhail Shustov 2021-05-26 10:57:01 +02:00 committed by GitHub
parent 987c736957
commit f915b6fe73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 269 additions and 145 deletions

View file

@ -26,11 +26,13 @@ const createConfigServiceMock = ({
addDeprecationProvider: jest.fn(),
validate: jest.fn(),
getHandledDeprecatedConfigs: jest.fn(),
getDeprecatedConfigPath$: jest.fn(),
};
mocked.atPath.mockReturnValue(new BehaviorSubject(atPath));
mocked.atPathSync.mockReturnValue(atPath);
mocked.getConfig$.mockReturnValue(new BehaviorSubject(new ObjectToConfigAdapter(getConfig$)));
mocked.getDeprecatedConfigPath$.mockReturnValue(new BehaviorSubject({ set: [], unset: [] }));
mocked.getUsedPaths.mockResolvedValue([]);
mocked.getUnusedPaths.mockResolvedValue([]);
mocked.isEnabledAtPath.mockResolvedValue(true);

View file

@ -11,10 +11,17 @@ import type { applyDeprecations } from './deprecation/apply_deprecations';
jest.mock('../../../package.json', () => mockPackage);
const changedPaths = {
set: ['foo'],
unset: ['bar.baz'],
};
export { changedPaths as mockedChangedPaths };
export const mockApplyDeprecations = jest.fn<
Record<string, any>,
ReturnType<typeof applyDeprecations>,
Parameters<typeof applyDeprecations>
>((config, deprecations, createAddDeprecation) => config);
>((config, deprecations, createAddDeprecation) => ({ config, changedPaths }));
jest.mock('./deprecation/apply_deprecations', () => ({
applyDeprecations: mockApplyDeprecations,

View file

@ -9,7 +9,7 @@
import { BehaviorSubject, Observable } from 'rxjs';
import { first, take } from 'rxjs/operators';
import { mockApplyDeprecations } from './config_service.test.mocks';
import { mockApplyDeprecations, mockedChangedPaths } from './config_service.test.mocks';
import { rawConfigServiceMock } from './raw/raw_config_service.mock';
import { schema } from '@kbn/config-schema';
@ -420,7 +420,7 @@ test('logs deprecation warning during validation', async () => {
const addDeprecation = createAddDeprecation!('');
addDeprecation({ message: 'some deprecation message' });
addDeprecation({ message: 'another deprecation message' });
return config;
return { config, changedPaths: mockedChangedPaths };
});
loggerMock.clear(logger);
@ -446,12 +446,12 @@ test('does not log warnings for silent deprecations during validation', async ()
const addDeprecation = createAddDeprecation!('');
addDeprecation({ message: 'some deprecation message', silent: true });
addDeprecation({ message: 'another deprecation message' });
return config;
return { config, changedPaths: mockedChangedPaths };
})
.mockImplementationOnce((config, deprecations, createAddDeprecation) => {
const addDeprecation = createAddDeprecation!('');
addDeprecation({ message: 'I am silent', silent: true });
return config;
return { config, changedPaths: mockedChangedPaths };
});
loggerMock.clear(logger);
@ -521,7 +521,7 @@ describe('getHandledDeprecatedConfigs', () => {
const addDeprecation = createAddDeprecation!(deprecation.path);
addDeprecation({ message: `some deprecation message`, documentationUrl: 'some-url' });
});
return config;
return { config, changedPaths: mockedChangedPaths };
});
await configService.validate();
@ -541,3 +541,18 @@ describe('getHandledDeprecatedConfigs', () => {
`);
});
});
describe('getDeprecatedConfigPath$', () => {
it('returns all config paths changes during deprecation', async () => {
const rawConfig$ = new BehaviorSubject<Record<string, any>>({ key: 'value' });
const rawConfigProvider = rawConfigServiceMock.create({ rawConfig$ });
const configService = new ConfigService(rawConfigProvider, defaultEnv, logger);
await configService.setSchema('key', schema.string());
await configService.validate();
const deprecatedConfigPath$ = configService.getDeprecatedConfigPath$();
const deprecatedConfigPath = await deprecatedConfigPath$.pipe(first()).toPromise();
expect(deprecatedConfigPath).toEqual(mockedChangedPaths);
});
});

View file

@ -22,6 +22,7 @@ import {
ConfigDeprecationProvider,
configDeprecationFactory,
DeprecatedConfigDetails,
ChangedDeprecatedPaths,
} from './deprecation';
import { LegacyObjectToConfigAdapter } from './legacy';
@ -36,6 +37,10 @@ export class ConfigService {
private validated = false;
private readonly config$: Observable<Config>;
private lastConfig?: Config;
private readonly deprecatedConfigPaths = new BehaviorSubject<ChangedDeprecatedPaths>({
set: [],
unset: [],
});
/**
* Whenever a config if read at a path, we mark that path as 'handled'. We can
@ -57,7 +62,8 @@ export class ConfigService {
this.config$ = combineLatest([this.rawConfigProvider.getConfig$(), this.deprecations]).pipe(
map(([rawConfig, deprecations]) => {
const migrated = applyDeprecations(rawConfig, deprecations);
return new LegacyObjectToConfigAdapter(migrated);
this.deprecatedConfigPaths.next(migrated.changedPaths);
return new LegacyObjectToConfigAdapter(migrated.config);
}),
tap((config) => {
this.lastConfig = config;
@ -191,6 +197,10 @@ export class ConfigService {
return config.getFlattenedPaths().filter((path) => isPathHandled(path, handledPaths));
}
public getDeprecatedConfigPath$() {
return this.deprecatedConfigPaths.asObservable();
}
private async logDeprecation() {
const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise();
const deprecations = await this.deprecations.pipe(take(1)).toPromise();

View file

@ -82,7 +82,7 @@ describe('applyDeprecations', () => {
it('returns the migrated config', () => {
const initialConfig = { foo: 'bar', deprecated: 'deprecated', renamed: 'renamed' };
const migrated = applyDeprecations(initialConfig, [
const { config: migrated } = applyDeprecations(initialConfig, [
wrapHandler(deprecations.unused('deprecated')),
wrapHandler(deprecations.rename('renamed', 'newname')),
]);
@ -93,7 +93,7 @@ describe('applyDeprecations', () => {
it('does not alter the initial config', () => {
const initialConfig = { foo: 'bar', deprecated: 'deprecated' };
const migrated = applyDeprecations(initialConfig, [
const { config: migrated } = applyDeprecations(initialConfig, [
wrapHandler(deprecations.unused('deprecated')),
]);
@ -110,7 +110,7 @@ describe('applyDeprecations', () => {
return { unset: [{ path: 'unknown' }] };
});
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
initialConfig,
[wrapHandler(handler, 'pathA')],
createAddDeprecation
@ -128,7 +128,7 @@ describe('applyDeprecations', () => {
return { rewrite: [{ path: 'foo' }] };
});
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
initialConfig,
[wrapHandler(handler, 'pathA')],
createAddDeprecation
@ -136,4 +136,25 @@ describe('applyDeprecations', () => {
expect(migrated).toEqual(initialConfig);
});
it('returns a list of changes config paths', () => {
const addDeprecation = jest.fn();
const createAddDeprecation = jest.fn().mockReturnValue(addDeprecation);
const initialConfig = { foo: 'bar', deprecated: 'deprecated' };
const handler = jest.fn().mockImplementation((config) => {
return { set: [{ path: 'foo', value: 'bar' }], unset: [{ path: 'baz' }] };
});
const { changedPaths } = applyDeprecations(
initialConfig,
[wrapHandler(handler, 'pathA')],
createAddDeprecation
);
expect(changedPaths).toEqual({
set: ['foo'],
unset: ['baz'],
});
});
});

View file

@ -8,7 +8,11 @@
import { cloneDeep, unset } from 'lodash';
import { set } from '@elastic/safer-lodash-set';
import { ConfigDeprecationWithContext, AddConfigDeprecation } from './types';
import type {
AddConfigDeprecation,
ChangedDeprecatedPaths,
ConfigDeprecationWithContext,
} from './types';
const noopAddDeprecationFactory: () => AddConfigDeprecation = () => () => undefined;
/**
@ -22,22 +26,31 @@ export const applyDeprecations = (
config: Record<string, any>,
deprecations: ConfigDeprecationWithContext[],
createAddDeprecation: (pluginId: string) => AddConfigDeprecation = noopAddDeprecationFactory
) => {
): { config: Record<string, any>; changedPaths: ChangedDeprecatedPaths } => {
const result = cloneDeep(config);
const changedPaths: ChangedDeprecatedPaths = {
set: [],
unset: [],
};
deprecations.forEach(({ deprecation, path }) => {
const commands = deprecation(result, path, createAddDeprecation(path));
if (commands) {
if (commands.set) {
changedPaths.set.push(...commands.set.map((c) => c.path));
commands.set.forEach(function ({ path: commandPath, value }) {
set(result, commandPath, value);
});
}
if (commands.unset) {
changedPaths.unset.push(...commands.unset.map((c) => c.path));
commands.unset.forEach(function ({ path: commandPath }) {
unset(result, commandPath);
});
}
}
});
return result;
return {
config: result,
changedPaths,
};
};

View file

@ -14,6 +14,7 @@ export type {
AddConfigDeprecation,
ConfigDeprecationProvider,
DeprecatedConfigDetails,
ChangedDeprecatedPaths,
} from './types';
export { configDeprecationFactory } from './deprecation_factory';
export { applyDeprecations } from './apply_deprecations';

View file

@ -55,6 +55,16 @@ export type ConfigDeprecation = (
addDeprecation: AddConfigDeprecation
) => void | ConfigDeprecationCommand;
/**
* List of config paths changed during deprecation.
*
* @public
*/
export interface ChangedDeprecatedPaths {
set: string[];
unset: string[];
}
/**
* Outcome of deprecation operation. Allows mutating config values in a declarative way.
*

View file

@ -13,6 +13,7 @@ export type {
ConfigDeprecationWithContext,
ConfigDeprecation,
ConfigDeprecationCommand,
ChangedDeprecatedPaths,
} from './deprecation';
export { applyDeprecations, configDeprecationFactory } from './deprecation';

View file

@ -16,7 +16,7 @@ function collectDeprecations(
) {
const deprecations = provider(configDeprecationFactory);
const deprecationMessages: string[] = [];
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
settings,
deprecations.map((deprecation) => ({
deprecation,

View file

@ -116,6 +116,10 @@ const createStartContractMock = () => {
maxImportExportSize: 10000,
maxImportPayloadBytes: 26214400,
},
deprecatedKeys: {
set: ['path.to.a.prop'],
unset: [],
},
},
environment: {
memory: {

View file

@ -91,7 +91,8 @@ describe('CoreUsageDataService', () => {
const savedObjectsStartPromise = Promise.resolve(
savedObjectsServiceMock.createStartContract()
);
service.setup({ http, metrics, savedObjectsStartPromise });
const changedDeprecatedConfigPath$ = configServiceMock.create().getDeprecatedConfigPath$();
service.setup({ http, metrics, savedObjectsStartPromise, changedDeprecatedConfigPath$ });
const savedObjects = await savedObjectsStartPromise;
expect(savedObjects.createInternalRepository).toHaveBeenCalledTimes(1);
@ -105,7 +106,13 @@ describe('CoreUsageDataService', () => {
const savedObjectsStartPromise = Promise.resolve(
savedObjectsServiceMock.createStartContract()
);
const coreUsageData = service.setup({ http, metrics, savedObjectsStartPromise });
const changedDeprecatedConfigPath$ = configServiceMock.create().getDeprecatedConfigPath$();
const coreUsageData = service.setup({
http,
metrics,
savedObjectsStartPromise,
changedDeprecatedConfigPath$,
});
const typeRegistry = typeRegistryMock.create();
coreUsageData.registerType(typeRegistry);
@ -126,7 +133,13 @@ describe('CoreUsageDataService', () => {
const savedObjectsStartPromise = Promise.resolve(
savedObjectsServiceMock.createStartContract()
);
const coreUsageData = service.setup({ http, metrics, savedObjectsStartPromise });
const changedDeprecatedConfigPath$ = configServiceMock.create().getDeprecatedConfigPath$();
const coreUsageData = service.setup({
http,
metrics,
savedObjectsStartPromise,
changedDeprecatedConfigPath$,
});
const usageStatsClient = coreUsageData.getClient();
expect(usageStatsClient).toBeInstanceOf(CoreUsageStatsClient);
@ -142,7 +155,11 @@ describe('CoreUsageDataService', () => {
const savedObjectsStartPromise = Promise.resolve(
savedObjectsServiceMock.createStartContract()
);
service.setup({ http, metrics, savedObjectsStartPromise });
const changedDeprecatedConfigPath$ = new BehaviorSubject({
set: ['new.path'],
unset: ['deprecated.path'],
});
service.setup({ http, metrics, savedObjectsStartPromise, changedDeprecatedConfigPath$ });
const elasticsearch = elasticsearchServiceMock.createStart();
elasticsearch.client.asInternalUser.cat.indices.mockResolvedValueOnce({
body: [
@ -180,6 +197,14 @@ describe('CoreUsageDataService', () => {
expect(getCoreUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"config": Object {
"deprecatedKeys": Object {
"set": Array [
"new.path",
],
"unset": Array [
"deprecated.path",
],
},
"elasticsearch": Object {
"apiVersion": "master",
"customHeadersConfigured": false,
@ -381,12 +406,10 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.enabled": "[redacted]",
"pluginAB.enabled": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.enabled': '[redacted]',
'pluginAB.enabled': '[redacted]',
});
});
it('returns an object of plugin config usage', async () => {
@ -418,23 +441,21 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"elasticsearch.password": "[redacted]",
"elasticsearch.username": "[redacted]",
"logging.json": false,
"pluginA.arrayOfNumbers": "[redacted]",
"pluginA.enabled": true,
"pluginA.objectConfig.debug": true,
"pluginA.objectConfig.username": "[redacted]",
"pluginAB.enabled": false,
"pluginB.arrayOfObjects": "[redacted]",
"plugins.paths": "[redacted]",
"server.basePath": "/zvt",
"server.port": 5603,
"server.rewriteBasePath": true,
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'elasticsearch.password': '[redacted]',
'elasticsearch.username': '[redacted]',
'logging.json': false,
'pluginA.arrayOfNumbers': '[redacted]',
'pluginA.enabled': true,
'pluginA.objectConfig.debug': true,
'pluginA.objectConfig.username': '[redacted]',
'pluginAB.enabled': false,
'pluginB.arrayOfObjects': '[redacted]',
'plugins.paths': '[redacted]',
'server.basePath': '/zvt',
'server.port': 5603,
'server.rewriteBasePath': true,
});
});
describe('config explicitly exposed to usage', () => {
@ -457,12 +478,10 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.objectConfig.debug": "[redacted]",
"server.basePath": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.objectConfig.debug': '[redacted]',
'server.basePath': '[redacted]',
});
});
it('returns config value on safe complete match', async () => {
@ -478,11 +497,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"server.basePath": "/zvt",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'server.basePath': '/zvt',
});
});
it('returns [redacted] on unsafe parent match', async () => {
@ -501,12 +518,10 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.objectConfig.debug": "[redacted]",
"pluginA.objectConfig.username": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.objectConfig.debug': '[redacted]',
'pluginA.objectConfig.username': '[redacted]',
});
});
it('returns config value on safe parent match', async () => {
@ -525,12 +540,10 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.objectConfig.debug": true,
"pluginA.objectConfig.username": "some_user",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.objectConfig.debug': true,
'pluginA.objectConfig.username': 'some_user',
});
});
it('returns [redacted] on explicitly marked as safe array of objects', async () => {
@ -546,11 +559,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginB.arrayOfObjects": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginB.arrayOfObjects': '[redacted]',
});
});
it('returns values on explicitly marked as safe array of numbers', async () => {
@ -566,15 +577,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.arrayOfNumbers": Array [
1,
2,
3,
],
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.arrayOfNumbers': [1, 2, 3],
});
});
it('returns values on explicitly marked as safe array of strings', async () => {
@ -590,15 +595,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"plugins.paths": Array [
"pluginA",
"pluginAB",
"pluginB",
],
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'plugins.paths': ['pluginA', 'pluginAB', 'pluginB'],
});
});
});
@ -619,12 +618,10 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.objectConfig.debug": "[redacted]",
"pluginA.objectConfig.username": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.objectConfig.debug': '[redacted]',
'pluginA.objectConfig.username': '[redacted]',
});
});
it('returns config value on safe parent match', async () => {
@ -640,13 +637,11 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"elasticsearch.password": "[redacted]",
"elasticsearch.username": "[redacted]",
"pluginA.objectConfig.username": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'elasticsearch.password': '[redacted]',
'elasticsearch.username': '[redacted]',
'pluginA.objectConfig.username': '[redacted]',
});
});
it('returns [redacted] on implicit array of objects', async () => {
@ -658,11 +653,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginB.arrayOfObjects": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginB.arrayOfObjects': '[redacted]',
});
});
it('returns values on implicit array of numbers', async () => {
@ -674,16 +667,11 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"pluginA.arrayOfNumbers": Array [
1,
2,
3,
],
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'pluginA.arrayOfNumbers': [1, 2, 3],
});
});
it('returns [redacted] on implicit array of strings', async () => {
configService.getUsedPaths.mockResolvedValue(['plugins.paths']);
@ -693,11 +681,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"plugins.paths": "[redacted]",
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'plugins.paths': '[redacted]',
});
});
it('returns config value for numbers', async () => {
@ -709,11 +695,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"server.port": 5603,
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'server.port': 5603,
});
});
it('returns config value for booleans', async () => {
@ -728,12 +712,10 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"logging.json": false,
"pluginA.objectConfig.debug": true,
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'logging.json': false,
'pluginA.objectConfig.debug': true,
});
});
it('ignores exposed to usage configs but not used', async () => {
@ -749,11 +731,9 @@ describe('CoreUsageDataService', () => {
elasticsearch,
});
await expect(getConfigsUsageData()).resolves.toMatchInlineSnapshot(`
Object {
"logging.json": false,
}
`);
await expect(getConfigsUsageData()).resolves.toEqual({
'logging.json': false,
});
});
});
});
@ -779,7 +759,8 @@ describe('CoreUsageDataService', () => {
savedObjectsServiceMock.createStartContract()
);
service.setup({ http, metrics, savedObjectsStartPromise });
const changedDeprecatedConfigPath$ = configServiceMock.create().getDeprecatedConfigPath$();
service.setup({ http, metrics, savedObjectsStartPromise, changedDeprecatedConfigPath$ });
// Use the stopTimer$ to delay calling stop() until the third frame
const stopTimer$ = cold('---a|');

View file

@ -6,10 +6,10 @@
* Side Public License, v 1.
*/
import { Subject } from 'rxjs';
import { Subject, Observable } from 'rxjs';
import { takeUntil, first } from 'rxjs/operators';
import { get } from 'lodash';
import { hasConfigPathIntersection } from '@kbn/config';
import { hasConfigPathIntersection, ChangedDeprecatedPaths } from '@kbn/config';
import { CoreService } from 'src/core/types';
import { Logger, SavedObjectsServiceStart, SavedObjectTypeRegistry } from 'src/core/server';
@ -39,6 +39,7 @@ export interface SetupDeps {
http: InternalHttpServiceSetup;
metrics: MetricsServiceSetup;
savedObjectsStartPromise: Promise<SavedObjectsServiceStart>;
changedDeprecatedConfigPath$: Observable<ChangedDeprecatedPaths>;
}
export interface StartDeps {
@ -89,6 +90,7 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
private opsMetrics?: OpsMetrics;
private kibanaConfig?: KibanaConfigType;
private coreUsageStatsClient?: CoreUsageStatsClient;
private deprecatedConfigPaths: ChangedDeprecatedPaths = { set: [], unset: [] };
constructor(core: CoreContext) {
this.logger = core.logger.get('core-usage-stats-service');
@ -257,6 +259,8 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
maxImportPayloadBytes: this.soConfig.maxImportPayloadBytes.getValueInBytes(),
maxImportExportSize: this.soConfig.maxImportExportSize,
},
deprecatedKeys: this.deprecatedConfigPaths,
},
environment: {
memory: {
@ -376,7 +380,7 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
}, {} as Record<string, any | any[]>);
}
setup({ http, metrics, savedObjectsStartPromise }: SetupDeps) {
setup({ http, metrics, savedObjectsStartPromise, changedDeprecatedConfigPath$ }: SetupDeps) {
metrics
.getOpsMetrics$()
.pipe(takeUntil(this.stop$))
@ -417,6 +421,10 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
this.kibanaConfig = config;
});
changedDeprecatedConfigPath$
.pipe(takeUntil(this.stop$))
.subscribe((deprecatedConfigPaths) => (this.deprecatedConfigPaths = deprecatedConfigPaths));
const internalRepositoryPromise = savedObjectsStartPromise.then((savedObjects) =>
savedObjects.createInternalRepository([CORE_USAGE_STATS_TYPE])
);

View file

@ -254,6 +254,11 @@ export interface CoreConfigUsageData {
// uiSettings: {
// overridesCount: number;
// };
deprecatedKeys: {
set: string[];
unset: string[];
};
}
/** @internal */

View file

@ -399,6 +399,11 @@ export interface ContextSetup {
// @internal
export interface CoreConfigUsageData {
// (undocumented)
deprecatedKeys: {
set: string[];
unset: string[];
};
// (undocumented)
elasticsearch: {
sniffOnStart: boolean;

View file

@ -153,6 +153,7 @@ export class Server {
http: httpSetup,
metrics: metricsSetup,
savedObjectsStartPromise: this.savedObjectsStartPromise,
changedDeprecatedConfigPath$: this.configService.getDeprecatedConfigPath$(),
});
const savedObjectsSetup = await this.savedObjects.setup({
@ -265,6 +266,7 @@ export class Server {
await this.http.start();
startTransaction?.end();
return this.coreStart;
}

View file

@ -308,6 +308,23 @@ export function getCoreUsageCollector(
},
},
},
deprecatedKeys: {
set: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'Config path added during config deprecation.' },
},
},
unset: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'Config path removed during config deprecation.' },
},
},
},
},
environment: {
memory: {

View file

@ -6950,6 +6950,28 @@
}
}
}
},
"deprecatedKeys": {
"properties": {
"set": {
"type": "array",
"items": {
"type": "keyword",
"_meta": {
"description": "Config path added during config deprecation."
}
}
},
"unset": {
"type": "array",
"items": {
"type": "keyword",
"_meta": {
"description": "Config path removed during config deprecation."
}
}
}
}
}
}
},

View file

@ -15,7 +15,7 @@ const applyReportingDeprecations = (settings: Record<string, any> = {}) => {
const deprecationMessages: string[] = [];
const _config: any = {};
_config[CONFIG_PATH] = settings;
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
_config,
deprecations.map((deprecation) => ({
deprecation,

View file

@ -14,7 +14,7 @@ import { securityConfigDeprecationProvider } from './config_deprecations';
const applyConfigDeprecations = (settings: Record<string, any> = {}) => {
const deprecations = securityConfigDeprecationProvider(configDeprecationFactory);
const deprecationMessages: string[] = [];
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
settings,
deprecations.map((deprecation) => ({
deprecation,

View file

@ -13,7 +13,7 @@ import { spacesConfigDeprecationProvider } from './config';
const applyConfigDeprecations = (settings: Record<string, any> = {}) => {
const deprecations = spacesConfigDeprecationProvider(configDeprecationFactory);
const deprecationMessages: string[] = [];
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
settings,
deprecations.map((deprecation) => ({
deprecation,

View file

@ -16,7 +16,7 @@ const applyTaskManagerDeprecations = (settings: Record<string, unknown> = {}) =>
const _config = {
[CONFIG_PATH]: settings,
};
const migrated = applyDeprecations(
const { config: migrated } = applyDeprecations(
_config,
deprecations.map((deprecation) => ({
deprecation,