Skip to content

Commit a65ef13

Browse files
committed
[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
1 parent efb903e commit a65ef13

22 files changed

Lines changed: 269 additions & 145 deletions

File tree

packages/kbn-config/src/config_service.mock.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ const createConfigServiceMock = ({
2626
addDeprecationProvider: jest.fn(),
2727
validate: jest.fn(),
2828
getHandledDeprecatedConfigs: jest.fn(),
29+
getDeprecatedConfigPath$: jest.fn(),
2930
};
3031

3132
mocked.atPath.mockReturnValue(new BehaviorSubject(atPath));
3233
mocked.atPathSync.mockReturnValue(atPath);
3334
mocked.getConfig$.mockReturnValue(new BehaviorSubject(new ObjectToConfigAdapter(getConfig$)));
35+
mocked.getDeprecatedConfigPath$.mockReturnValue(new BehaviorSubject({ set: [], unset: [] }));
3436
mocked.getUsedPaths.mockResolvedValue([]);
3537
mocked.getUnusedPaths.mockResolvedValue([]);
3638
mocked.isEnabledAtPath.mockResolvedValue(true);

packages/kbn-config/src/config_service.test.mocks.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@ import type { applyDeprecations } from './deprecation/apply_deprecations';
1111

1212
jest.mock('../../../package.json', () => mockPackage);
1313

14+
const changedPaths = {
15+
set: ['foo'],
16+
unset: ['bar.baz'],
17+
};
18+
19+
export { changedPaths as mockedChangedPaths };
20+
1421
export const mockApplyDeprecations = jest.fn<
15-
Record<string, any>,
22+
ReturnType<typeof applyDeprecations>,
1623
Parameters<typeof applyDeprecations>
17-
>((config, deprecations, createAddDeprecation) => config);
24+
>((config, deprecations, createAddDeprecation) => ({ config, changedPaths }));
1825

1926
jest.mock('./deprecation/apply_deprecations', () => ({
2027
applyDeprecations: mockApplyDeprecations,

packages/kbn-config/src/config_service.test.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import { BehaviorSubject, Observable } from 'rxjs';
1010
import { first, take } from 'rxjs/operators';
1111

12-
import { mockApplyDeprecations } from './config_service.test.mocks';
12+
import { mockApplyDeprecations, mockedChangedPaths } from './config_service.test.mocks';
1313
import { rawConfigServiceMock } from './raw/raw_config_service.mock';
1414

1515
import { schema } from '@kbn/config-schema';
@@ -420,7 +420,7 @@ test('logs deprecation warning during validation', async () => {
420420
const addDeprecation = createAddDeprecation!('');
421421
addDeprecation({ message: 'some deprecation message' });
422422
addDeprecation({ message: 'another deprecation message' });
423-
return config;
423+
return { config, changedPaths: mockedChangedPaths };
424424
});
425425

426426
loggerMock.clear(logger);
@@ -446,12 +446,12 @@ test('does not log warnings for silent deprecations during validation', async ()
446446
const addDeprecation = createAddDeprecation!('');
447447
addDeprecation({ message: 'some deprecation message', silent: true });
448448
addDeprecation({ message: 'another deprecation message' });
449-
return config;
449+
return { config, changedPaths: mockedChangedPaths };
450450
})
451451
.mockImplementationOnce((config, deprecations, createAddDeprecation) => {
452452
const addDeprecation = createAddDeprecation!('');
453453
addDeprecation({ message: 'I am silent', silent: true });
454-
return config;
454+
return { config, changedPaths: mockedChangedPaths };
455455
});
456456

457457
loggerMock.clear(logger);
@@ -521,7 +521,7 @@ describe('getHandledDeprecatedConfigs', () => {
521521
const addDeprecation = createAddDeprecation!(deprecation.path);
522522
addDeprecation({ message: `some deprecation message`, documentationUrl: 'some-url' });
523523
});
524-
return config;
524+
return { config, changedPaths: mockedChangedPaths };
525525
});
526526

527527
await configService.validate();
@@ -541,3 +541,18 @@ describe('getHandledDeprecatedConfigs', () => {
541541
`);
542542
});
543543
});
544+
545+
describe('getDeprecatedConfigPath$', () => {
546+
it('returns all config paths changes during deprecation', async () => {
547+
const rawConfig$ = new BehaviorSubject<Record<string, any>>({ key: 'value' });
548+
const rawConfigProvider = rawConfigServiceMock.create({ rawConfig$ });
549+
550+
const configService = new ConfigService(rawConfigProvider, defaultEnv, logger);
551+
await configService.setSchema('key', schema.string());
552+
await configService.validate();
553+
554+
const deprecatedConfigPath$ = configService.getDeprecatedConfigPath$();
555+
const deprecatedConfigPath = await deprecatedConfigPath$.pipe(first()).toPromise();
556+
expect(deprecatedConfigPath).toEqual(mockedChangedPaths);
557+
});
558+
});

packages/kbn-config/src/config_service.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
ConfigDeprecationProvider,
2323
configDeprecationFactory,
2424
DeprecatedConfigDetails,
25+
ChangedDeprecatedPaths,
2526
} from './deprecation';
2627
import { LegacyObjectToConfigAdapter } from './legacy';
2728

@@ -36,6 +37,10 @@ export class ConfigService {
3637
private validated = false;
3738
private readonly config$: Observable<Config>;
3839
private lastConfig?: Config;
40+
private readonly deprecatedConfigPaths = new BehaviorSubject<ChangedDeprecatedPaths>({
41+
set: [],
42+
unset: [],
43+
});
3944

4045
/**
4146
* Whenever a config if read at a path, we mark that path as 'handled'. We can
@@ -57,7 +62,8 @@ export class ConfigService {
5762
this.config$ = combineLatest([this.rawConfigProvider.getConfig$(), this.deprecations]).pipe(
5863
map(([rawConfig, deprecations]) => {
5964
const migrated = applyDeprecations(rawConfig, deprecations);
60-
return new LegacyObjectToConfigAdapter(migrated);
65+
this.deprecatedConfigPaths.next(migrated.changedPaths);
66+
return new LegacyObjectToConfigAdapter(migrated.config);
6167
}),
6268
tap((config) => {
6369
this.lastConfig = config;
@@ -191,6 +197,10 @@ export class ConfigService {
191197
return config.getFlattenedPaths().filter((path) => isPathHandled(path, handledPaths));
192198
}
193199

200+
public getDeprecatedConfigPath$() {
201+
return this.deprecatedConfigPaths.asObservable();
202+
}
203+
194204
private async logDeprecation() {
195205
const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise();
196206
const deprecations = await this.deprecations.pipe(take(1)).toPromise();

packages/kbn-config/src/deprecation/apply_deprecations.test.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe('applyDeprecations', () => {
8282
it('returns the migrated config', () => {
8383
const initialConfig = { foo: 'bar', deprecated: 'deprecated', renamed: 'renamed' };
8484

85-
const migrated = applyDeprecations(initialConfig, [
85+
const { config: migrated } = applyDeprecations(initialConfig, [
8686
wrapHandler(deprecations.unused('deprecated')),
8787
wrapHandler(deprecations.rename('renamed', 'newname')),
8888
]);
@@ -93,7 +93,7 @@ describe('applyDeprecations', () => {
9393
it('does not alter the initial config', () => {
9494
const initialConfig = { foo: 'bar', deprecated: 'deprecated' };
9595

96-
const migrated = applyDeprecations(initialConfig, [
96+
const { config: migrated } = applyDeprecations(initialConfig, [
9797
wrapHandler(deprecations.unused('deprecated')),
9898
]);
9999

@@ -110,7 +110,7 @@ describe('applyDeprecations', () => {
110110
return { unset: [{ path: 'unknown' }] };
111111
});
112112

113-
const migrated = applyDeprecations(
113+
const { config: migrated } = applyDeprecations(
114114
initialConfig,
115115
[wrapHandler(handler, 'pathA')],
116116
createAddDeprecation
@@ -128,12 +128,33 @@ describe('applyDeprecations', () => {
128128
return { rewrite: [{ path: 'foo' }] };
129129
});
130130

131-
const migrated = applyDeprecations(
131+
const { config: migrated } = applyDeprecations(
132132
initialConfig,
133133
[wrapHandler(handler, 'pathA')],
134134
createAddDeprecation
135135
);
136136

137137
expect(migrated).toEqual(initialConfig);
138138
});
139+
140+
it('returns a list of changes config paths', () => {
141+
const addDeprecation = jest.fn();
142+
const createAddDeprecation = jest.fn().mockReturnValue(addDeprecation);
143+
const initialConfig = { foo: 'bar', deprecated: 'deprecated' };
144+
145+
const handler = jest.fn().mockImplementation((config) => {
146+
return { set: [{ path: 'foo', value: 'bar' }], unset: [{ path: 'baz' }] };
147+
});
148+
149+
const { changedPaths } = applyDeprecations(
150+
initialConfig,
151+
[wrapHandler(handler, 'pathA')],
152+
createAddDeprecation
153+
);
154+
155+
expect(changedPaths).toEqual({
156+
set: ['foo'],
157+
unset: ['baz'],
158+
});
159+
});
139160
});

packages/kbn-config/src/deprecation/apply_deprecations.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88

99
import { cloneDeep, unset } from 'lodash';
1010
import { set } from '@elastic/safer-lodash-set';
11-
import { ConfigDeprecationWithContext, AddConfigDeprecation } from './types';
11+
import type {
12+
AddConfigDeprecation,
13+
ChangedDeprecatedPaths,
14+
ConfigDeprecationWithContext,
15+
} from './types';
1216

1317
const noopAddDeprecationFactory: () => AddConfigDeprecation = () => () => undefined;
1418
/**
@@ -22,22 +26,31 @@ export const applyDeprecations = (
2226
config: Record<string, any>,
2327
deprecations: ConfigDeprecationWithContext[],
2428
createAddDeprecation: (pluginId: string) => AddConfigDeprecation = noopAddDeprecationFactory
25-
) => {
29+
): { config: Record<string, any>; changedPaths: ChangedDeprecatedPaths } => {
2630
const result = cloneDeep(config);
31+
const changedPaths: ChangedDeprecatedPaths = {
32+
set: [],
33+
unset: [],
34+
};
2735
deprecations.forEach(({ deprecation, path }) => {
2836
const commands = deprecation(result, path, createAddDeprecation(path));
2937
if (commands) {
3038
if (commands.set) {
39+
changedPaths.set.push(...commands.set.map((c) => c.path));
3140
commands.set.forEach(function ({ path: commandPath, value }) {
3241
set(result, commandPath, value);
3342
});
3443
}
3544
if (commands.unset) {
45+
changedPaths.unset.push(...commands.unset.map((c) => c.path));
3646
commands.unset.forEach(function ({ path: commandPath }) {
3747
unset(result, commandPath);
3848
});
3949
}
4050
}
4151
});
42-
return result;
52+
return {
53+
config: result,
54+
changedPaths,
55+
};
4356
};

packages/kbn-config/src/deprecation/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export type {
1414
AddConfigDeprecation,
1515
ConfigDeprecationProvider,
1616
DeprecatedConfigDetails,
17+
ChangedDeprecatedPaths,
1718
} from './types';
1819
export { configDeprecationFactory } from './deprecation_factory';
1920
export { applyDeprecations } from './apply_deprecations';

packages/kbn-config/src/deprecation/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ export type ConfigDeprecation = (
5555
addDeprecation: AddConfigDeprecation
5656
) => void | ConfigDeprecationCommand;
5757

58+
/**
59+
* List of config paths changed during deprecation.
60+
*
61+
* @public
62+
*/
63+
export interface ChangedDeprecatedPaths {
64+
set: string[];
65+
unset: string[];
66+
}
67+
5868
/**
5969
* Outcome of deprecation operation. Allows mutating config values in a declarative way.
6070
*

packages/kbn-config/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type {
1313
ConfigDeprecationWithContext,
1414
ConfigDeprecation,
1515
ConfigDeprecationCommand,
16+
ChangedDeprecatedPaths,
1617
} from './deprecation';
1718

1819
export { applyDeprecations, configDeprecationFactory } from './deprecation';

src/core/server/config/test_utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function collectDeprecations(
1616
) {
1717
const deprecations = provider(configDeprecationFactory);
1818
const deprecationMessages: string[] = [];
19-
const migrated = applyDeprecations(
19+
const { config: migrated } = applyDeprecations(
2020
settings,
2121
deprecations.map((deprecation) => ({
2222
deprecation,

0 commit comments

Comments
 (0)