Skip to content

Commit b27e281

Browse files
authored
remove FeatureInsight tag (microsoft#203295)
- remove FeatureInsight tag - report event per setting with owner and purpose information - adopt the opted in settings
1 parent 3b82957 commit b27e281

File tree

9 files changed

+198
-117
lines changed

9 files changed

+198
-117
lines changed

src/vs/editor/common/config/editorOptions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2818,7 +2818,7 @@ class EditorStickyScroll extends BaseEditorOption<EditorOption.stickyScroll, IEd
28182818
type: 'boolean',
28192819
default: defaults.enabled,
28202820
description: nls.localize('editor.stickyScroll.enabled', "Shows the nested current scopes during the scroll at the top of the editor."),
2821-
tags: ['experimental', 'FeatureInsight']
2821+
tags: ['experimental']
28222822
},
28232823
'editor.stickyScroll.maxLineCount': {
28242824
type: 'number',

src/vs/workbench/browser/workbench.contribution.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,6 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
505505
localize('workbench.activityBar.location.top', "Show the Activity Bar on top of the Primary Side Bar."),
506506
localize('workbench.activityBar.location.hide', "Hide the Activity Bar.")
507507
],
508-
tags: ['FeatureInsight']
509508
},
510509
'workbench.activityBar.iconClickBehavior': {
511510
'type': 'string',

src/vs/workbench/contrib/chat/common/chatService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,5 @@ export interface IChatService {
313313

314314
transferChatSession(transferredSessionData: IChatTransferredSessionData, toWorkspace: URI): void;
315315
}
316+
317+
export const KEYWORD_ACTIVIATION_SETTING_ID = 'accessibility.voice.keywordActivation';

src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
1717
import { spinningLoading } from 'vs/platform/theme/common/iconRegistry';
1818
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
1919
import { IChatWidget, IChatWidgetService, IQuickChatService } from 'vs/workbench/contrib/chat/browser/chat';
20-
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
20+
import { IChatService, KEYWORD_ACTIVIATION_SETTING_ID } from 'vs/workbench/contrib/chat/common/chatService';
2121
import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, MENU_INLINE_CHAT_INPUT } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
2222
import { CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
2323
import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController';
@@ -771,15 +771,13 @@ function supportsKeywordActivation(configurationService: IConfigurationService,
771771
return false;
772772
}
773773

774-
const value = configurationService.getValue(KeywordActivationContribution.SETTINGS_ID);
774+
const value = configurationService.getValue(KEYWORD_ACTIVIATION_SETTING_ID);
775775

776776
return typeof value === 'string' && value !== KeywordActivationContribution.SETTINGS_VALUE.OFF;
777777
}
778778

779779
export class KeywordActivationContribution extends Disposable implements IWorkbenchContribution {
780780

781-
static SETTINGS_ID = 'accessibility.voice.keywordActivation';
782-
783781
static SETTINGS_VALUE = {
784782
OFF: 'off',
785783
INLINE_CHAT: 'inlineChat',
@@ -817,7 +815,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
817815
this._register(this.speechService.onDidEndSpeechToTextSession(() => this.handleKeywordActivation()));
818816

819817
this._register(this.configurationService.onDidChangeConfiguration(e => {
820-
if (e.affectsConfiguration(KeywordActivationContribution.SETTINGS_ID)) {
818+
if (e.affectsConfiguration(KEYWORD_ACTIVIATION_SETTING_ID)) {
821819
this.handleKeywordActivation();
822820
}
823821
}));
@@ -836,7 +834,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
836834
registry.registerConfiguration({
837835
...accessibilityConfigurationNodeBase,
838836
properties: {
839-
[KeywordActivationContribution.SETTINGS_ID]: {
837+
[KEYWORD_ACTIVIATION_SETTING_ID]: {
840838
'type': 'string',
841839
'enum': [
842840
KeywordActivationContribution.SETTINGS_VALUE.OFF,
@@ -854,7 +852,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
854852
],
855853
'description': localize('voice.keywordActivation', "Controls whether the keyword phrase 'Hey Code' is recognized to start a voice chat session. Enabling this will start recording from the microphone but the audio is processed locally and never sent to a server."),
856854
'default': 'off',
857-
'tags': ['accessibility', 'FeatureInsight']
855+
'tags': ['accessibility']
858856
}
859857
}
860858
});
@@ -905,7 +903,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
905903
}
906904

907905
private getKeywordCommand(): string {
908-
const setting = this.configurationService.getValue(KeywordActivationContribution.SETTINGS_ID);
906+
const setting = this.configurationService.getValue(KEYWORD_ACTIVIATION_SETTING_ID);
909907
switch (setting) {
910908
case KeywordActivationContribution.SETTINGS_VALUE.INLINE_CHAT:
911909
return InlineVoiceChatAction.ID;
@@ -949,7 +947,7 @@ class KeywordActivationStatusEntry extends Disposable {
949947
) {
950948
super();
951949

952-
CommandsRegistry.registerCommand(KeywordActivationStatusEntry.STATUS_COMMAND, () => this.commandService.executeCommand('workbench.action.openSettings', KeywordActivationContribution.SETTINGS_ID));
950+
CommandsRegistry.registerCommand(KeywordActivationStatusEntry.STATUS_COMMAND, () => this.commandService.executeCommand('workbench.action.openSettings', KEYWORD_ACTIVIATION_SETTING_ID));
953951

954952
this.registerListeners();
955953
this.updateStatusEntry();
@@ -959,7 +957,7 @@ class KeywordActivationStatusEntry extends Disposable {
959957
this._register(this.speechService.onDidStartKeywordRecognition(() => this.updateStatusEntry()));
960958
this._register(this.speechService.onDidEndKeywordRecognition(() => this.updateStatusEntry()));
961959
this._register(this.configurationService.onDidChangeConfiguration(e => {
962-
if (e.affectsConfiguration(KeywordActivationContribution.SETTINGS_ID)) {
960+
if (e.affectsConfiguration(KEYWORD_ACTIVIATION_SETTING_ID)) {
963961
this.updateStatusEntry();
964962
}
965963
}));

src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
146146
description: localize('extensions.autoUpdate', "Controls the automatic update behavior of extensions. The updates are fetched from a Microsoft online service."),
147147
default: true,
148148
scope: ConfigurationScope.APPLICATION,
149-
tags: ['usesOnlineServices', 'FeatureInsight']
149+
tags: ['usesOnlineServices']
150150
},
151151
'extensions.autoCheckUpdates': {
152152
type: 'boolean',

src/vs/workbench/contrib/files/browser/files.contribution.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,7 @@ configurationRegistry.registerConfiguration({
251251
],
252252
'default': isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF,
253253
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSave' }, "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE, AutoSaveConfiguration.AFTER_DELAY),
254-
scope: ConfigurationScope.LANGUAGE_OVERRIDABLE,
255-
tags: ['FeatureInsight']
254+
scope: ConfigurationScope.LANGUAGE_OVERRIDABLE
256255
},
257256
'files.autoSaveDelay': {
258257
'type': 'number',

src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts

Lines changed: 181 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,23 @@ import { language } from 'vs/base/common/platform';
1616
import { Disposable } from 'vs/base/common/lifecycle';
1717
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
1818
import { TelemetryTrustedValue } from 'vs/platform/telemetry/common/telemetryUtils';
19-
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
19+
import { ConfigurationTarget, ConfigurationTargetToString, IConfigurationService } from 'vs/platform/configuration/common/configuration';
2020
import { ITextFileService, ITextFileSaveEvent, ITextFileResolveEvent } from 'vs/workbench/services/textfile/common/textfiles';
2121
import { extname, basename, isEqual, isEqualOrParent } from 'vs/base/common/resources';
2222
import { URI } from 'vs/base/common/uri';
23+
import { Event } from 'vs/base/common/event';
2324
import { Schemas } from 'vs/base/common/network';
2425
import { getMimeTypes } from 'vs/editor/common/services/languagesAssociations';
2526
import { hash } from 'vs/base/common/hash';
2627
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
2728
import { ViewContainerLocation } from 'vs/workbench/common/views';
2829
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
2930
import { mainWindow } from 'vs/base/browser/window';
31+
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
32+
import { isBoolean, isNumber, isString } from 'vs/base/common/types';
33+
import { LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
34+
import { AutoUpdateConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions';
35+
import { KEYWORD_ACTIVIATION_SETTING_ID } from 'vs/workbench/contrib/chat/common/chatService';
3036

3137
type TelemetryData = {
3238
mimeType: TelemetryTrustedValue<string>;
@@ -58,7 +64,6 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr
5864
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
5965
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
6066
@IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService,
61-
@IConfigurationService configurationService: IConfigurationService,
6267
@IPaneCompositePartService paneCompositeService: IPaneCompositePartService,
6368
@ITextFileService textFileService: ITextFileService
6469
) {
@@ -229,4 +234,177 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr
229234
}
230235
}
231236

232-
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TelemetryContribution, LifecyclePhase.Restored);
237+
class ConfigurationTelemetryContribution extends Disposable implements IWorkbenchContribution {
238+
239+
private readonly configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
240+
241+
constructor(
242+
@IConfigurationService private readonly configurationService: IConfigurationService,
243+
@ITelemetryService private readonly telemetryService: ITelemetryService,
244+
) {
245+
super();
246+
247+
// Debounce the event by 1000 ms and merge all affected keys into one event
248+
const debouncedConfigService = Event.debounce(configurationService.onDidChangeConfiguration, (last, cur) => {
249+
const newAffectedKeys: ReadonlySet<string> = last ? new Set([...last.affectedKeys, ...cur.affectedKeys]) : cur.affectedKeys;
250+
return { ...cur, affectedKeys: newAffectedKeys };
251+
}, 1000, true);
252+
253+
debouncedConfigService(event => {
254+
if (event.source !== ConfigurationTarget.DEFAULT) {
255+
type UpdateConfigurationClassification = {
256+
owner: 'sandy081';
257+
comment: 'Event which fires when user updates settings';
258+
configurationSource: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration file was updated i.e user or workspace' };
259+
configurationKeys: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration keys were updated' };
260+
};
261+
type UpdateConfigurationEvent = {
262+
configurationSource: string;
263+
configurationKeys: string[];
264+
};
265+
telemetryService.publicLog2<UpdateConfigurationEvent, UpdateConfigurationClassification>('updateConfiguration', {
266+
configurationSource: ConfigurationTargetToString(event.source),
267+
configurationKeys: Array.from(event.affectedKeys)
268+
});
269+
}
270+
});
271+
272+
const { user, workspace } = configurationService.keys();
273+
for (const setting of user) {
274+
this.reportTelemetry(setting, ConfigurationTarget.USER_LOCAL);
275+
}
276+
for (const setting of workspace) {
277+
this.reportTelemetry(setting, ConfigurationTarget.WORKSPACE);
278+
}
279+
}
280+
281+
/**
282+
* Report value of a setting only if it is an enum, boolean, or number or an array of those.
283+
*/
284+
private getValueToReport(key: string, target: ConfigurationTarget.USER_LOCAL | ConfigurationTarget.WORKSPACE): any {
285+
const schema = this.configurationRegistry.getConfigurationProperties()[key];
286+
const inpsectData = this.configurationService.inspect(key);
287+
const value = target === ConfigurationTarget.USER_LOCAL ? inpsectData.user?.value : inpsectData.workspace?.value;
288+
if (isNumber(value) || isBoolean(value)) {
289+
return value;
290+
}
291+
if (isString(value)) {
292+
if (schema?.enum?.includes(value)) {
293+
return value;
294+
}
295+
return undefined;
296+
}
297+
if (Array.isArray(value)) {
298+
if (value.every(v => isNumber(v) || isBoolean(v) || (isString(v) && schema?.enum?.includes(v)))) {
299+
return value;
300+
}
301+
}
302+
return undefined;
303+
}
304+
305+
private reportTelemetry(key: string, target: ConfigurationTarget.USER_LOCAL | ConfigurationTarget.WORKSPACE): void {
306+
type UpdatedSettingEvent = {
307+
value: any;
308+
source: string;
309+
};
310+
const source = ConfigurationTargetToString(target);
311+
312+
switch (key) {
313+
314+
case LayoutSettings.ACTIVITY_BAR_LOCATION:
315+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
316+
owner: 'sandy081';
317+
comment: 'This is used to know where activity bar is shown in the workbench.';
318+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
319+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
320+
}>('workbench.activityBar.location', { value: this.getValueToReport(key, target), source });
321+
return;
322+
323+
case AutoUpdateConfigurationKey:
324+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
325+
owner: 'sandy081';
326+
comment: 'This is used to know if extensions are getting auto updated or not';
327+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
328+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
329+
}>('extensions.autoUpdate', { value: this.getValueToReport(key, target), source });
330+
return;
331+
332+
case 'files.autoSave':
333+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
334+
owner: 'isidorn';
335+
comment: 'This is used to know if auto save is enabled or not';
336+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
337+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
338+
}>('files.autoSave', { value: this.getValueToReport(key, target), source });
339+
return;
340+
341+
case 'editor.stickyScroll.enabled':
342+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
343+
owner: 'aiday-mar';
344+
comment: 'This is used to know if editor sticky scroll is enabled or not';
345+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
346+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
347+
}>('editor.stickyScroll.enabled', { value: this.getValueToReport(key, target), source });
348+
return;
349+
350+
case KEYWORD_ACTIVIATION_SETTING_ID:
351+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
352+
owner: 'bpasero';
353+
comment: 'This is used to know if voice keyword activation is enabled or not';
354+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
355+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
356+
}>('accessibility.voice.keywordActivation', { value: this.getValueToReport(key, target), source });
357+
return;
358+
359+
case 'window.zoomLevel':
360+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
361+
owner: 'bpasero';
362+
comment: 'This is used to know if window zoom level is configured or not';
363+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
364+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
365+
}>('window.zoomLevel', { value: this.getValueToReport(key, target), source });
366+
return;
367+
368+
case 'window.zoomPerWindow':
369+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
370+
owner: 'bpasero';
371+
comment: 'This is used to know if window zoom per window is configured or not';
372+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
373+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
374+
}>('window.zoomPerWindow', { value: this.getValueToReport(key, target), source });
375+
return;
376+
377+
case 'window.titleBarStyle':
378+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
379+
owner: 'benibenj';
380+
comment: 'This is used to know if window title bar style is set to custom or not';
381+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
382+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
383+
}>('window.titleBarStyle', { value: this.getValueToReport(key, target), source });
384+
return;
385+
386+
case 'window.customTitleBarVisibility':
387+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
388+
owner: 'benibenj';
389+
comment: 'This is used to know if window custom title bar visibility is configured or not';
390+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
391+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
392+
}>('window.customTitleBarVisibility', { value: this.getValueToReport(key, target), source });
393+
return;
394+
395+
case 'window.nativeTabs':
396+
this.telemetryService.publicLog2<UpdatedSettingEvent, {
397+
owner: 'benibenj';
398+
comment: 'This is used to know if window native tabs are enabled or not';
399+
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
400+
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
401+
}>('window.nativeTabs', { value: this.getValueToReport(key, target), source });
402+
return;
403+
}
404+
}
405+
406+
}
407+
408+
const workbenchContributionRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
409+
workbenchContributionRegistry.registerWorkbenchContribution(TelemetryContribution, LifecyclePhase.Restored);
410+
workbenchContributionRegistry.registerWorkbenchContribution(ConfigurationTelemetryContribution, LifecyclePhase.Eventually);

0 commit comments

Comments
 (0)