Skip to content

Commit 6a59181

Browse files
authored
Experiments (microsoft#52848)
Infrastructure to run experiments
1 parent a474fe9 commit 6a59181

15 files changed

Lines changed: 1338 additions & 116 deletions

File tree

src/vs/platform/extensionManagement/common/extensionManagement.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,8 @@ export enum ExtensionRecommendationReason {
419419
Workspace,
420420
File,
421421
Executable,
422-
DynamicWorkspace
422+
DynamicWorkspace,
423+
Experimental
423424
}
424425

425426
export const ExtensionsLabel = localize('extensions', "Extensions");

src/vs/platform/node/product.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export interface IProductConfiguration {
2222
commit?: string;
2323
settingsSearchBuildId?: number;
2424
settingsSearchUrl?: string;
25+
experimentsUrl?: string;
2526
date: string;
2627
extensionsGallery: {
2728
serviceUrl: string;

src/vs/platform/telemetry/common/experiments.ts

Lines changed: 0 additions & 92 deletions
This file was deleted.

src/vs/workbench/electron-browser/shell.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import { ContextViewService } from 'vs/platform/contextview/browser/contextViewS
2020
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
2121
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2222
import { NullTelemetryService, configurationTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
23-
import { IExperimentService, ExperimentService } from 'vs/platform/telemetry/common/experiments';
2423
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
2524
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
2625
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
@@ -125,7 +124,6 @@ export class WorkbenchShell {
125124
private configurationService: IConfigurationService;
126125
private contextService: IWorkspaceContextService;
127126
private telemetryService: ITelemetryService;
128-
private experimentService: IExperimentService;
129127
private extensionService: ExtensionService;
130128
private broadcastService: IBroadcastService;
131129
private timerService: ITimerService;
@@ -254,7 +252,6 @@ export class WorkbenchShell {
254252
"customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
255253
"theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
256254
"language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" },
257-
"experiments": { "${inline}": [ "${IExperiments}" ] },
258255
"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
259256
"restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
260257
"restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
@@ -272,7 +269,6 @@ export class WorkbenchShell {
272269
customKeybindingsCount: info.customKeybindingsCount,
273270
theme: this.themeService.getColorTheme().id,
274271
language: platform.language,
275-
experiments: this.experimentService.getExperiments(),
276272
pinnedViewlets: info.pinnedViewlets,
277273
restoredViewlet: info.restoredViewlet,
278274
restoredEditors: info.restoredEditorsCount,
@@ -367,10 +363,6 @@ export class WorkbenchShell {
367363
// Hash
368364
serviceCollection.set(IHashService, new SyncDescriptor(HashService));
369365

370-
// Experiments
371-
this.experimentService = instantiationService.createInstance(ExperimentService);
372-
serviceCollection.set(IExperimentService, this.experimentService);
373-
374366
// Telemetry
375367
if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
376368
const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
7+
import { INotificationService, Severity, IPromptChoice } from 'vs/platform/notification/common/notification';
8+
import { IExperimentService, IExperiment, ExperimentActionType, IExperimentActionPromptProperties, ExperimentState } from 'vs/workbench/parts/experiments/node/experimentService';
9+
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
10+
import { IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions';
11+
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
12+
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
13+
14+
export class ExperimentalPrompts extends Disposable implements IWorkbenchContribution {
15+
private _disposables: IDisposable[] = [];
16+
17+
constructor(
18+
@IExperimentService private experimentService: IExperimentService,
19+
@IViewletService private viewletService: IViewletService,
20+
@INotificationService private notificationService: INotificationService,
21+
@ITelemetryService private telemetryService: ITelemetryService
22+
23+
) {
24+
super();
25+
this.experimentService.onExperimentEnabled(e => {
26+
if (e.action && e.action.type === ExperimentActionType.Prompt && e.state === ExperimentState.Run) {
27+
this.showExperimentalPrompts(e);
28+
}
29+
}, this, this._disposables);
30+
}
31+
32+
private showExperimentalPrompts(experiment: IExperiment): void {
33+
if (!experiment || !experiment.enabled || !experiment.action || experiment.state !== ExperimentState.Run) {
34+
return;
35+
}
36+
37+
const logTelemetry = (commandText?: string) => {
38+
/* __GDPR__
39+
"experimentalPrompts" : {
40+
"experimentId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
41+
"commandText": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
42+
"cancelled": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
43+
}
44+
*/
45+
this.telemetryService.publicLog('experimentalPrompts', {
46+
experimentId: experiment.id,
47+
commandText,
48+
cancelled: !commandText
49+
});
50+
};
51+
52+
const actionProperties = (<IExperimentActionPromptProperties>experiment.action.properties);
53+
if (!actionProperties || !actionProperties.promptText) {
54+
return;
55+
}
56+
if (!actionProperties.commands) {
57+
actionProperties.commands = [];
58+
}
59+
60+
const choices: IPromptChoice[] = actionProperties.commands.map(command => {
61+
return {
62+
label: command.text,
63+
run: () => {
64+
logTelemetry(command.text);
65+
if (command.externalLink) {
66+
window.open(command.externalLink);
67+
return;
68+
}
69+
if (command.curatedExtensionsKey && Array.isArray(command.curatedExtensionsList)) {
70+
this.viewletService.openViewlet('workbench.view.extensions', true)
71+
.then(viewlet => viewlet as IExtensionsViewlet)
72+
.then(viewlet => {
73+
if (viewlet) {
74+
viewlet.search('curated:' + command.curatedExtensionsKey);
75+
}
76+
});
77+
return;
78+
}
79+
80+
this.experimentService.markAsCompleted(experiment.id);
81+
82+
}
83+
};
84+
});
85+
86+
this.notificationService.prompt(Severity.Info, actionProperties.promptText, choices, logTelemetry);
87+
}
88+
89+
dispose() {
90+
this._disposables = dispose(this._disposables);
91+
}
92+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
7+
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
8+
import { IExperimentService, ExperimentService } from 'vs/workbench/parts/experiments/node/experimentService';
9+
import { Registry } from 'vs/platform/registry/common/platform';
10+
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
11+
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
12+
import { ExperimentalPrompts } from 'vs/workbench/parts/experiments/electron-browser/experimentalPrompt';
13+
14+
registerSingleton(IExperimentService, ExperimentService);
15+
16+
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExperimentalPrompts, LifecyclePhase.Eventually);

0 commit comments

Comments
 (0)