remove FeatureInsight tag (#203295)

- remove FeatureInsight tag
- report event per setting with owner and purpose information
- adopt the opted in settings
This commit is contained in:
Sandeep Somavarapu 2024-01-24 10:32:12 +01:00 committed by GitHub
parent 3b82957586
commit b27e28197e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 198 additions and 117 deletions

View file

@ -2818,7 +2818,7 @@ class EditorStickyScroll extends BaseEditorOption<EditorOption.stickyScroll, IEd
type: 'boolean',
default: defaults.enabled,
description: nls.localize('editor.stickyScroll.enabled', "Shows the nested current scopes during the scroll at the top of the editor."),
tags: ['experimental', 'FeatureInsight']
tags: ['experimental']
},
'editor.stickyScroll.maxLineCount': {
type: 'number',

View file

@ -505,7 +505,6 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
localize('workbench.activityBar.location.top', "Show the Activity Bar on top of the Primary Side Bar."),
localize('workbench.activityBar.location.hide', "Hide the Activity Bar.")
],
tags: ['FeatureInsight']
},
'workbench.activityBar.iconClickBehavior': {
'type': 'string',

View file

@ -313,3 +313,5 @@ export interface IChatService {
transferChatSession(transferredSessionData: IChatTransferredSessionData, toWorkspace: URI): void;
}
export const KEYWORD_ACTIVIATION_SETTING_ID = 'accessibility.voice.keywordActivation';

View file

@ -17,7 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { spinningLoading } from 'vs/platform/theme/common/iconRegistry';
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
import { IChatWidget, IChatWidgetService, IQuickChatService } from 'vs/workbench/contrib/chat/browser/chat';
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
import { IChatService, KEYWORD_ACTIVIATION_SETTING_ID } from 'vs/workbench/contrib/chat/common/chatService';
import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, MENU_INLINE_CHAT_INPUT } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
import { CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController';
@ -771,15 +771,13 @@ function supportsKeywordActivation(configurationService: IConfigurationService,
return false;
}
const value = configurationService.getValue(KeywordActivationContribution.SETTINGS_ID);
const value = configurationService.getValue(KEYWORD_ACTIVIATION_SETTING_ID);
return typeof value === 'string' && value !== KeywordActivationContribution.SETTINGS_VALUE.OFF;
}
export class KeywordActivationContribution extends Disposable implements IWorkbenchContribution {
static SETTINGS_ID = 'accessibility.voice.keywordActivation';
static SETTINGS_VALUE = {
OFF: 'off',
INLINE_CHAT: 'inlineChat',
@ -817,7 +815,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
this._register(this.speechService.onDidEndSpeechToTextSession(() => this.handleKeywordActivation()));
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(KeywordActivationContribution.SETTINGS_ID)) {
if (e.affectsConfiguration(KEYWORD_ACTIVIATION_SETTING_ID)) {
this.handleKeywordActivation();
}
}));
@ -836,7 +834,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
registry.registerConfiguration({
...accessibilityConfigurationNodeBase,
properties: {
[KeywordActivationContribution.SETTINGS_ID]: {
[KEYWORD_ACTIVIATION_SETTING_ID]: {
'type': 'string',
'enum': [
KeywordActivationContribution.SETTINGS_VALUE.OFF,
@ -854,7 +852,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
],
'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."),
'default': 'off',
'tags': ['accessibility', 'FeatureInsight']
'tags': ['accessibility']
}
}
});
@ -905,7 +903,7 @@ export class KeywordActivationContribution extends Disposable implements IWorkbe
}
private getKeywordCommand(): string {
const setting = this.configurationService.getValue(KeywordActivationContribution.SETTINGS_ID);
const setting = this.configurationService.getValue(KEYWORD_ACTIVIATION_SETTING_ID);
switch (setting) {
case KeywordActivationContribution.SETTINGS_VALUE.INLINE_CHAT:
return InlineVoiceChatAction.ID;
@ -949,7 +947,7 @@ class KeywordActivationStatusEntry extends Disposable {
) {
super();
CommandsRegistry.registerCommand(KeywordActivationStatusEntry.STATUS_COMMAND, () => this.commandService.executeCommand('workbench.action.openSettings', KeywordActivationContribution.SETTINGS_ID));
CommandsRegistry.registerCommand(KeywordActivationStatusEntry.STATUS_COMMAND, () => this.commandService.executeCommand('workbench.action.openSettings', KEYWORD_ACTIVIATION_SETTING_ID));
this.registerListeners();
this.updateStatusEntry();
@ -959,7 +957,7 @@ class KeywordActivationStatusEntry extends Disposable {
this._register(this.speechService.onDidStartKeywordRecognition(() => this.updateStatusEntry()));
this._register(this.speechService.onDidEndKeywordRecognition(() => this.updateStatusEntry()));
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(KeywordActivationContribution.SETTINGS_ID)) {
if (e.affectsConfiguration(KEYWORD_ACTIVIATION_SETTING_ID)) {
this.updateStatusEntry();
}
}));

View file

@ -146,7 +146,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
description: localize('extensions.autoUpdate', "Controls the automatic update behavior of extensions. The updates are fetched from a Microsoft online service."),
default: true,
scope: ConfigurationScope.APPLICATION,
tags: ['usesOnlineServices', 'FeatureInsight']
tags: ['usesOnlineServices']
},
'extensions.autoCheckUpdates': {
type: 'boolean',

View file

@ -251,8 +251,7 @@ configurationRegistry.registerConfiguration({
],
'default': isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF,
'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),
scope: ConfigurationScope.LANGUAGE_OVERRIDABLE,
tags: ['FeatureInsight']
scope: ConfigurationScope.LANGUAGE_OVERRIDABLE
},
'files.autoSaveDelay': {
'type': 'number',

View file

@ -16,10 +16,11 @@ import { language } from 'vs/base/common/platform';
import { Disposable } from 'vs/base/common/lifecycle';
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
import { TelemetryTrustedValue } from 'vs/platform/telemetry/common/telemetryUtils';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ConfigurationTarget, ConfigurationTargetToString, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITextFileService, ITextFileSaveEvent, ITextFileResolveEvent } from 'vs/workbench/services/textfile/common/textfiles';
import { extname, basename, isEqual, isEqualOrParent } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
import { Schemas } from 'vs/base/common/network';
import { getMimeTypes } from 'vs/editor/common/services/languagesAssociations';
import { hash } from 'vs/base/common/hash';
@ -27,6 +28,11 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b
import { ViewContainerLocation } from 'vs/workbench/common/views';
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { mainWindow } from 'vs/base/browser/window';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { isBoolean, isNumber, isString } from 'vs/base/common/types';
import { LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
import { AutoUpdateConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions';
import { KEYWORD_ACTIVIATION_SETTING_ID } from 'vs/workbench/contrib/chat/common/chatService';
type TelemetryData = {
mimeType: TelemetryTrustedValue<string>;
@ -58,7 +64,6 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService,
@IConfigurationService configurationService: IConfigurationService,
@IPaneCompositePartService paneCompositeService: IPaneCompositePartService,
@ITextFileService textFileService: ITextFileService
) {
@ -229,4 +234,177 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr
}
}
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TelemetryContribution, LifecyclePhase.Restored);
class ConfigurationTelemetryContribution extends Disposable implements IWorkbenchContribution {
private readonly configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
) {
super();
// Debounce the event by 1000 ms and merge all affected keys into one event
const debouncedConfigService = Event.debounce(configurationService.onDidChangeConfiguration, (last, cur) => {
const newAffectedKeys: ReadonlySet<string> = last ? new Set([...last.affectedKeys, ...cur.affectedKeys]) : cur.affectedKeys;
return { ...cur, affectedKeys: newAffectedKeys };
}, 1000, true);
debouncedConfigService(event => {
if (event.source !== ConfigurationTarget.DEFAULT) {
type UpdateConfigurationClassification = {
owner: 'sandy081';
comment: 'Event which fires when user updates settings';
configurationSource: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration file was updated i.e user or workspace' };
configurationKeys: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration keys were updated' };
};
type UpdateConfigurationEvent = {
configurationSource: string;
configurationKeys: string[];
};
telemetryService.publicLog2<UpdateConfigurationEvent, UpdateConfigurationClassification>('updateConfiguration', {
configurationSource: ConfigurationTargetToString(event.source),
configurationKeys: Array.from(event.affectedKeys)
});
}
});
const { user, workspace } = configurationService.keys();
for (const setting of user) {
this.reportTelemetry(setting, ConfigurationTarget.USER_LOCAL);
}
for (const setting of workspace) {
this.reportTelemetry(setting, ConfigurationTarget.WORKSPACE);
}
}
/**
* Report value of a setting only if it is an enum, boolean, or number or an array of those.
*/
private getValueToReport(key: string, target: ConfigurationTarget.USER_LOCAL | ConfigurationTarget.WORKSPACE): any {
const schema = this.configurationRegistry.getConfigurationProperties()[key];
const inpsectData = this.configurationService.inspect(key);
const value = target === ConfigurationTarget.USER_LOCAL ? inpsectData.user?.value : inpsectData.workspace?.value;
if (isNumber(value) || isBoolean(value)) {
return value;
}
if (isString(value)) {
if (schema?.enum?.includes(value)) {
return value;
}
return undefined;
}
if (Array.isArray(value)) {
if (value.every(v => isNumber(v) || isBoolean(v) || (isString(v) && schema?.enum?.includes(v)))) {
return value;
}
}
return undefined;
}
private reportTelemetry(key: string, target: ConfigurationTarget.USER_LOCAL | ConfigurationTarget.WORKSPACE): void {
type UpdatedSettingEvent = {
value: any;
source: string;
};
const source = ConfigurationTargetToString(target);
switch (key) {
case LayoutSettings.ACTIVITY_BAR_LOCATION:
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'sandy081';
comment: 'This is used to know where activity bar is shown in the workbench.';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('workbench.activityBar.location', { value: this.getValueToReport(key, target), source });
return;
case AutoUpdateConfigurationKey:
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'sandy081';
comment: 'This is used to know if extensions are getting auto updated or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('extensions.autoUpdate', { value: this.getValueToReport(key, target), source });
return;
case 'files.autoSave':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'isidorn';
comment: 'This is used to know if auto save is enabled or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('files.autoSave', { value: this.getValueToReport(key, target), source });
return;
case 'editor.stickyScroll.enabled':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'aiday-mar';
comment: 'This is used to know if editor sticky scroll is enabled or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('editor.stickyScroll.enabled', { value: this.getValueToReport(key, target), source });
return;
case KEYWORD_ACTIVIATION_SETTING_ID:
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'bpasero';
comment: 'This is used to know if voice keyword activation is enabled or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('accessibility.voice.keywordActivation', { value: this.getValueToReport(key, target), source });
return;
case 'window.zoomLevel':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'bpasero';
comment: 'This is used to know if window zoom level is configured or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('window.zoomLevel', { value: this.getValueToReport(key, target), source });
return;
case 'window.zoomPerWindow':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'bpasero';
comment: 'This is used to know if window zoom per window is configured or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('window.zoomPerWindow', { value: this.getValueToReport(key, target), source });
return;
case 'window.titleBarStyle':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'benibenj';
comment: 'This is used to know if window title bar style is set to custom or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('window.titleBarStyle', { value: this.getValueToReport(key, target), source });
return;
case 'window.customTitleBarVisibility':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'benibenj';
comment: 'This is used to know if window custom title bar visibility is configured or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('window.customTitleBarVisibility', { value: this.getValueToReport(key, target), source });
return;
case 'window.nativeTabs':
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'benibenj';
comment: 'This is used to know if window native tabs are enabled or not';
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
}>('window.nativeTabs', { value: this.getValueToReport(key, target), source });
return;
}
}
}
const workbenchContributionRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionRegistry.registerWorkbenchContribution(TelemetryContribution, LifecyclePhase.Restored);
workbenchContributionRegistry.registerWorkbenchContribution(ConfigurationTelemetryContribution, LifecyclePhase.Eventually);

View file

@ -195,13 +195,13 @@ import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from 'vs/platform/window/electron-sand
'maximum': MAX_ZOOM_LEVEL,
'markdownDescription': localize({ comment: ['{0} will be a setting name rendered as a link'], key: 'zoomLevel' }, "Adjust the default zoom level for all windows. Each increment above `0` (e.g. `1`) or below (e.g. `-1`) represents zooming `20%` larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity. See {0} for configuring if the 'Zoom In' and 'Zoom Out' commands apply the zoom level to all windows or only the active window.", '`#window.zoomPerWindow#`'),
ignoreSync: true,
tags: ['accessibility', 'FeatureInsight']
tags: ['accessibility']
},
'window.zoomPerWindow': {
'type': 'boolean',
'default': true,
'markdownDescription': localize({ comment: ['{0} will be a setting name rendered as a link'], key: 'zoomPerWindow' }, "Controls if the 'Zoom In' and 'Zoom Out' commands apply the zoom level to all windows or only the active window. See {0} for configuring a default zoom level for all windows.", '`#window.zoomLevel#`'),
tags: ['accessibility', 'FeatureInsight']
tags: ['accessibility']
},
'window.newWindowDimensions': {
'type': 'string',
@ -234,7 +234,6 @@ import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from 'vs/platform/window/electron-sand
'default': isLinux ? 'native' : 'custom',
'scope': ConfigurationScope.APPLICATION,
'description': localize('titleBarStyle', "Adjust the appearance of the window title bar to be native by the OS or custom. On Linux and Windows, this setting also affects the application and context menu appearances. Changes require a full restart to apply."),
tags: ['FeatureInsight']
},
'window.customTitleBarVisibility': {
'type': 'string',
@ -247,7 +246,6 @@ import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from 'vs/platform/window/electron-sand
'default': isLinux ? 'never' : 'auto',
'scope': ConfigurationScope.APPLICATION,
'description': localize('window.customTitleBarVisibility', "Adjust when the custom title bar should be shown."),
tags: ['FeatureInsight']
},
'window.dialogStyle': {
'type': 'string',
@ -262,7 +260,6 @@ import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from 'vs/platform/window/electron-sand
'scope': ConfigurationScope.APPLICATION,
'description': localize('window.nativeTabs', "Enables macOS Sierra window tabs. Note that changes require a full restart to apply and that native tabs will disable a custom title bar style if configured."),
'included': isMacintosh,
tags: ['FeatureInsight']
},
'window.nativeFullScreen': {
'type': 'boolean',

View file

@ -17,7 +17,7 @@ import { IPolicyConfiguration, NullPolicyConfiguration, PolicyConfiguration } fr
import { Configuration } from 'vs/workbench/services/configuration/common/configurationModels';
import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId, IConfigurationCache, machineSettingsSchemaId, LOCAL_MACHINE_SCOPES, IWorkbenchConfigurationService, RestrictedSettings, PROFILE_SCOPES, LOCAL_MACHINE_PROFILE_SCOPES, profileSettingsSchemaId, APPLY_ALL_PROFILES_SETTING } from 'vs/workbench/services/configuration/common/configuration';
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings, machineSettings, machineOverridableSettings, ConfigurationScope, IConfigurationPropertySchema, keyFromOverrideIdentifiers, OVERRIDE_PROPERTY_PATTERN, resourceLanguageSettingsSchemaId, configurationDefaultsSchemaId, IRegisteredConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings, machineSettings, machineOverridableSettings, ConfigurationScope, IConfigurationPropertySchema, keyFromOverrideIdentifiers, OVERRIDE_PROPERTY_PATTERN, resourceLanguageSettingsSchemaId, configurationDefaultsSchemaId } from 'vs/platform/configuration/common/configurationRegistry';
import { IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, getStoredWorkspaceFolder, toWorkspaceFolders } from 'vs/platform/workspaces/common/workspaces';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ConfigurationEditing, EditableConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
@ -37,7 +37,7 @@ import { delta, distinct, equals as arrayEquals } from 'vs/base/common/arrays';
import { IStringDictionary } from 'vs/base/common/collections';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkbenchAssignmentService } from 'vs/workbench/services/assignment/common/assignmentService';
import { isBoolean, isNumber, isString, isUndefined } from 'vs/base/common/types';
import { isUndefined } from 'vs/base/common/types';
import { localize } from 'vs/nls';
import { DidChangeUserDataProfileEvent, IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { IPolicyService, NullPolicyService } from 'vs/platform/policy/common/policy';
@ -47,7 +47,6 @@ import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/envir
import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration';
import { mainWindow } from 'vs/base/browser/window';
import { runWhenWindowIdle } from 'vs/base/browser/dom';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
function getLocalUserConfigurationScopes(userDataProfile: IUserDataProfile, hasRemote: boolean): ConfigurationScope[] | undefined {
return (userDataProfile.isDefault || userDataProfile.useDefaultFlags?.settings)
@ -1325,96 +1324,6 @@ class ResetConfigurationDefaultsOverridesCache extends Disposable implements IWo
}
}
class ConfigurationTelemetryContribution extends Disposable implements IWorkbenchContribution {
private readonly configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
constructor(
@IConfigurationService private readonly configurationService: WorkspaceService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
) {
super();
// Debounce the event by 1000 ms and merge all affected keys into one event
const debouncedConfigService = Event.debounce(configurationService.onDidChangeConfiguration, (last, cur) => {
const newAffectedKeys: ReadonlySet<string> = last ? new Set([...last.affectedKeys, ...cur.affectedKeys]) : cur.affectedKeys;
return { ...cur, affectedKeys: newAffectedKeys };
}, 1000, true);
debouncedConfigService(event => {
if (event.source !== ConfigurationTarget.DEFAULT) {
type UpdateConfigurationClassification = {
owner: 'sandy081';
comment: 'Event which fires when user updates settings';
configurationSource: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration file was updated i.e user or workspace' };
configurationKeys: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration keys were updated' };
};
type UpdateConfigurationEvent = {
configurationSource: string;
configurationKeys: string[];
};
telemetryService.publicLog2<UpdateConfigurationEvent, UpdateConfigurationClassification>('updateConfiguration', {
configurationSource: ConfigurationTargetToString(event.source),
configurationKeys: Array.from(event.affectedKeys)
});
}
});
type UpdatedSettingClassification = {
owner: 'sandy081';
comment: 'Event reporting the updated setting';
setting: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'name of the setting' };
value: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'value of the setting' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' };
};
type UpdatedSettingEvent = {
setting: string;
value: string;
source: string;
};
const { user, workspace } = configurationService.keys();
const userSource = ConfigurationTargetToString(ConfigurationTarget.USER_LOCAL);
for (const setting of user) {
const schema = this.configurationRegistry.getConfigurationProperties()[setting];
if (schema?.tags?.includes('FeatureInsight')) {
const value = this.getValueToReport(setting, ConfigurationTarget.USER_LOCAL, schema);
this.telemetryService.publicLog2<UpdatedSettingEvent, UpdatedSettingClassification>('updatedsetting', { setting, value, source: userSource });
}
}
const worskpaceSource = ConfigurationTargetToString(ConfigurationTarget.WORKSPACE);
for (const setting of workspace) {
const schema = this.configurationRegistry.getConfigurationProperties()[setting];
if (schema?.tags?.includes('FeatureInsight')) {
const value = this.getValueToReport(setting, ConfigurationTarget.WORKSPACE, schema);
this.telemetryService.publicLog2<UpdatedSettingEvent, UpdatedSettingClassification>('updatedsetting', { setting, value, source: worskpaceSource });
}
}
}
/**
* Report value of a setting only if it is an enum, boolean, or number or an array of those.
*/
private getValueToReport(key: string, target: ConfigurationTarget, schema: IRegisteredConfigurationPropertySchema): any {
const configurationModel = this.configurationService.getConfigurationModel(target);
const value = configurationModel?.getValue(key);
if (isNumber(value) || isBoolean(value)) {
return value;
}
if (isString(value)) {
if (schema.enum?.includes(value)) {
return value;
}
return undefined;
}
if (Array.isArray(value)) {
if (value.every(v => isNumber(v) || isBoolean(v) || (isString(v) && schema.enum?.includes(v)))) {
return value;
}
}
return undefined;
}
}
class UpdateExperimentalSettingsDefaults extends Disposable implements IWorkbenchContribution {
private readonly processedExperimentalSettings = new Set<string>();
@ -1457,7 +1366,6 @@ const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegist
workbenchContributionsRegistry.registerWorkbenchContribution(RegisterConfigurationSchemasContribution, LifecyclePhase.Restored);
workbenchContributionsRegistry.registerWorkbenchContribution(ResetConfigurationDefaultsOverridesCache, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(UpdateExperimentalSettingsDefaults, LifecyclePhase.Ready);
workbenchContributionsRegistry.registerWorkbenchContribution(ConfigurationTelemetryContribution, LifecyclePhase.Eventually);
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
configurationRegistry.registerConfiguration({