Skip to content

Commit deebc34

Browse files
authored
Ability to have telemetry always opted in (#49798) (#50236)
* Initial work * WIP changes * Turn off banner when allowChangingOptInStatus is true * Fix bugs * Fix broken jest tests * Add jest tests for TelemetryForm * Add TelemetryOptIn jest tests * Make some adjustments to allow always being opted in * Disallow turning telemetry completely off * Fix bug in Joi config * Keep route there
1 parent 02a63d6 commit deebc34

File tree

15 files changed

+470
-23
lines changed

15 files changed

+470
-23
lines changed

src/legacy/core_plugins/telemetry/index.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* under the License.
1818
*/
1919

20+
import * as Rx from 'rxjs';
2021
import { resolve } from 'path';
2122
import JoiNamespace from 'joi';
2223
import { Server } from 'hapi';
@@ -45,6 +46,14 @@ const telemetry = (kibana: any) => {
4546
config(Joi: typeof JoiNamespace) {
4647
return Joi.object({
4748
enabled: Joi.boolean().default(true),
49+
optIn: Joi.when('allowChangingOptInStatus', {
50+
is: false,
51+
then: Joi.valid(true),
52+
otherwise: Joi.boolean()
53+
.allow(null)
54+
.default(null),
55+
}),
56+
allowChangingOptInStatus: Joi.boolean().default(true),
4857
// `config` is used internally and not intended to be set
4958
config: Joi.string().default(Joi.ref('$defaultConfigPath')),
5059
banner: Joi.boolean().default(true),
@@ -80,8 +89,25 @@ const telemetry = (kibana: any) => {
8089
},
8190
},
8291
async replaceInjectedVars(originalInjectedVars: any, request: any) {
92+
const config = request.server.config();
93+
const optIn = config.get('telemetry.optIn');
94+
const allowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus');
8395
const currentKibanaVersion = getCurrentKibanaVersion(request.server);
84-
const telemetryOptedIn = await getTelemetryOptIn({ request, currentKibanaVersion });
96+
let telemetryOptedIn: boolean | null;
97+
98+
if (typeof optIn === 'boolean' && !allowChangingOptInStatus) {
99+
// When not allowed to change optIn status and an optIn value is set, we'll overwrite with that
100+
telemetryOptedIn = optIn;
101+
} else {
102+
telemetryOptedIn = await getTelemetryOptIn({
103+
request,
104+
currentKibanaVersion,
105+
});
106+
if (telemetryOptedIn === null) {
107+
// In the senario there's no value set in telemetryOptedIn, we'll return optIn value
108+
telemetryOptedIn = optIn;
109+
}
110+
}
85111

86112
return {
87113
...originalInjectedVars,
@@ -93,28 +119,44 @@ const telemetry = (kibana: any) => {
93119
return {
94120
telemetryEnabled: getXpackConfigWithDeprecated(config, 'telemetry.enabled'),
95121
telemetryUrl: getXpackConfigWithDeprecated(config, 'telemetry.url'),
96-
telemetryBanner: getXpackConfigWithDeprecated(config, 'telemetry.banner'),
97-
telemetryOptedIn: null,
122+
telemetryBanner:
123+
config.get('telemetry.allowChangingOptInStatus') !== false &&
124+
getXpackConfigWithDeprecated(config, 'telemetry.banner'),
125+
telemetryOptedIn: config.get('telemetry.optIn'),
126+
allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'),
98127
};
99128
},
100129
hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'],
101130
mappings,
102131
},
103-
init(server: Server) {
132+
async init(server: Server) {
104133
const initializerContext = {
105134
env: {
106135
packageInfo: {
107136
version: getCurrentKibanaVersion(server),
108137
},
109138
},
139+
config: {
140+
create() {
141+
const config = server.config();
142+
return Rx.of({
143+
enabled: config.get('telemetry.enabled'),
144+
optIn: config.get('telemetry.optIn'),
145+
config: config.get('telemetry.config'),
146+
banner: config.get('telemetry.banner'),
147+
url: config.get('telemetry.url'),
148+
allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'),
149+
});
150+
},
151+
},
110152
} as PluginInitializerContext;
111153

112154
const coreSetup = ({
113155
http: { server },
114156
log: server.log,
115157
} as any) as CoreSetup;
116158

117-
telemetryPlugin(initializerContext).setup(coreSetup);
159+
await telemetryPlugin(initializerContext).setup(coreSetup);
118160

119161
// register collectors
120162
server.usage.collectorSet.register(createLocalizationUsageCollector(server));

src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/legacy/core_plugins/telemetry/public/components/telemetry_form.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ export class TelemetryForm extends Component {
7878
queryMatches,
7979
} = this.state;
8080

81+
if (!telemetryOptInProvider.canChangeOptInStatus()) {
82+
return null;
83+
}
84+
8185
if (queryMatches !== null && !queryMatches) {
8286
return null;
8387
}

src/legacy/core_plugins/telemetry/public/components/telemetry_form.test.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* under the License.
1818
*/
1919

20-
import '../services/telemetry_opt_in.test.mocks';
20+
import { mockInjectedMetadata } from '../services/telemetry_opt_in.test.mocks';
2121
import React from 'react';
2222
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
2323
import { TelemetryForm } from './telemetry_form';
@@ -33,6 +33,8 @@ const buildTelemetryOptInProvider = () => {
3333
switch (key) {
3434
case '$http':
3535
return mockHttp;
36+
case 'allowChangingOptInStatus':
37+
return true;
3638
default:
3739
return null;
3840
}
@@ -47,7 +49,23 @@ const buildTelemetryOptInProvider = () => {
4749
};
4850

4951
describe('TelemetryForm', () => {
50-
it('renders as expected', () => {
52+
it('renders as expected when allows to change optIn status', () => {
53+
mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true });
54+
55+
expect(shallowWithIntl(
56+
<TelemetryForm
57+
spacesEnabled={false}
58+
query={{ text: '' }}
59+
onQueryMatchChange={jest.fn()}
60+
telemetryOptInProvider={buildTelemetryOptInProvider()}
61+
enableSaving={true}
62+
/>)
63+
).toMatchSnapshot();
64+
});
65+
66+
it(`doesn't render form when not allowed to change optIn status`, () => {
67+
mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: false });
68+
5169
expect(shallowWithIntl(
5270
<TelemetryForm
5371
spacesEnabled={false}

src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/click_banner.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('click_banner', () => {
7272

7373
const optIn = true;
7474
const bannerId = 'bruce-banner';
75-
mockInjectedMetadata({ telemetryOptedIn: optIn });
75+
mockInjectedMetadata({ telemetryOptedIn: optIn, allowChangingOptInStatus: true });
7676
const telemetryOptInProvider = getTelemetryOptInProvider();
7777

7878
telemetryOptInProvider.setBannerId(bannerId);
@@ -92,7 +92,7 @@ describe('click_banner', () => {
9292
remove: sinon.spy()
9393
};
9494
const optIn = true;
95-
mockInjectedMetadata({ telemetryOptedIn: null });
95+
mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true });
9696
const telemetryOptInProvider = getTelemetryOptInProvider({ simulateFailure: true });
9797

9898
await clickBanner(telemetryOptInProvider, optIn, { _banners: banners, _toastNotifications: toastNotifications });
@@ -110,7 +110,7 @@ describe('click_banner', () => {
110110
remove: sinon.spy()
111111
};
112112
const optIn = false;
113-
mockInjectedMetadata({ telemetryOptedIn: null });
113+
mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true });
114114
const telemetryOptInProvider = getTelemetryOptInProvider({ simulateError: true });
115115

116116
await clickBanner(telemetryOptInProvider, optIn, { _banners: banners, _toastNotifications: toastNotifications });

src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const getTelemetryOptInProvider = (enabled, { simulateFailure = false } = {}) =>
3838
const chrome = {
3939
addBasePath: url => url
4040
};
41-
mockInjectedMetadata({ telemetryOptedIn: enabled });
41+
mockInjectedMetadata({ telemetryOptedIn: enabled, allowChangingOptInStatus: true });
4242

4343
const $injector = {
4444
get: (key) => {

src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const getMockInjector = () => {
3838
};
3939

4040
const getTelemetryOptInProvider = ({ telemetryOptedIn = null } = {}) => {
41-
mockInjectedMetadata({ telemetryOptedIn });
41+
mockInjectedMetadata({ telemetryOptedIn, allowChangingOptInStatus: true });
4242
const injector = getMockInjector();
4343
const chrome = {
4444
addBasePath: (url) => url

src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('TelemetryOptInProvider', () => {
3434
addBasePath: (url) => url
3535
};
3636

37-
mockInjectedMetadata({ telemetryOptedIn: optedIn });
37+
mockInjectedMetadata({ telemetryOptedIn: optedIn, allowChangingOptInStatus: true });
3838

3939
const mockInjector = {
4040
get: (key) => {

src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ import {
2424
} from '../../../../../core/public/mocks';
2525
const injectedMetadataMock = injectedMetadataServiceMock.createStartContract();
2626

27-
export function mockInjectedMetadata({ telemetryOptedIn }) {
27+
export function mockInjectedMetadata({ telemetryOptedIn, allowChangingOptInStatus }) {
2828
const mockGetInjectedVar = jest.fn().mockImplementation((key) => {
2929
switch (key) {
3030
case 'telemetryOptedIn': return telemetryOptedIn;
31+
case 'allowChangingOptInStatus': return allowChangingOptInStatus;
3132
default: throw new Error(`unexpected injectedVar ${key}`);
3233
}
3334
});

src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ let currentOptInStatus = false;
2828

2929
export function TelemetryOptInProvider($injector: any, chrome: any) {
3030
currentOptInStatus = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn') as boolean;
31+
const allowChangingOptInStatus = npStart.core.injectedMetadata.getInjectedVar(
32+
'allowChangingOptInStatus'
33+
) as boolean;
3134

3235
setCanTrackUiMetrics(currentOptInStatus);
3336
const provider = {
3437
getBannerId: () => bannerId,
3538
getOptIn: () => currentOptInStatus,
39+
canChangeOptInStatus: () => allowChangingOptInStatus,
3640
setBannerId(id: string) {
3741
bannerId = id;
3842
},

0 commit comments

Comments
 (0)