Skip to content

Commit 25ee562

Browse files
authored
Add cli override to control startupExp group (microsoft#253155)
* Add startup experiment group support to environment services * refactor: streamline startup experiment group handling and remove unused code * feat: add first session date check to initialize experiments
1 parent 4bfa684 commit 25ee562

File tree

6 files changed

+50
-9
lines changed

6 files changed

+50
-9
lines changed

src/vs/platform/environment/common/argv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export interface NativeParsedArgs {
138138
'unresponsive-sample-period'?: string;
139139
'enable-rdp-display-tracking'?: boolean;
140140
'disable-layout-restore'?: boolean;
141+
'startup-experiment-group'?: string;
141142

142143
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
143144
'no-proxy-server'?: boolean;

src/vs/platform/environment/node/argv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
200200
'unresponsive-sample-period': { type: 'string' },
201201
'enable-rdp-display-tracking': { type: 'boolean' },
202202
'disable-layout-restore': { type: 'boolean' },
203+
'startup-experiment-group': { type: 'string', cat: 't', args: 'control|maximizedChat|splitEmptyEditorChat|splitWelcomeChat', description: localize('startupExperimentGroup', "Override the startup experiment group.") },
203204

204205
// chromium flags
205206
'no-proxy-server': { type: 'boolean' },

src/vs/workbench/services/coreExperimentation/common/coreExperimentationService.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { IStorageService, StorageScope, StorageTarget } from '../../../../platfo
1010
import { firstSessionDateStorageKey, ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
1111
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
1212
import { IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
13+
import { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';
1314

1415
export const ICoreExperimentationService = createDecorator<ICoreExperimentationService>('coreExperimentationService');
1516
export const startupExpContext = new RawContextKey<string>('coreExperimentation.startupExpGroup', '');
@@ -83,7 +84,8 @@ export class CoreExperimentationService extends Disposable implements ICoreExper
8384
@IStorageService private readonly storageService: IStorageService,
8485
@ITelemetryService private readonly telemetryService: ITelemetryService,
8586
@IProductService private readonly productService: IProductService,
86-
@IContextKeyService private readonly contextKeyService: IContextKeyService
87+
@IContextKeyService private readonly contextKeyService: IContextKeyService,
88+
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
8789
) {
8890
super();
8991
this.initializeExperiments();
@@ -141,6 +143,22 @@ export class CoreExperimentationService extends Disposable implements ICoreExper
141143
}
142144

143145
private createStartupExperiment(experimentName: string, experimentConfig: ExperimentConfiguration): IExperiment | undefined {
146+
const startupExpGroupOverride = this.environmentService.startupExperimentGroup;
147+
if (startupExpGroupOverride) {
148+
// If the user has an override, we use that directly
149+
const group = experimentConfig.groups.find(g => g.name === startupExpGroupOverride);
150+
if (group) {
151+
return {
152+
cohort: 1,
153+
subCohort: 1,
154+
experimentGroup: group.name,
155+
iteration: group.iteration,
156+
isInExperiment: true
157+
};
158+
}
159+
return undefined;
160+
}
161+
144162
const cohort = Math.random();
145163

146164
if (cohort >= experimentConfig.targetPercentage / 100) {

src/vs/workbench/services/coreExperimentation/test/browser/coreExperimentationService.test.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { firstSessionDateStorageKey, ITelemetryService, ITelemetryData, Telemetr
1111
import { StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
1212
import { TestStorageService } from '../../../../test/common/workbenchTestServices.js';
1313
import { IProductService } from '../../../../../platform/product/common/productService.js';
14+
import { IWorkbenchEnvironmentService } from '../../../environment/common/environmentService.js';
1415

1516
interface ITelemetryEvent {
1617
eventName: string;
@@ -72,12 +73,14 @@ suite('CoreExperimentationService', () => {
7273
let telemetryService: MockTelemetryService;
7374
let productService: MockProductService;
7475
let contextKeyService: MockContextKeyService;
76+
let environmentService: IWorkbenchEnvironmentService;
7577

7678
setup(() => {
7779
storageService = disposables.add(new TestStorageService());
7880
telemetryService = new MockTelemetryService();
7981
productService = new MockProductService();
8082
contextKeyService = new MockContextKeyService();
83+
environmentService = {} as IWorkbenchEnvironmentService;
8184
});
8285

8386
test('should return experiment from storage if it exists', () => {
@@ -97,7 +100,8 @@ suite('CoreExperimentationService', () => {
97100
storageService,
98101
telemetryService,
99102
productService,
100-
contextKeyService
103+
contextKeyService,
104+
environmentService
101105
));
102106

103107
// Should not return experiment again
@@ -120,7 +124,8 @@ suite('CoreExperimentationService', () => {
120124
storageService,
121125
telemetryService,
122126
productService,
123-
contextKeyService
127+
contextKeyService,
128+
environmentService
124129
));
125130

126131
// Should create experiment
@@ -154,7 +159,8 @@ suite('CoreExperimentationService', () => {
154159
storageService,
155160
telemetryService,
156161
productService,
157-
contextKeyService
162+
contextKeyService,
163+
environmentService
158164
));
159165

160166
const experiment = service.getExperiment();
@@ -191,7 +197,8 @@ suite('CoreExperimentationService', () => {
191197
storageService,
192198
telemetryService,
193199
productService,
194-
contextKeyService
200+
contextKeyService,
201+
environmentService
195202
));
196203

197204
// Should not create experiment
@@ -229,7 +236,8 @@ suite('CoreExperimentationService', () => {
229236
storageService,
230237
telemetryService,
231238
productService,
232-
contextKeyService
239+
contextKeyService,
240+
environmentService
233241
));
234242

235243
const experiment = service.getExperiment();
@@ -254,7 +262,8 @@ suite('CoreExperimentationService', () => {
254262
storageService,
255263
telemetryService,
256264
productService,
257-
contextKeyService
265+
contextKeyService,
266+
environmentService
258267
));
259268

260269
const experiment = service.getExperiment();
@@ -285,7 +294,8 @@ suite('CoreExperimentationService', () => {
285294
storageService,
286295
telemetryService,
287296
productService,
288-
contextKeyService
297+
contextKeyService,
298+
environmentService
289299
));
290300

291301
const experiment = service.getExperiment();
@@ -309,7 +319,8 @@ suite('CoreExperimentationService', () => {
309319
storageService,
310320
telemetryService,
311321
productService,
312-
contextKeyService
322+
contextKeyService,
323+
environmentService
313324
));
314325

315326
const experiment = service.getExperiment();

src/vs/workbench/services/environment/common/environmentService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService {
3636
readonly skipWelcome: boolean;
3737
readonly disableWorkspaceTrust: boolean;
3838
readonly webviewExternalEndpoint: string;
39+
readonly startupExperimentGroup?: string;
3940

4041
// --- Development
4142
readonly debugRenderer: boolean;

src/vs/workbench/services/environment/electron-browser/environmentService.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ export class NativeWorkbenchEnvironmentService extends AbstractNativeEnvironment
147147
@memoize
148148
get filesToWait(): IPathsToWaitFor | undefined { return this.configuration.filesToWait; }
149149

150+
@memoize
151+
get startupExperimentGroup(): string | undefined {
152+
const group = this.args['startup-experiment-group'];
153+
if (typeof group === 'string') {
154+
return group;
155+
}
156+
return undefined;
157+
}
158+
150159
constructor(
151160
private readonly configuration: INativeWindowConfiguration,
152161
productService: IProductService

0 commit comments

Comments
 (0)