From 6f19e0b34fabec36e137064ad711f8ab972fe4f0 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Mon, 25 May 2020 08:56:33 -0700 Subject: [PATCH 01/25] Add npm package --- package-lock.json | 47 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 48 insertions(+) diff --git a/package-lock.json b/package-lock.json index 72c37630d6fb..5161977546a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5359,6 +5359,14 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, "azure-devops-node-api": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-7.2.0.tgz", @@ -10386,6 +10394,29 @@ } } }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "font-awesome": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", @@ -22123,6 +22154,14 @@ } } }, + "tas-client": { + "version": "0.0.762", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.0.762.tgz", + "integrity": "sha512-i4dcYHkk2rnmBHr8RC1IoZVHU9wQT+OmDDnUeRW/vbpjDSCqgL5Qh8KeHs3DizJgqP9MWjLK/Kmqfm8VbD6g3g==", + "requires": { + "axios": "^0.19.0" + } + }, "tcp-port-used": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.1.tgz", @@ -24729,6 +24768,14 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.1.tgz", "integrity": "sha512-tZFUSbyjUcrh+qQf13ALX4QDdOfDX0cVaBFgy7ktJ0VwS7AW/yRKgGPSxVqqP9OCMNPdqP57O5q47w2pEwfaUg==" }, + "vscode-tas-client": { + "version": "0.0.757", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.0.757.tgz", + "integrity": "sha512-IXP+vFTIE1HpvYxqm7SuFe/K5N3cPoF4TTH6uYGAeuuYxV586tjYFtK9UmF00ajzcqvLGvsPgxmfgLeX6vUUtA==", + "requires": { + "tas-client": "0.0.762" + } + }, "vscode-test": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.2.3.tgz", diff --git a/package.json b/package.json index 9501da29d5d7..eead9154c020 100644 --- a/package.json +++ b/package.json @@ -3060,6 +3060,7 @@ "vscode-languageclient": "^6.2.0-next.2", "vscode-languageserver": "^6.2.0-next.2", "vscode-languageserver-protocol": "^3.16.0-next.2", + "vscode-tas-client": "0.0.757", "vsls": "^0.3.1291", "winreg": "^1.2.4", "winston": "^3.2.1", From bf7bd56cc689fe698e866a1a695e0edb1a9c5b9d Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Mon, 25 May 2020 08:58:05 -0700 Subject: [PATCH 02/25] News entry --- news/1 Enhancements/10008.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/1 Enhancements/10008.md diff --git a/news/1 Enhancements/10008.md b/news/1 Enhancements/10008.md new file mode 100644 index 000000000000..1da59c36dc77 --- /dev/null +++ b/news/1 Enhancements/10008.md @@ -0,0 +1 @@ +Integrate VS Code experiment framework in the extension. From b5bef693c13d521be948daaf5269eeca5e12f94e Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Mon, 25 May 2020 09:22:30 -0700 Subject: [PATCH 03/25] experiments.ts -> experiments/manager.ts --- .../manager.ts} | 28 ++++++++++--------- src/client/common/serviceRegistry.ts | 2 +- .../activation/activationManager.unit.test.ts | 2 +- .../languageServer/manager.unit.test.ts | 2 +- src/test/api.functional.test.ts | 2 +- src/test/common/experiments.unit.test.ts | 2 +- src/test/common/installer.test.ts | 2 +- src/test/common/moduleInstaller.test.ts | 2 +- src/test/common/serviceRegistry.unit.test.ts | 2 +- .../datascience/dataScienceIocContainer.ts | 2 +- .../extension/adapter/factory.unit.test.ts | 2 +- .../outdatedDebuggerPrompt.unit.test.ts | 2 +- .../launchConfigExperiments.unit.test.ts | 2 +- ...rEnvironmentActivationService.unit.test.ts | 2 +- .../autoSelection/rules/settings.unit.test.ts | 2 +- .../rules/workspaceEnv.unit.test.ts | 2 +- src/test/testing/main.unit.test.ts | 2 +- 17 files changed, 31 insertions(+), 29 deletions(-) rename src/client/common/{experiments.ts => experiments/manager.ts} (95%) diff --git a/src/client/common/experiments.ts b/src/client/common/experiments/manager.ts similarity index 95% rename from src/client/common/experiments.ts rename to src/client/common/experiments/manager.ts index 0525ef115eff..a37441d209f5 100644 --- a/src/client/common/experiments.ts +++ b/src/client/common/experiments/manager.ts @@ -8,25 +8,27 @@ import { inject, injectable, named, optional } from 'inversify'; import { parse } from 'jsonc-parser'; import * as path from 'path'; -import { IConfigurationService, IHttpClient, IPythonSettings } from '../common/types'; -import { sendTelemetryEvent } from '../telemetry'; -import { EventName } from '../telemetry/constants'; -import { IApplicationEnvironment } from './application/types'; -import { EXTENSION_ROOT_DIR, STANDARD_OUTPUT_CHANNEL } from './constants'; -import { NativeNotebook } from './experimentGroups'; -import { traceDecorators, traceError } from './logger'; -import { IFileSystem } from './platform/types'; +import { sendTelemetryEvent } from '../../telemetry'; +import { EventName } from '../../telemetry/constants'; +import { IApplicationEnvironment } from '../application/types'; +import { EXTENSION_ROOT_DIR, STANDARD_OUTPUT_CHANNEL } from '../constants'; +import { NativeNotebook } from '../experimentGroups'; +import { traceDecorators, traceError } from '../logger'; +import { IFileSystem } from '../platform/types'; import { ABExperiments, + IConfigurationService, ICryptoUtils, IExperimentsManager, + IHttpClient, IOutputChannel, IPersistentState, - IPersistentStateFactory -} from './types'; -import { sleep } from './utils/async'; -import { swallowExceptions } from './utils/decorators'; -import { Experiments } from './utils/localize'; + IPersistentStateFactory, + IPythonSettings +} from '../types'; +import { sleep } from '../utils/async'; +import { swallowExceptions } from '../utils/decorators'; +import { Experiments } from '../utils/localize'; const EXPIRY_DURATION_MS = 30 * 60 * 1000; export const isDownloadedStorageValidKey = 'IS_EXPERIMENTS_STORAGE_VALID_KEY'; diff --git a/src/client/common/serviceRegistry.ts b/src/client/common/serviceRegistry.ts index ed2211de034a..87ac23f8229a 100644 --- a/src/client/common/serviceRegistry.ts +++ b/src/client/common/serviceRegistry.ts @@ -41,7 +41,7 @@ import { AsyncDisposableRegistry } from './asyncDisposableRegistry'; import { ConfigurationService } from './configuration/service'; import { CryptoUtils } from './crypto'; import { EditorUtils } from './editor'; -import { ExperimentsManager } from './experiments'; +import { ExperimentsManager } from './experiments/manager'; import { FeatureDeprecationManager } from './featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, diff --git a/src/test/activation/activationManager.unit.test.ts b/src/test/activation/activationManager.unit.test.ts index 43a14e4978c0..388d4780fde6 100644 --- a/src/test/activation/activationManager.unit.test.ts +++ b/src/test/activation/activationManager.unit.test.ts @@ -17,7 +17,7 @@ import { IActiveResourceService, IDocumentManager, IWorkspaceService } from '../ import { WorkspaceService } from '../../client/common/application/workspace'; import { PYTHON_LANGUAGE } from '../../client/common/constants'; import { DeprecatePythonPath } from '../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../client/common/experiments'; +import { ExperimentsManager } from '../../client/common/experiments/manager'; import { InterpreterPathService } from '../../client/common/interpreterPathService'; import { FileSystem } from '../../client/common/platform/fileSystem'; import { IFileSystem } from '../../client/common/platform/types'; diff --git a/src/test/activation/languageServer/manager.unit.test.ts b/src/test/activation/languageServer/manager.unit.test.ts index 143a754a2dab..4e0b359c686c 100644 --- a/src/test/activation/languageServer/manager.unit.test.ts +++ b/src/test/activation/languageServer/manager.unit.test.ts @@ -17,7 +17,7 @@ import { ILanguageServerProxy } from '../../../client/activation/types'; import { ConfigurationService } from '../../../client/common/configuration/service'; -import { ExperimentsManager } from '../../../client/common/experiments'; +import { ExperimentsManager } from '../../../client/common/experiments/manager'; import { IConfigurationService, IExperimentsManager, IPythonExtensionBanner } from '../../../client/common/types'; import { ServiceContainer } from '../../../client/ioc/container'; import { IServiceContainer } from '../../../client/ioc/types'; diff --git a/src/test/api.functional.test.ts b/src/test/api.functional.test.ts index 2d9bf970ca24..e70a8236a202 100644 --- a/src/test/api.functional.test.ts +++ b/src/test/api.functional.test.ts @@ -12,7 +12,7 @@ import { Uri } from 'vscode'; import { buildApi } from '../client/api'; import { ConfigurationService } from '../client/common/configuration/service'; import { EXTENSION_ROOT_DIR } from '../client/common/constants'; -import { ExperimentsManager } from '../client/common/experiments'; +import { ExperimentsManager } from '../client/common/experiments/manager'; import { IConfigurationService, IExperimentsManager } from '../client/common/types'; import { ServiceContainer } from '../client/ioc/container'; import { ServiceManager } from '../client/ioc/serviceManager'; diff --git a/src/test/common/experiments.unit.test.ts b/src/test/common/experiments.unit.test.ts index fb43b343c2bb..e74f3e535913 100644 --- a/src/test/common/experiments.unit.test.ts +++ b/src/test/common/experiments.unit.test.ts @@ -22,7 +22,7 @@ import { experimentStorageKey, isDownloadedStorageValidKey, oldExperimentSalts -} from '../../client/common/experiments'; +} from '../../client/common/experiments/manager'; import { HttpClient } from '../../client/common/net/httpClient'; import { PersistentStateFactory } from '../../client/common/persistentState'; import { FileSystem } from '../../client/common/platform/fileSystem'; diff --git a/src/test/common/installer.test.ts b/src/test/common/installer.test.ts index 0f7756d933ee..2bd92b8bba5e 100644 --- a/src/test/common/installer.test.ts +++ b/src/test/common/installer.test.ts @@ -29,7 +29,7 @@ import { AsyncDisposableRegistry } from '../../client/common/asyncDisposableRegi import { ConfigurationService } from '../../client/common/configuration/service'; import { CryptoUtils } from '../../client/common/crypto'; import { EditorUtils } from '../../client/common/editor'; -import { ExperimentsManager } from '../../client/common/experiments'; +import { ExperimentsManager } from '../../client/common/experiments/manager'; import { FeatureDeprecationManager } from '../../client/common/featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, diff --git a/src/test/common/moduleInstaller.test.ts b/src/test/common/moduleInstaller.test.ts index 8e13feb05e7b..9a84713e3e89 100644 --- a/src/test/common/moduleInstaller.test.ts +++ b/src/test/common/moduleInstaller.test.ts @@ -36,7 +36,7 @@ import { AsyncDisposableRegistry } from '../../client/common/asyncDisposableRegi import { ConfigurationService } from '../../client/common/configuration/service'; import { CryptoUtils } from '../../client/common/crypto'; import { EditorUtils } from '../../client/common/editor'; -import { ExperimentsManager } from '../../client/common/experiments'; +import { ExperimentsManager } from '../../client/common/experiments/manager'; import { FeatureDeprecationManager } from '../../client/common/featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, diff --git a/src/test/common/serviceRegistry.unit.test.ts b/src/test/common/serviceRegistry.unit.test.ts index 62bab1a4a092..d40edb5e5378 100644 --- a/src/test/common/serviceRegistry.unit.test.ts +++ b/src/test/common/serviceRegistry.unit.test.ts @@ -34,7 +34,7 @@ import { AsyncDisposableRegistry } from '../../client/common/asyncDisposableRegi import { ConfigurationService } from '../../client/common/configuration/service'; import { CryptoUtils } from '../../client/common/crypto'; import { EditorUtils } from '../../client/common/editor'; -import { ExperimentsManager } from '../../client/common/experiments'; +import { ExperimentsManager } from '../../client/common/experiments/manager'; import { FeatureDeprecationManager } from '../../client/common/featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index 521dc9e1fff2..88c2d3862ce1 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -97,7 +97,7 @@ import { CryptoUtils } from '../../client/common/crypto'; import { DotNetCompatibilityService } from '../../client/common/dotnet/compatibilityService'; import { IDotNetCompatibilityService } from '../../client/common/dotnet/types'; import { LocalZMQKernel } from '../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../client/common/experiments'; +import { ExperimentsManager } from '../../client/common/experiments/manager'; import { InstallationChannelManager } from '../../client/common/installer/channelManager'; import { ProductInstaller } from '../../client/common/installer/productInstaller'; import { diff --git a/src/test/debugger/extension/adapter/factory.unit.test.ts b/src/test/debugger/extension/adapter/factory.unit.test.ts index f3a05d97b9fd..e9e394db4c7d 100644 --- a/src/test/debugger/extension/adapter/factory.unit.test.ts +++ b/src/test/debugger/extension/adapter/factory.unit.test.ts @@ -18,7 +18,7 @@ import { IApplicationShell } from '../../../../client/common/application/types'; import { ConfigurationService } from '../../../../client/common/configuration/service'; import { CryptoUtils } from '../../../../client/common/crypto'; import { DebugAdapterNewPtvsd } from '../../../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../../../client/common/experiments'; +import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { HttpClient } from '../../../../client/common/net/httpClient'; import { PersistentStateFactory } from '../../../../client/common/persistentState'; import { FileSystem } from '../../../../client/common/platform/fileSystem'; diff --git a/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts b/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts index a924be25a2db..0fe67c70b12d 100644 --- a/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts +++ b/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts @@ -13,7 +13,7 @@ import { IApplicationShell } from '../../../../client/common/application/types'; import { ConfigurationService } from '../../../../client/common/configuration/service'; import { CryptoUtils } from '../../../../client/common/crypto'; import { DebugAdapterNewPtvsd } from '../../../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../../../client/common/experiments'; +import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { BrowserService } from '../../../../client/common/net/browser'; import { HttpClient } from '../../../../client/common/net/httpClient'; import { PersistentStateFactory } from '../../../../client/common/persistentState'; diff --git a/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts b/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts index 339f3bd68ba1..568b80822a97 100644 --- a/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts +++ b/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts @@ -11,7 +11,7 @@ import { ApplicationEnvironment } from '../../../../../client/common/application import { ConfigurationService } from '../../../../../client/common/configuration/service'; import { CryptoUtils } from '../../../../../client/common/crypto'; import { DebugAdapterNewPtvsd, WebAppReload } from '../../../../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../../../../client/common/experiments'; +import { ExperimentsManager } from '../../../../../client/common/experiments/manager'; import { HttpClient } from '../../../../../client/common/net/httpClient'; import { PersistentStateFactory } from '../../../../../client/common/persistentState'; import { FileSystem } from '../../../../../client/common/platform/fileSystem'; diff --git a/src/test/interpreters/activation/wrapperEnvironmentActivationService.unit.test.ts b/src/test/interpreters/activation/wrapperEnvironmentActivationService.unit.test.ts index d09858a4412b..1d9677dbd4f0 100644 --- a/src/test/interpreters/activation/wrapperEnvironmentActivationService.unit.test.ts +++ b/src/test/interpreters/activation/wrapperEnvironmentActivationService.unit.test.ts @@ -8,7 +8,7 @@ import { EventEmitter, Uri } from 'vscode'; import { IWorkspaceService } from '../../../client/common/application/types'; import { WorkspaceService } from '../../../client/common/application/workspace'; import { CryptoUtils } from '../../../client/common/crypto'; -import { ExperimentsManager } from '../../../client/common/experiments'; +import { ExperimentsManager } from '../../../client/common/experiments/manager'; import { FileSystem } from '../../../client/common/platform/fileSystem'; import { IFileSystem } from '../../../client/common/platform/types'; import { ICryptoUtils, IExperimentsManager, IExtensionContext, Resource } from '../../../client/common/types'; diff --git a/src/test/interpreters/autoSelection/rules/settings.unit.test.ts b/src/test/interpreters/autoSelection/rules/settings.unit.test.ts index 73b9d647c5d7..21d877c14330 100644 --- a/src/test/interpreters/autoSelection/rules/settings.unit.test.ts +++ b/src/test/interpreters/autoSelection/rules/settings.unit.test.ts @@ -10,7 +10,7 @@ import { anything, instance, mock, when } from 'ts-mockito'; import { IWorkspaceService } from '../../../../client/common/application/types'; import { WorkspaceService } from '../../../../client/common/application/workspace'; import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../../../client/common/experiments'; +import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { InterpreterPathService } from '../../../../client/common/interpreterPathService'; import { PersistentState, PersistentStateFactory } from '../../../../client/common/persistentState'; import { FileSystem } from '../../../../client/common/platform/fileSystem'; diff --git a/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts b/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts index 91add8e2b24e..87786ddda735 100644 --- a/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts +++ b/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts @@ -14,7 +14,7 @@ import { Uri, WorkspaceFolder } from 'vscode'; import { IWorkspaceService } from '../../../../client/common/application/types'; import { WorkspaceService } from '../../../../client/common/application/workspace'; import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../../../client/common/experiments'; +import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { InterpreterPathService } from '../../../../client/common/interpreterPathService'; import { PersistentState, PersistentStateFactory } from '../../../../client/common/persistentState'; import { FileSystem } from '../../../../client/common/platform/fileSystem'; diff --git a/src/test/testing/main.unit.test.ts b/src/test/testing/main.unit.test.ts index 7f38e6ad6b72..1cbea4fddcb2 100644 --- a/src/test/testing/main.unit.test.ts +++ b/src/test/testing/main.unit.test.ts @@ -9,7 +9,7 @@ import { Disposable } from 'vscode'; import { CommandManager } from '../../client/common/application/commandManager'; import { ICommandManager } from '../../client/common/application/types'; import { AlwaysDisplayTestExplorerGroups } from '../../client/common/experimentGroups'; -import { ExperimentsManager } from '../../client/common/experiments'; +import { ExperimentsManager } from '../../client/common/experiments/manager'; import { IDisposableRegistry, IExperimentsManager } from '../../client/common/types'; import { ServiceContainer } from '../../client/ioc/container'; import { IServiceContainer } from '../../client/ioc/types'; From 95021461e7083d7e8e6f7887c267ff8b0ff8253f Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Mon, 25 May 2020 09:24:27 -0700 Subject: [PATCH 04/25] Wrong issue number --- news/1 Enhancements/{10008.md => 10790.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename news/1 Enhancements/{10008.md => 10790.md} (100%) diff --git a/news/1 Enhancements/10008.md b/news/1 Enhancements/10790.md similarity index 100% rename from news/1 Enhancements/10008.md rename to news/1 Enhancements/10790.md From b0683b9cbcbaa3cfa21fdc4191cf753503a1fed8 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Mon, 25 May 2020 09:33:03 -0700 Subject: [PATCH 05/25] eexperimentGroups -> experiments/experimentGroups --- src/client/activation/aaTesting.ts | 2 +- src/client/activation/activationManager.ts | 2 +- src/client/activation/activationService.ts | 2 +- src/client/activation/extensionSurvey.ts | 2 +- src/client/activation/languageClientMiddleware.ts | 2 +- src/client/api.ts | 2 +- .../application/diagnostics/checks/macPythonInterpreter.ts | 2 +- .../application/diagnostics/checks/pythonPathDeprecated.ts | 2 +- src/client/application/diagnostics/checks/upgradeCodeRunner.ts | 2 +- src/client/common/configSettings.ts | 2 +- src/client/common/configuration/service.ts | 2 +- src/client/common/{ => experiments}/experimentGroups.ts | 0 src/client/common/experiments/manager.ts | 2 +- src/client/common/utils/cacheUtils.ts | 2 +- src/client/datascience/context/activeEditorContext.ts | 2 +- src/client/datascience/data-viewing/dataViewer.ts | 2 +- src/client/datascience/editor-integration/hoverProvider.ts | 2 +- src/client/datascience/interactive-common/interactiveBase.ts | 2 +- src/client/datascience/ipywidgets/ipywidgetHandler.ts | 2 +- src/client/datascience/jupyter/jupyterDebugger.ts | 2 +- src/client/datascience/jupyter/jupyterVariables.ts | 2 +- src/client/datascience/kernel-launcher/kernelDaemonPreWarmer.ts | 2 +- src/client/datascience/notebook/integration.ts | 2 +- src/client/datascience/plotting/plotViewer.ts | 2 +- src/client/datascience/raw-kernel/rawNotebookProvider.ts | 2 +- src/client/datascience/serviceRegistry.ts | 2 +- src/client/debugger/extension/adapter/factory.ts | 2 +- src/client/debugger/extension/adapter/outdatedDebuggerPrompt.ts | 2 +- src/client/debugger/extension/configuration/resolvers/attach.ts | 2 +- .../extension/configuration/resolvers/launchConfigExperiment.ts | 2 +- .../activation/wrapperEnvironmentActivationService.ts | 2 +- src/client/interpreter/autoSelection/rules/settings.ts | 2 +- src/client/interpreter/autoSelection/rules/workspaceEnv.ts | 2 +- .../configuration/interpreterSelector/interpreterSelector.ts | 2 +- .../configuration/pythonPathUpdaterServiceFactory.ts | 2 +- src/client/interpreter/interpreterService.ts | 2 +- src/client/startupTelemetry.ts | 2 +- src/client/testing/main.ts | 2 +- src/test/activation/aaTesting.unit.test.ts | 2 +- src/test/activation/activationManager.unit.test.ts | 2 +- src/test/activation/activationService.unit.test.ts | 2 +- src/test/activation/extensionSurvey.unit.test.ts | 2 +- .../diagnostics/checks/macPythonInterpreter.unit.test.ts | 2 +- .../diagnostics/checks/pythonPathDeprecated.unit.test.ts | 2 +- .../diagnostics/checks/upgradeCodeRunner.unit.test.ts | 2 +- .../configSettings/configSettings.pythonPath.unit.test.ts | 2 +- src/test/common/configuration/service.unit.test.ts | 2 +- src/test/common/experiments.unit.test.ts | 2 +- .../terminalActivation.testvirtualenvs.ts | 2 +- .../interpreterSelector/interpreterSelector.unit.test.ts | 2 +- src/test/datascience/dataScienceIocContainer.ts | 2 +- src/test/datascience/debugger.functional.test.tsx | 2 +- src/test/datascience/notebook.functional.test.ts | 2 +- src/test/datascience/uiTests/ipywidget.ui.functional.test.ts | 2 +- src/test/datascience/variableexplorer.functional.test.tsx | 2 +- src/test/debugger/attach.ptvsd.test.ts | 2 +- src/test/debugger/extension/adapter/factory.unit.test.ts | 2 +- .../extension/adapter/outdatedDebuggerPrompt.unit.test.ts | 2 +- .../extension/configuration/resolvers/attach.unit.test.ts | 2 +- .../resolvers/launchConfigExperiments.unit.test.ts | 2 +- src/test/interpreters/autoSelection/rules/settings.unit.test.ts | 2 +- .../interpreters/autoSelection/rules/workspaceEnv.unit.test.ts | 2 +- src/test/interpreters/interpreterService.unit.test.ts | 2 +- src/test/interpreters/pythonPathUpdaterFactory.unit.test.ts | 2 +- src/test/startupTelemetry.unit.test.ts | 2 +- src/test/testing/main.unit.test.ts | 2 +- 66 files changed, 65 insertions(+), 65 deletions(-) rename src/client/common/{ => experiments}/experimentGroups.ts (100%) diff --git a/src/client/activation/aaTesting.ts b/src/client/activation/aaTesting.ts index e37ddb31e4d0..7a0bad49065a 100644 --- a/src/client/activation/aaTesting.ts +++ b/src/client/activation/aaTesting.ts @@ -4,7 +4,7 @@ 'use strict'; import { inject, injectable } from 'inversify'; -import { ValidateABTesting } from '../common/experimentGroups'; +import { ValidateABTesting } from '../common/experiments/experimentGroups'; import { IExperimentsManager } from '../common/types'; import { IExtensionSingleActivationService } from './types'; diff --git a/src/client/activation/activationManager.ts b/src/client/activation/activationManager.ts index f570eb05aa3a..cda28ba0d9a1 100644 --- a/src/client/activation/activationManager.ts +++ b/src/client/activation/activationManager.ts @@ -8,7 +8,7 @@ import { TextDocument } from 'vscode'; import { IApplicationDiagnostics } from '../application/types'; import { IActiveResourceService, IDocumentManager, IWorkspaceService } from '../common/application/types'; import { DEFAULT_INTERPRETER_SETTING, PYTHON_LANGUAGE } from '../common/constants'; -import { DeprecatePythonPath } from '../common/experimentGroups'; +import { DeprecatePythonPath } from '../common/experiments/experimentGroups'; import { traceDecorators } from '../common/logger'; import { IFileSystem } from '../common/platform/types'; import { IDisposable, IExperimentsManager, IInterpreterPathService, Resource } from '../common/types'; diff --git a/src/client/activation/activationService.ts b/src/client/activation/activationService.ts index 3cc2d7f18b80..bd7f73481e63 100644 --- a/src/client/activation/activationService.ts +++ b/src/client/activation/activationService.ts @@ -9,7 +9,7 @@ import { LSNotSupportedDiagnosticServiceId } from '../application/diagnostics/ch import { IDiagnosticsService } from '../application/diagnostics/types'; import { IApplicationShell, ICommandManager, IWorkspaceService } from '../common/application/types'; import { STANDARD_OUTPUT_CHANNEL } from '../common/constants'; -import { LSControl, LSEnabled } from '../common/experimentGroups'; +import { LSControl, LSEnabled } from '../common/experiments/experimentGroups'; import { traceError } from '../common/logger'; import { IConfigurationService, diff --git a/src/client/activation/extensionSurvey.ts b/src/client/activation/extensionSurvey.ts index d502591390b8..9b0642b71190 100644 --- a/src/client/activation/extensionSurvey.ts +++ b/src/client/activation/extensionSurvey.ts @@ -6,7 +6,7 @@ import { inject, injectable, optional } from 'inversify'; import * as querystring from 'querystring'; import { IApplicationEnvironment, IApplicationShell } from '../common/application/types'; -import { ShowExtensionSurveyPrompt } from '../common/experimentGroups'; +import { ShowExtensionSurveyPrompt } from '../common/experiments/experimentGroups'; import '../common/extensions'; import { traceDecorators } from '../common/logger'; import { IPlatformService } from '../common/platform/types'; diff --git a/src/client/activation/languageClientMiddleware.ts b/src/client/activation/languageClientMiddleware.ts index 07418180c674..12d8aca5418f 100644 --- a/src/client/activation/languageClientMiddleware.ts +++ b/src/client/activation/languageClientMiddleware.ts @@ -60,7 +60,7 @@ import { import { ProvideDeclarationSignature } from 'vscode-languageclient/lib/declaration'; import { HiddenFilePrefix } from '../common/constants'; -import { CollectLSRequestTiming, CollectNodeLSRequestTiming } from '../common/experimentGroups'; +import { CollectLSRequestTiming, CollectNodeLSRequestTiming } from '../common/experiments/experimentGroups'; import { IConfigurationService, IExperimentsManager, IPythonExtensionBanner } from '../common/types'; import { StopWatch } from '../common/utils/stopWatch'; import { sendTelemetryEvent } from '../telemetry'; diff --git a/src/client/api.ts b/src/client/api.ts index 61328de72ae6..c9e7532e8e74 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -4,7 +4,7 @@ 'use strict'; import { isTestExecution } from './common/constants'; -import { DebugAdapterNewPtvsd } from './common/experimentGroups'; +import { DebugAdapterNewPtvsd } from './common/experiments/experimentGroups'; import { traceError } from './common/logger'; import { IConfigurationService, IExperimentsManager, Resource } from './common/types'; import { diff --git a/src/client/application/diagnostics/checks/macPythonInterpreter.ts b/src/client/application/diagnostics/checks/macPythonInterpreter.ts index 26344f41a607..1f14bec6be4e 100644 --- a/src/client/application/diagnostics/checks/macPythonInterpreter.ts +++ b/src/client/application/diagnostics/checks/macPythonInterpreter.ts @@ -6,7 +6,7 @@ import { inject, injectable } from 'inversify'; import { ConfigurationChangeEvent, DiagnosticSeverity, Uri } from 'vscode'; import { IWorkspaceService } from '../../../common/application/types'; -import { DeprecatePythonPath } from '../../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../../common/experiments/experimentGroups'; import '../../../common/extensions'; import { IPlatformService } from '../../../common/platform/types'; import { diff --git a/src/client/application/diagnostics/checks/pythonPathDeprecated.ts b/src/client/application/diagnostics/checks/pythonPathDeprecated.ts index 80dd0d5b0cbc..0dd88786d6fe 100644 --- a/src/client/application/diagnostics/checks/pythonPathDeprecated.ts +++ b/src/client/application/diagnostics/checks/pythonPathDeprecated.ts @@ -6,7 +6,7 @@ import { inject, named } from 'inversify'; import { ConfigurationTarget, DiagnosticSeverity } from 'vscode'; import { IWorkspaceService } from '../../../common/application/types'; -import { DeprecatePythonPath } from '../../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../../common/experiments/experimentGroups'; import { IDisposableRegistry, IExperimentsManager, Resource } from '../../../common/types'; import { Common, Diagnostics } from '../../../common/utils/localize'; import { IServiceContainer } from '../../../ioc/types'; diff --git a/src/client/application/diagnostics/checks/upgradeCodeRunner.ts b/src/client/application/diagnostics/checks/upgradeCodeRunner.ts index c2f43939ce6e..da7e11b4268d 100644 --- a/src/client/application/diagnostics/checks/upgradeCodeRunner.ts +++ b/src/client/application/diagnostics/checks/upgradeCodeRunner.ts @@ -7,7 +7,7 @@ import { inject, named } from 'inversify'; import { DiagnosticSeverity } from 'vscode'; import { IWorkspaceService } from '../../../common/application/types'; import { CODE_RUNNER_EXTENSION_ID } from '../../../common/constants'; -import { DeprecatePythonPath } from '../../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../../common/experiments/experimentGroups'; import { IDisposableRegistry, IExperimentsManager, IExtensions, Resource } from '../../../common/types'; import { Common, Diagnostics } from '../../../common/utils/localize'; import { IServiceContainer } from '../../../ioc/types'; diff --git a/src/client/common/configSettings.ts b/src/client/common/configSettings.ts index 89aa79e5f7eb..5ae5f0165e77 100644 --- a/src/client/common/configSettings.ts +++ b/src/client/common/configSettings.ts @@ -21,7 +21,7 @@ import { sendSettingTelemetry } from '../telemetry/envFileTelemetry'; import { IWorkspaceService } from './application/types'; import { WorkspaceService } from './application/workspace'; import { DEFAULT_INTERPRETER_SETTING, isTestExecution } from './constants'; -import { DeprecatePythonPath } from './experimentGroups'; +import { DeprecatePythonPath } from './experiments/experimentGroups'; import { ExtensionChannels } from './insidersBuild/types'; import { IS_WINDOWS } from './platform/constants'; import * as internalPython from './process/internal/python'; diff --git a/src/client/common/configuration/service.ts b/src/client/common/configuration/service.ts index 00a8c789f204..658e3f2cba23 100644 --- a/src/client/common/configuration/service.ts +++ b/src/client/common/configuration/service.ts @@ -11,7 +11,7 @@ import { IServiceContainer } from '../../ioc/types'; import { IWorkspaceService } from '../application/types'; import { PythonSettings } from '../configSettings'; import { isUnitTestExecution } from '../constants'; -import { DeprecatePythonPath } from '../experimentGroups'; +import { DeprecatePythonPath } from '../experiments/experimentGroups'; import { IConfigurationService, IExperimentsManager, IInterpreterPathService, IPythonSettings } from '../types'; @injectable() diff --git a/src/client/common/experimentGroups.ts b/src/client/common/experiments/experimentGroups.ts similarity index 100% rename from src/client/common/experimentGroups.ts rename to src/client/common/experiments/experimentGroups.ts diff --git a/src/client/common/experiments/manager.ts b/src/client/common/experiments/manager.ts index a37441d209f5..40b5e1d64067 100644 --- a/src/client/common/experiments/manager.ts +++ b/src/client/common/experiments/manager.ts @@ -12,7 +12,6 @@ import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { IApplicationEnvironment } from '../application/types'; import { EXTENSION_ROOT_DIR, STANDARD_OUTPUT_CHANNEL } from '../constants'; -import { NativeNotebook } from '../experimentGroups'; import { traceDecorators, traceError } from '../logger'; import { IFileSystem } from '../platform/types'; import { @@ -29,6 +28,7 @@ import { import { sleep } from '../utils/async'; import { swallowExceptions } from '../utils/decorators'; import { Experiments } from '../utils/localize'; +import { NativeNotebook } from './experimentGroups'; const EXPIRY_DURATION_MS = 30 * 60 * 1000; export const isDownloadedStorageValidKey = 'IS_EXPERIMENTS_STORAGE_VALID_KEY'; diff --git a/src/client/common/utils/cacheUtils.ts b/src/client/common/utils/cacheUtils.ts index 66fe0c35f626..51ccd1741fc6 100644 --- a/src/client/common/utils/cacheUtils.ts +++ b/src/client/common/utils/cacheUtils.ts @@ -9,7 +9,7 @@ import { Uri } from 'vscode'; import '../../common/extensions'; import { IServiceContainer } from '../../ioc/types'; import { DEFAULT_INTERPRETER_SETTING } from '../constants'; -import { DeprecatePythonPath } from '../experimentGroups'; +import { DeprecatePythonPath } from '../experiments/experimentGroups'; import { IExperimentsManager, IInterpreterPathService, Resource } from '../types'; type VSCodeType = typeof import('vscode'); diff --git a/src/client/datascience/context/activeEditorContext.ts b/src/client/datascience/context/activeEditorContext.ts index 0872109b3621..f7b490ce14b8 100644 --- a/src/client/datascience/context/activeEditorContext.ts +++ b/src/client/datascience/context/activeEditorContext.ts @@ -9,7 +9,7 @@ import { IExtensionSingleActivationService } from '../../activation/types'; import { ICommandManager, IDocumentManager, IVSCodeNotebook } from '../../common/application/types'; import { PYTHON_LANGUAGE } from '../../common/constants'; import { ContextKey } from '../../common/contextKey'; -import { NativeNotebook } from '../../common/experimentGroups'; +import { NativeNotebook } from '../../common/experiments/experimentGroups'; import { IDisposable, IDisposableRegistry, IExperimentsManager } from '../../common/types'; import { EditorContexts } from '../constants'; import { IInteractiveWindow, IInteractiveWindowProvider, INotebookEditor, INotebookEditorProvider } from '../types'; diff --git a/src/client/datascience/data-viewing/dataViewer.ts b/src/client/datascience/data-viewing/dataViewer.ts index 25a3538c08dc..f46e6a4ea091 100644 --- a/src/client/datascience/data-viewing/dataViewer.ts +++ b/src/client/datascience/data-viewing/dataViewer.ts @@ -9,7 +9,7 @@ import { ViewColumn } from 'vscode'; import { IApplicationShell, IWebPanelProvider, IWorkspaceService } from '../../common/application/types'; import { EXTENSION_ROOT_DIR, UseCustomEditorApi } from '../../common/constants'; -import { WebHostNotebook } from '../../common/experimentGroups'; +import { WebHostNotebook } from '../../common/experiments/experimentGroups'; import { traceError } from '../../common/logger'; import { IConfigurationService, IDisposable, IExperimentsManager, Resource } from '../../common/types'; import * as localize from '../../common/utils/localize'; diff --git a/src/client/datascience/editor-integration/hoverProvider.ts b/src/client/datascience/editor-integration/hoverProvider.ts index 51198033355b..c25be9da85f1 100644 --- a/src/client/datascience/editor-integration/hoverProvider.ts +++ b/src/client/datascience/editor-integration/hoverProvider.ts @@ -6,7 +6,7 @@ import { inject, injectable, named } from 'inversify'; import * as vscode from 'vscode'; import { Cancellation } from '../../common/cancellation'; import { PYTHON } from '../../common/constants'; -import { RunByLine } from '../../common/experimentGroups'; +import { RunByLine } from '../../common/experiments/experimentGroups'; import { traceError } from '../../common/logger'; import { IExperimentsManager } from '../../common/types'; import { sleep } from '../../common/utils/async'; diff --git a/src/client/datascience/interactive-common/interactiveBase.ts b/src/client/datascience/interactive-common/interactiveBase.ts index 3dd45fb02ecd..1d45baddb77d 100644 --- a/src/client/datascience/interactive-common/interactiveBase.ts +++ b/src/client/datascience/interactive-common/interactiveBase.ts @@ -35,7 +35,7 @@ import { } from '../../common/application/types'; import { CancellationError } from '../../common/cancellation'; import { EXTENSION_ROOT_DIR, isTestExecution, PYTHON_LANGUAGE } from '../../common/constants'; -import { RunByLine, WebHostNotebook } from '../../common/experimentGroups'; +import { RunByLine, WebHostNotebook } from '../../common/experiments/experimentGroups'; import { traceError, traceInfo, traceWarning } from '../../common/logger'; import { IFileSystem } from '../../common/platform/types'; import { IConfigurationService, IDisposableRegistry, IExperimentsManager } from '../../common/types'; diff --git a/src/client/datascience/ipywidgets/ipywidgetHandler.ts b/src/client/datascience/ipywidgets/ipywidgetHandler.ts index 3a22f0a79462..7d29232156c1 100644 --- a/src/client/datascience/ipywidgets/ipywidgetHandler.ts +++ b/src/client/datascience/ipywidgets/ipywidgetHandler.ts @@ -12,7 +12,7 @@ import { LoadIPyWidgetClassLoadAction, NotifyIPyWidgeWidgetVersionNotSupportedAction } from '../../../datascience-ui/interactive-common/redux/reducers/types'; -import { EnableIPyWidgets } from '../../common/experimentGroups'; +import { EnableIPyWidgets } from '../../common/experiments/experimentGroups'; import { traceError, traceInfo } from '../../common/logger'; import { IDisposableRegistry, IExperimentsManager, IOutputChannel } from '../../common/types'; import * as localize from '../../common/utils/localize'; diff --git a/src/client/datascience/jupyter/jupyterDebugger.ts b/src/client/datascience/jupyter/jupyterDebugger.ts index 3649e3dcecb4..34ce21652832 100644 --- a/src/client/datascience/jupyter/jupyterDebugger.ts +++ b/src/client/datascience/jupyter/jupyterDebugger.ts @@ -10,7 +10,7 @@ import * as vsls from 'vsls/vscode'; import { concatMultilineStringOutput } from '../../../datascience-ui/common'; import { ServerStatus } from '../../../datascience-ui/interactive-common/mainState'; import { IApplicationShell } from '../../common/application/types'; -import { DebugAdapterNewPtvsd } from '../../common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../common/experiments/experimentGroups'; import { traceError, traceInfo, traceWarning } from '../../common/logger'; import { IPlatformService } from '../../common/platform/types'; import { IConfigurationService, IExperimentsManager, Version } from '../../common/types'; diff --git a/src/client/datascience/jupyter/jupyterVariables.ts b/src/client/datascience/jupyter/jupyterVariables.ts index 539e6690e88f..8fff0747a771 100644 --- a/src/client/datascience/jupyter/jupyterVariables.ts +++ b/src/client/datascience/jupyter/jupyterVariables.ts @@ -5,7 +5,7 @@ import type { JSONObject } from '@phosphor/coreutils'; import { inject, injectable, named } from 'inversify'; import { Event, EventEmitter } from 'vscode'; -import { RunByLine } from '../../common/experimentGroups'; +import { RunByLine } from '../../common/experiments/experimentGroups'; import { IDisposableRegistry, IExperimentsManager } from '../../common/types'; import { captureTelemetry } from '../../telemetry'; import { Identifiers, Telemetry } from '../constants'; diff --git a/src/client/datascience/kernel-launcher/kernelDaemonPreWarmer.ts b/src/client/datascience/kernel-launcher/kernelDaemonPreWarmer.ts index 1259e15c1a64..f4a21c8231a9 100644 --- a/src/client/datascience/kernel-launcher/kernelDaemonPreWarmer.ts +++ b/src/client/datascience/kernel-launcher/kernelDaemonPreWarmer.ts @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify'; import { IExtensionActivationService } from '../../activation/types'; -import { LocalZMQKernel } from '../../common/experimentGroups'; +import { LocalZMQKernel } from '../../common/experiments/experimentGroups'; import '../../common/extensions'; import { IDisposableRegistry, IExperimentsManager, Resource } from '../../common/types'; import { swallowExceptions } from '../../common/utils/decorators'; diff --git a/src/client/datascience/notebook/integration.ts b/src/client/datascience/notebook/integration.ts index 48af9307b55d..fa1d2750c9d4 100644 --- a/src/client/datascience/notebook/integration.ts +++ b/src/client/datascience/notebook/integration.ts @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify'; import * as path from 'path'; import { IExtensionSingleActivationService } from '../../activation/types'; import { ICommandManager, IVSCodeNotebook } from '../../common/application/types'; -import { NativeNotebook } from '../../common/experimentGroups'; +import { NativeNotebook } from '../../common/experiments/experimentGroups'; import { IFileSystem } from '../../common/platform/types'; import { IDisposableRegistry, IExperimentsManager, IExtensionContext } from '../../common/types'; import { noop } from '../../common/utils/misc'; diff --git a/src/client/datascience/plotting/plotViewer.ts b/src/client/datascience/plotting/plotViewer.ts index 6f17e0d9bf91..9b4917a21735 100644 --- a/src/client/datascience/plotting/plotViewer.ts +++ b/src/client/datascience/plotting/plotViewer.ts @@ -11,7 +11,7 @@ import { traceInfo } from '../../../client/common/logger'; import { createDeferred } from '../../../client/common/utils/async'; import { IApplicationShell, IWebPanelProvider, IWorkspaceService } from '../../common/application/types'; import { EXTENSION_ROOT_DIR, UseCustomEditorApi } from '../../common/constants'; -import { WebHostNotebook } from '../../common/experimentGroups'; +import { WebHostNotebook } from '../../common/experiments/experimentGroups'; import { traceError } from '../../common/logger'; import { IFileSystem } from '../../common/platform/types'; import { IConfigurationService, IDisposable, IExperimentsManager, Resource } from '../../common/types'; diff --git a/src/client/datascience/raw-kernel/rawNotebookProvider.ts b/src/client/datascience/raw-kernel/rawNotebookProvider.ts index a8fae10c20b0..1cc06161ba2e 100644 --- a/src/client/datascience/raw-kernel/rawNotebookProvider.ts +++ b/src/client/datascience/raw-kernel/rawNotebookProvider.ts @@ -6,7 +6,7 @@ import * as uuid from 'uuid/v4'; import { Event, EventEmitter, Uri } from 'vscode'; import { CancellationToken } from 'vscode-jsonrpc'; import { ILiveShareApi } from '../../common/application/types'; -import { LocalZMQKernel } from '../../common/experimentGroups'; +import { LocalZMQKernel } from '../../common/experiments/experimentGroups'; import '../../common/extensions'; import { traceError, traceInfo } from '../../common/logger'; import { IAsyncDisposableRegistry, IConfigurationService, IExperimentsManager, Resource } from '../../common/types'; diff --git a/src/client/datascience/serviceRegistry.ts b/src/client/datascience/serviceRegistry.ts index aa33e7914e6c..e242c26b8dfa 100644 --- a/src/client/datascience/serviceRegistry.ts +++ b/src/client/datascience/serviceRegistry.ts @@ -4,7 +4,7 @@ import { IExtensionSingleActivationService } from '../activation/types'; import { IApplicationEnvironment } from '../common/application/types'; import { UseCustomEditorApi } from '../common/constants'; -import { NativeNotebook } from '../common/experimentGroups'; +import { NativeNotebook } from '../common/experiments/experimentGroups'; import { IExperimentsManager } from '../common/types'; import { ProtocolParser } from '../debugger/debugAdapter/Common/protocolParser'; import { IProtocolParser } from '../debugger/debugAdapter/types'; diff --git a/src/client/debugger/extension/adapter/factory.ts b/src/client/debugger/extension/adapter/factory.ts index cb4a34b13e9c..968e7c013003 100644 --- a/src/client/debugger/extension/adapter/factory.ts +++ b/src/client/debugger/extension/adapter/factory.ts @@ -13,7 +13,7 @@ import { WorkspaceFolder } from 'vscode'; import { IApplicationShell } from '../../../common/application/types'; -import { DebugAdapterNewPtvsd } from '../../../common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../../common/experiments/experimentGroups'; import { traceVerbose } from '../../../common/logger'; import { IExperimentsManager } from '../../../common/types'; import { EXTENSION_ROOT_DIR } from '../../../constants'; diff --git a/src/client/debugger/extension/adapter/outdatedDebuggerPrompt.ts b/src/client/debugger/extension/adapter/outdatedDebuggerPrompt.ts index f149e0958dbd..b5ff671369aa 100644 --- a/src/client/debugger/extension/adapter/outdatedDebuggerPrompt.ts +++ b/src/client/debugger/extension/adapter/outdatedDebuggerPrompt.ts @@ -7,7 +7,7 @@ import { inject, injectable } from 'inversify'; import { DebugAdapterTracker, DebugAdapterTrackerFactory, DebugSession, ProviderResult } from 'vscode'; import { DebugProtocol } from 'vscode-debugprotocol'; import { IApplicationShell } from '../../../common/application/types'; -import { DebugAdapterNewPtvsd } from '../../../common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../../common/experiments/experimentGroups'; import { IBrowserService, IExperimentsManager } from '../../../common/types'; import { Common, OutdatedDebugger } from '../../../common/utils/localize'; import { IPromptShowState } from './types'; diff --git a/src/client/debugger/extension/configuration/resolvers/attach.ts b/src/client/debugger/extension/configuration/resolvers/attach.ts index bcfdd4734e79..fc18fd614d8b 100644 --- a/src/client/debugger/extension/configuration/resolvers/attach.ts +++ b/src/client/debugger/extension/configuration/resolvers/attach.ts @@ -6,7 +6,7 @@ import { inject, injectable } from 'inversify'; import { CancellationToken, Uri, WorkspaceFolder } from 'vscode'; import { IDocumentManager, IWorkspaceService } from '../../../../common/application/types'; -import { DebugAdapterNewPtvsd } from '../../../../common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../../../common/experiments/experimentGroups'; import { IPlatformService } from '../../../../common/platform/types'; import { IConfigurationService, IExperimentsManager } from '../../../../common/types'; import { Diagnostics } from '../../../../common/utils/localize'; diff --git a/src/client/debugger/extension/configuration/resolvers/launchConfigExperiment.ts b/src/client/debugger/extension/configuration/resolvers/launchConfigExperiment.ts index d6416950adf0..6c7d32184a5e 100644 --- a/src/client/debugger/extension/configuration/resolvers/launchConfigExperiment.ts +++ b/src/client/debugger/extension/configuration/resolvers/launchConfigExperiment.ts @@ -4,7 +4,7 @@ 'use strict'; import { inject, injectable } from 'inversify'; -import { DebugAdapterNewPtvsd, WebAppReload } from '../../../../common/experimentGroups'; +import { DebugAdapterNewPtvsd, WebAppReload } from '../../../../common/experiments/experimentGroups'; import { traceInfo } from '../../../../common/logger'; import { IExperimentsManager } from '../../../../common/types'; import { sendTelemetryEvent } from '../../../../telemetry'; diff --git a/src/client/interpreter/activation/wrapperEnvironmentActivationService.ts b/src/client/interpreter/activation/wrapperEnvironmentActivationService.ts index b8fc7317caeb..7dcf0e41b93b 100644 --- a/src/client/interpreter/activation/wrapperEnvironmentActivationService.ts +++ b/src/client/interpreter/activation/wrapperEnvironmentActivationService.ts @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify'; import * as path from 'path'; -import { UseTerminalToGetActivatedEnvVars } from '../../common/experimentGroups'; +import { UseTerminalToGetActivatedEnvVars } from '../../common/experiments/experimentGroups'; import '../../common/extensions'; import { traceError } from '../../common/logger'; import { IFileSystem } from '../../common/platform/types'; diff --git a/src/client/interpreter/autoSelection/rules/settings.ts b/src/client/interpreter/autoSelection/rules/settings.ts index bbd79abe6f0c..a2139a5a480f 100644 --- a/src/client/interpreter/autoSelection/rules/settings.ts +++ b/src/client/interpreter/autoSelection/rules/settings.ts @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify'; import { IWorkspaceService } from '../../../common/application/types'; -import { DeprecatePythonPath } from '../../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../../common/experiments/experimentGroups'; import { IFileSystem } from '../../../common/platform/types'; import { IExperimentsManager, IInterpreterPathService, IPersistentStateFactory, Resource } from '../../../common/types'; import { AutoSelectionRule, IInterpreterAutoSelectionService } from '../types'; diff --git a/src/client/interpreter/autoSelection/rules/workspaceEnv.ts b/src/client/interpreter/autoSelection/rules/workspaceEnv.ts index d033b087c451..95e625a3a44d 100644 --- a/src/client/interpreter/autoSelection/rules/workspaceEnv.ts +++ b/src/client/interpreter/autoSelection/rules/workspaceEnv.ts @@ -6,7 +6,7 @@ import { inject, injectable, named } from 'inversify'; import { Uri } from 'vscode'; import { IWorkspaceService } from '../../../common/application/types'; -import { DeprecatePythonPath } from '../../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../../common/experiments/experimentGroups'; import { traceVerbose } from '../../../common/logger'; import { IFileSystem, IPlatformService } from '../../../common/platform/types'; import { IExperimentsManager, IInterpreterPathService, IPersistentStateFactory, Resource } from '../../../common/types'; diff --git a/src/client/interpreter/configuration/interpreterSelector/interpreterSelector.ts b/src/client/interpreter/configuration/interpreterSelector/interpreterSelector.ts index f7c95fb7e0e1..4d449b782d95 100644 --- a/src/client/interpreter/configuration/interpreterSelector/interpreterSelector.ts +++ b/src/client/interpreter/configuration/interpreterSelector/interpreterSelector.ts @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify'; import { Disposable, Uri } from 'vscode'; -import { DeprecatePythonPath } from '../../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../../common/experiments/experimentGroups'; import { IExperimentsManager, IPathUtils, Resource } from '../../../common/types'; import { IInterpreterSecurityService } from '../../autoSelection/types'; import { IInterpreterService, PythonInterpreter } from '../../contracts'; diff --git a/src/client/interpreter/configuration/pythonPathUpdaterServiceFactory.ts b/src/client/interpreter/configuration/pythonPathUpdaterServiceFactory.ts index b1e70235c4b8..66a0ea85d923 100644 --- a/src/client/interpreter/configuration/pythonPathUpdaterServiceFactory.ts +++ b/src/client/interpreter/configuration/pythonPathUpdaterServiceFactory.ts @@ -1,7 +1,7 @@ import { inject, injectable } from 'inversify'; import { Uri } from 'vscode'; import { IWorkspaceService } from '../../common/application/types'; -import { DeprecatePythonPath } from '../../common/experimentGroups'; +import { DeprecatePythonPath } from '../../common/experiments/experimentGroups'; import { IExperimentsManager, IInterpreterPathService } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; import { GlobalPythonPathUpdaterService } from './services/globalUpdaterService'; diff --git a/src/client/interpreter/interpreterService.ts b/src/client/interpreter/interpreterService.ts index 6eef287fe8e4..6d9a0496f752 100644 --- a/src/client/interpreter/interpreterService.ts +++ b/src/client/interpreter/interpreterService.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import { Disposable, Event, EventEmitter, Uri } from 'vscode'; import '../../client/common/extensions'; import { IDocumentManager, IWorkspaceService } from '../common/application/types'; -import { DeprecatePythonPath } from '../common/experimentGroups'; +import { DeprecatePythonPath } from '../common/experiments/experimentGroups'; import { traceError } from '../common/logger'; import { getArchitectureDisplayName } from '../common/platform/registry'; import { IFileSystem } from '../common/platform/types'; diff --git a/src/client/startupTelemetry.ts b/src/client/startupTelemetry.ts index c84e78c10837..cbc48b7553df 100644 --- a/src/client/startupTelemetry.ts +++ b/src/client/startupTelemetry.ts @@ -3,7 +3,7 @@ import { IWorkspaceService } from './common/application/types'; import { isTestExecution } from './common/constants'; -import { DeprecatePythonPath } from './common/experimentGroups'; +import { DeprecatePythonPath } from './common/experiments/experimentGroups'; import { traceError } from './common/logger'; import { ITerminalHelper } from './common/terminal/types'; import { diff --git a/src/client/testing/main.ts b/src/client/testing/main.ts index f7e84b4b1ff0..c242014ee51a 100644 --- a/src/client/testing/main.ts +++ b/src/client/testing/main.ts @@ -15,7 +15,7 @@ import { } from 'vscode'; import { IApplicationShell, ICommandManager, IDocumentManager, IWorkspaceService } from '../common/application/types'; import * as constants from '../common/constants'; -import { AlwaysDisplayTestExplorerGroups } from '../common/experimentGroups'; +import { AlwaysDisplayTestExplorerGroups } from '../common/experiments/experimentGroups'; import '../common/extensions'; import { traceError } from '../common/logger'; import { diff --git a/src/test/activation/aaTesting.unit.test.ts b/src/test/activation/aaTesting.unit.test.ts index 78e1af84a2c9..5b2d7340fb92 100644 --- a/src/test/activation/aaTesting.unit.test.ts +++ b/src/test/activation/aaTesting.unit.test.ts @@ -5,7 +5,7 @@ import * as TypeMoq from 'typemoq'; import { AATesting } from '../../client/activation/aaTesting'; -import { ValidateABTesting } from '../../client/common/experimentGroups'; +import { ValidateABTesting } from '../../client/common/experiments/experimentGroups'; import { IExperimentsManager } from '../../client/common/types'; suite('A/A Testing', () => { diff --git a/src/test/activation/activationManager.unit.test.ts b/src/test/activation/activationManager.unit.test.ts index 388d4780fde6..8fd5bd519c79 100644 --- a/src/test/activation/activationManager.unit.test.ts +++ b/src/test/activation/activationManager.unit.test.ts @@ -16,7 +16,7 @@ import { ActiveResourceService } from '../../client/common/application/activeRes import { IActiveResourceService, IDocumentManager, IWorkspaceService } from '../../client/common/application/types'; import { WorkspaceService } from '../../client/common/application/workspace'; import { PYTHON_LANGUAGE } from '../../client/common/constants'; -import { DeprecatePythonPath } from '../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../client/common/experiments/manager'; import { InterpreterPathService } from '../../client/common/interpreterPathService'; import { FileSystem } from '../../client/common/platform/fileSystem'; diff --git a/src/test/activation/activationService.unit.test.ts b/src/test/activation/activationService.unit.test.ts index 4dccd02b03f3..6dc12f75ae90 100644 --- a/src/test/activation/activationService.unit.test.ts +++ b/src/test/activation/activationService.unit.test.ts @@ -16,7 +16,7 @@ import { import { LSNotSupportedDiagnosticServiceId } from '../../client/application/diagnostics/checks/lsNotSupported'; import { IDiagnostic, IDiagnosticsService } from '../../client/application/diagnostics/types'; import { IApplicationShell, ICommandManager, IWorkspaceService } from '../../client/common/application/types'; -import { LSControl, LSEnabled } from '../../client/common/experimentGroups'; +import { LSControl, LSEnabled } from '../../client/common/experiments/experimentGroups'; import { IPlatformService } from '../../client/common/platform/types'; import { IConfigurationService, diff --git a/src/test/activation/extensionSurvey.unit.test.ts b/src/test/activation/extensionSurvey.unit.test.ts index d482d8466e54..09bba07a6fc8 100644 --- a/src/test/activation/extensionSurvey.unit.test.ts +++ b/src/test/activation/extensionSurvey.unit.test.ts @@ -9,7 +9,7 @@ import { anything, instance, mock, verify, when } from 'ts-mockito'; import * as TypeMoq from 'typemoq'; import { ExtensionSurveyPrompt, extensionSurveyStateKeys } from '../../client/activation/extensionSurvey'; import { IApplicationEnvironment, IApplicationShell } from '../../client/common/application/types'; -import { ShowExtensionSurveyPrompt } from '../../client/common/experimentGroups'; +import { ShowExtensionSurveyPrompt } from '../../client/common/experiments/experimentGroups'; import { PersistentStateFactory } from '../../client/common/persistentState'; import { IPlatformService } from '../../client/common/platform/types'; import { diff --git a/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts b/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts index eaa9315341d3..6ff415893eef 100644 --- a/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts +++ b/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts @@ -29,7 +29,7 @@ import { } from '../../../../client/application/diagnostics/types'; import { CommandsWithoutArgs } from '../../../../client/common/application/commands'; import { IWorkspaceService } from '../../../../client/common/application/types'; -import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../../client/common/experiments/experimentGroups'; import { IPlatformService } from '../../../../client/common/platform/types'; import { IConfigurationService, diff --git a/src/test/application/diagnostics/checks/pythonPathDeprecated.unit.test.ts b/src/test/application/diagnostics/checks/pythonPathDeprecated.unit.test.ts index 014bf92eff1e..c530d16d0220 100644 --- a/src/test/application/diagnostics/checks/pythonPathDeprecated.unit.test.ts +++ b/src/test/application/diagnostics/checks/pythonPathDeprecated.unit.test.ts @@ -28,7 +28,7 @@ import { IDiagnosticHandlerService } from '../../../../client/application/diagnostics/types'; import { IWorkspaceService } from '../../../../client/common/application/types'; -import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../../client/common/experiments/experimentGroups'; import { IDisposableRegistry, IExperimentsManager, Resource } from '../../../../client/common/types'; import { Common, Diagnostics } from '../../../../client/common/utils/localize'; import { IServiceContainer } from '../../../../client/ioc/types'; diff --git a/src/test/application/diagnostics/checks/upgradeCodeRunner.unit.test.ts b/src/test/application/diagnostics/checks/upgradeCodeRunner.unit.test.ts index 64b4f9f35ee5..7bb493668761 100644 --- a/src/test/application/diagnostics/checks/upgradeCodeRunner.unit.test.ts +++ b/src/test/application/diagnostics/checks/upgradeCodeRunner.unit.test.ts @@ -28,7 +28,7 @@ import { } from '../../../../client/application/diagnostics/types'; import { IWorkspaceService } from '../../../../client/common/application/types'; import { CODE_RUNNER_EXTENSION_ID } from '../../../../client/common/constants'; -import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../../client/common/experiments/experimentGroups'; import { IDisposableRegistry, IExperimentsManager, IExtensions, Resource } from '../../../../client/common/types'; import { Common, Diagnostics } from '../../../../client/common/utils/localize'; import { IServiceContainer } from '../../../../client/ioc/types'; diff --git a/src/test/common/configSettings/configSettings.pythonPath.unit.test.ts b/src/test/common/configSettings/configSettings.pythonPath.unit.test.ts index b15ebfff705e..ab3fdd57439f 100644 --- a/src/test/common/configSettings/configSettings.pythonPath.unit.test.ts +++ b/src/test/common/configSettings/configSettings.pythonPath.unit.test.ts @@ -13,7 +13,7 @@ import * as typemoq from 'typemoq'; import { Uri, WorkspaceConfiguration } from 'vscode'; import { IWorkspaceService } from '../../../client/common/application/types'; import { PythonSettings } from '../../../client/common/configSettings'; -import { DeprecatePythonPath } from '../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../client/common/experiments/experimentGroups'; import { IExperimentsManager, IInterpreterPathService } from '../../../client/common/types'; import { noop } from '../../../client/common/utils/misc'; import { IInterpreterSecurityService } from '../../../client/interpreter/autoSelection/types'; diff --git a/src/test/common/configuration/service.unit.test.ts b/src/test/common/configuration/service.unit.test.ts index 87fceaad4a7c..0beb2f7d2b06 100644 --- a/src/test/common/configuration/service.unit.test.ts +++ b/src/test/common/configuration/service.unit.test.ts @@ -9,7 +9,7 @@ import { ConfigurationTarget, Uri, WorkspaceConfiguration } from 'vscode'; import { IWorkspaceService } from '../../../client/common/application/types'; import { PythonSettings } from '../../../client/common/configSettings'; import { ConfigurationService } from '../../../client/common/configuration/service'; -import { DeprecatePythonPath } from '../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../client/common/experiments/experimentGroups'; import { IExperimentsManager, IInterpreterPathService } from '../../../client/common/types'; import { IInterpreterAutoSeletionProxyService, diff --git a/src/test/common/experiments.unit.test.ts b/src/test/common/experiments.unit.test.ts index e74f3e535913..14b03b08fb70 100644 --- a/src/test/common/experiments.unit.test.ts +++ b/src/test/common/experiments.unit.test.ts @@ -14,7 +14,7 @@ import { IApplicationEnvironment } from '../../client/common/application/types'; import { PythonSettings } from '../../client/common/configSettings'; import { ConfigurationService } from '../../client/common/configuration/service'; import { CryptoUtils } from '../../client/common/crypto'; -import { NativeNotebook } from '../../client/common/experimentGroups'; +import { NativeNotebook } from '../../client/common/experiments/experimentGroups'; import { configUri, downloadedExperimentStorageKey, diff --git a/src/test/common/terminals/environmentActivationProviders/terminalActivation.testvirtualenvs.ts b/src/test/common/terminals/environmentActivationProviders/terminalActivation.testvirtualenvs.ts index 180b790eb774..8203dd709e7c 100644 --- a/src/test/common/terminals/environmentActivationProviders/terminalActivation.testvirtualenvs.ts +++ b/src/test/common/terminals/environmentActivationProviders/terminalActivation.testvirtualenvs.ts @@ -7,7 +7,7 @@ import { expect } from 'chai'; import * as fs from 'fs-extra'; import * as path from 'path'; import * as vscode from 'vscode'; -import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../../client/common/experiments/experimentGroups'; import { FileSystem } from '../../../../client/common/platform/fileSystem'; import { IExperimentsManager } from '../../../../client/common/types'; import { PYTHON_VIRTUAL_ENVS_LOCATION } from '../../../ciConstants'; diff --git a/src/test/configuration/interpreterSelector/interpreterSelector.unit.test.ts b/src/test/configuration/interpreterSelector/interpreterSelector.unit.test.ts index 0410a29dac78..61396c503138 100644 --- a/src/test/configuration/interpreterSelector/interpreterSelector.unit.test.ts +++ b/src/test/configuration/interpreterSelector/interpreterSelector.unit.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { SemVer } from 'semver'; import * as TypeMoq from 'typemoq'; import { Uri } from 'vscode'; -import { DeprecatePythonPath } from '../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../client/common/experiments/experimentGroups'; import { PathUtils } from '../../../client/common/platform/pathUtils'; import { IFileSystem } from '../../../client/common/platform/types'; import { IExperimentsManager } from '../../../client/common/types'; diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index 88c2d3862ce1..6a19f5ffd26f 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -96,7 +96,7 @@ import { EXTENSION_ROOT_DIR, UseCustomEditorApi, UseProposedApi } from '../../cl import { CryptoUtils } from '../../client/common/crypto'; import { DotNetCompatibilityService } from '../../client/common/dotnet/compatibilityService'; import { IDotNetCompatibilityService } from '../../client/common/dotnet/types'; -import { LocalZMQKernel } from '../../client/common/experimentGroups'; +import { LocalZMQKernel } from '../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../client/common/experiments/manager'; import { InstallationChannelManager } from '../../client/common/installer/channelManager'; import { ProductInstaller } from '../../client/common/installer/productInstaller'; diff --git a/src/test/datascience/debugger.functional.test.tsx b/src/test/datascience/debugger.functional.test.tsx index 5be60c8da38b..6ec94dfb04a4 100644 --- a/src/test/datascience/debugger.functional.test.tsx +++ b/src/test/datascience/debugger.functional.test.tsx @@ -9,7 +9,7 @@ import { CodeLens, Disposable, Position, Range, SourceBreakpoint, Uri } from 'vs import { CancellationToken } from 'vscode-jsonrpc'; import { IApplicationShell, IDocumentManager } from '../../client/common/application/types'; -import { RunByLine } from '../../client/common/experimentGroups'; +import { RunByLine } from '../../client/common/experiments/experimentGroups'; import { createDeferred, waitForPromise } from '../../client/common/utils/async'; import { noop } from '../../client/common/utils/misc'; import { EXTENSION_ROOT_DIR } from '../../client/constants'; diff --git a/src/test/datascience/notebook.functional.test.ts b/src/test/datascience/notebook.functional.test.ts index 1459ed863feb..2d5a3cc0d7fe 100644 --- a/src/test/datascience/notebook.functional.test.ts +++ b/src/test/datascience/notebook.functional.test.ts @@ -19,7 +19,7 @@ import { ApplicationShell } from '../../client/common/application/applicationShe import { IApplicationShell } from '../../client/common/application/types'; import { Cancellation, CancellationError } from '../../client/common/cancellation'; import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; -import { LocalZMQKernel } from '../../client/common/experimentGroups'; +import { LocalZMQKernel } from '../../client/common/experiments/experimentGroups'; import { traceError, traceInfo } from '../../client/common/logger'; import { IFileSystem } from '../../client/common/platform/types'; import { IPythonExecutionFactory, IPythonExecutionService, Output } from '../../client/common/process/types'; diff --git a/src/test/datascience/uiTests/ipywidget.ui.functional.test.ts b/src/test/datascience/uiTests/ipywidget.ui.functional.test.ts index 0c7bee367f83..969e89668236 100644 --- a/src/test/datascience/uiTests/ipywidget.ui.functional.test.ts +++ b/src/test/datascience/uiTests/ipywidget.ui.functional.test.ts @@ -13,7 +13,7 @@ import * as os from 'os'; import * as path from 'path'; import * as sinon from 'sinon'; import { Disposable } from 'vscode'; -import { LocalZMQKernel } from '../../../client/common/experimentGroups'; +import { LocalZMQKernel } from '../../../client/common/experiments/experimentGroups'; import { EXTENSION_ROOT_DIR } from '../../../client/constants'; import { retryIfFail as retryIfFailOriginal } from '../../common'; import { mockedVSCodeNamespaces } from '../../vscode-mock'; diff --git a/src/test/datascience/variableexplorer.functional.test.tsx b/src/test/datascience/variableexplorer.functional.test.tsx index ebb38f1123d3..bb5fdc0e9856 100644 --- a/src/test/datascience/variableexplorer.functional.test.tsx +++ b/src/test/datascience/variableexplorer.functional.test.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import * as AdazzleReactDataGrid from 'react-data-grid'; import { Disposable } from 'vscode'; -import { RunByLine } from '../../client/common/experimentGroups'; +import { RunByLine } from '../../client/common/experiments/experimentGroups'; import { InteractiveWindowMessages } from '../../client/datascience/interactive-common/interactiveWindowTypes'; import { IJupyterVariable } from '../../client/datascience/types'; import { DataScienceIocContainer } from './dataScienceIocContainer'; diff --git a/src/test/debugger/attach.ptvsd.test.ts b/src/test/debugger/attach.ptvsd.test.ts index 0be2a3801c87..7c79de45c230 100644 --- a/src/test/debugger/attach.ptvsd.test.ts +++ b/src/test/debugger/attach.ptvsd.test.ts @@ -13,7 +13,7 @@ import { DebugClient } from 'vscode-debugadapter-testsupport'; import { IDocumentManager, IWorkspaceService } from '../../client/common/application/types'; import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; -import { DebugAdapterNewPtvsd } from '../../client/common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../client/common/experiments/experimentGroups'; import { IS_WINDOWS } from '../../client/common/platform/constants'; import { IPlatformService } from '../../client/common/platform/types'; import { IConfigurationService, IExperimentsManager } from '../../client/common/types'; diff --git a/src/test/debugger/extension/adapter/factory.unit.test.ts b/src/test/debugger/extension/adapter/factory.unit.test.ts index e9e394db4c7d..7254bc211252 100644 --- a/src/test/debugger/extension/adapter/factory.unit.test.ts +++ b/src/test/debugger/extension/adapter/factory.unit.test.ts @@ -17,7 +17,7 @@ import { ApplicationShell } from '../../../../client/common/application/applicat import { IApplicationShell } from '../../../../client/common/application/types'; import { ConfigurationService } from '../../../../client/common/configuration/service'; import { CryptoUtils } from '../../../../client/common/crypto'; -import { DebugAdapterNewPtvsd } from '../../../../client/common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { HttpClient } from '../../../../client/common/net/httpClient'; import { PersistentStateFactory } from '../../../../client/common/persistentState'; diff --git a/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts b/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts index 0fe67c70b12d..33e3b7f49a01 100644 --- a/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts +++ b/src/test/debugger/extension/adapter/outdatedDebuggerPrompt.unit.test.ts @@ -12,7 +12,7 @@ import { ApplicationShell } from '../../../../client/common/application/applicat import { IApplicationShell } from '../../../../client/common/application/types'; import { ConfigurationService } from '../../../../client/common/configuration/service'; import { CryptoUtils } from '../../../../client/common/crypto'; -import { DebugAdapterNewPtvsd } from '../../../../client/common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { BrowserService } from '../../../../client/common/net/browser'; import { HttpClient } from '../../../../client/common/net/httpClient'; diff --git a/src/test/debugger/extension/configuration/resolvers/attach.unit.test.ts b/src/test/debugger/extension/configuration/resolvers/attach.unit.test.ts index a36aaf374a25..de7c21c5cef1 100644 --- a/src/test/debugger/extension/configuration/resolvers/attach.unit.test.ts +++ b/src/test/debugger/extension/configuration/resolvers/attach.unit.test.ts @@ -10,7 +10,7 @@ import * as TypeMoq from 'typemoq'; import { DebugConfiguration, DebugConfigurationProvider, TextDocument, TextEditor, Uri, WorkspaceFolder } from 'vscode'; import { IDocumentManager, IWorkspaceService } from '../../../../../client/common/application/types'; import { PYTHON_LANGUAGE } from '../../../../../client/common/constants'; -import { DebugAdapterNewPtvsd } from '../../../../../client/common/experimentGroups'; +import { DebugAdapterNewPtvsd } from '../../../../../client/common/experiments/experimentGroups'; import { IFileSystem, IPlatformService } from '../../../../../client/common/platform/types'; import { IConfigurationService, IExperimentsManager } from '../../../../../client/common/types'; import { Diagnostics } from '../../../../../client/common/utils/localize'; diff --git a/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts b/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts index 568b80822a97..f50f807c732a 100644 --- a/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts +++ b/src/test/debugger/extension/configuration/resolvers/launchConfigExperiments.unit.test.ts @@ -10,7 +10,7 @@ import { instance, mock, spy, when } from 'ts-mockito'; import { ApplicationEnvironment } from '../../../../../client/common/application/applicationEnvironment'; import { ConfigurationService } from '../../../../../client/common/configuration/service'; import { CryptoUtils } from '../../../../../client/common/crypto'; -import { DebugAdapterNewPtvsd, WebAppReload } from '../../../../../client/common/experimentGroups'; +import { DebugAdapterNewPtvsd, WebAppReload } from '../../../../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../../../../client/common/experiments/manager'; import { HttpClient } from '../../../../../client/common/net/httpClient'; import { PersistentStateFactory } from '../../../../../client/common/persistentState'; diff --git a/src/test/interpreters/autoSelection/rules/settings.unit.test.ts b/src/test/interpreters/autoSelection/rules/settings.unit.test.ts index 21d877c14330..6b9bb5af5190 100644 --- a/src/test/interpreters/autoSelection/rules/settings.unit.test.ts +++ b/src/test/interpreters/autoSelection/rules/settings.unit.test.ts @@ -9,7 +9,7 @@ import { expect } from 'chai'; import { anything, instance, mock, when } from 'ts-mockito'; import { IWorkspaceService } from '../../../../client/common/application/types'; import { WorkspaceService } from '../../../../client/common/application/workspace'; -import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { InterpreterPathService } from '../../../../client/common/interpreterPathService'; import { PersistentState, PersistentStateFactory } from '../../../../client/common/persistentState'; diff --git a/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts b/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts index 87786ddda735..97d809fbc47e 100644 --- a/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts +++ b/src/test/interpreters/autoSelection/rules/workspaceEnv.unit.test.ts @@ -13,7 +13,7 @@ import * as typemoq from 'typemoq'; import { Uri, WorkspaceFolder } from 'vscode'; import { IWorkspaceService } from '../../../../client/common/application/types'; import { WorkspaceService } from '../../../../client/common/application/workspace'; -import { DeprecatePythonPath } from '../../../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../../../client/common/experiments/manager'; import { InterpreterPathService } from '../../../../client/common/interpreterPathService'; import { PersistentState, PersistentStateFactory } from '../../../../client/common/persistentState'; diff --git a/src/test/interpreters/interpreterService.unit.test.ts b/src/test/interpreters/interpreterService.unit.test.ts index 48b224666585..8cad13c1ef54 100644 --- a/src/test/interpreters/interpreterService.unit.test.ts +++ b/src/test/interpreters/interpreterService.unit.test.ts @@ -14,7 +14,7 @@ import { SemVer } from 'semver'; import * as TypeMoq from 'typemoq'; import { ConfigurationTarget, Disposable, TextDocument, TextEditor, Uri, WorkspaceConfiguration } from 'vscode'; import { IDocumentManager, IWorkspaceService } from '../../client/common/application/types'; -import { DeprecatePythonPath } from '../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../client/common/experiments/experimentGroups'; import { getArchitectureDisplayName } from '../../client/common/platform/registry'; import { IFileSystem } from '../../client/common/platform/types'; import { IPythonExecutionFactory, IPythonExecutionService } from '../../client/common/process/types'; diff --git a/src/test/interpreters/pythonPathUpdaterFactory.unit.test.ts b/src/test/interpreters/pythonPathUpdaterFactory.unit.test.ts index e59e379cbc34..91e511b4d09b 100644 --- a/src/test/interpreters/pythonPathUpdaterFactory.unit.test.ts +++ b/src/test/interpreters/pythonPathUpdaterFactory.unit.test.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as TypeMoq from 'typemoq'; import { ConfigurationTarget, Uri, WorkspaceConfiguration } from 'vscode'; import { IWorkspaceService } from '../../client/common/application/types'; -import { DeprecatePythonPath } from '../../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../../client/common/experiments/experimentGroups'; import { IExperimentsManager, IInterpreterPathService } from '../../client/common/types'; import { PythonPathUpdaterServiceFactory } from '../../client/interpreter/configuration/pythonPathUpdaterServiceFactory'; import { IPythonPathUpdaterServiceFactory } from '../../client/interpreter/configuration/types'; diff --git a/src/test/startupTelemetry.unit.test.ts b/src/test/startupTelemetry.unit.test.ts index 828a85a000ff..2dfdbec2ecc2 100644 --- a/src/test/startupTelemetry.unit.test.ts +++ b/src/test/startupTelemetry.unit.test.ts @@ -7,7 +7,7 @@ import { expect } from 'chai'; import * as TypeMoq from 'typemoq'; import { Uri, WorkspaceConfiguration } from 'vscode'; import { IWorkspaceService } from '../client/common/application/types'; -import { DeprecatePythonPath } from '../client/common/experimentGroups'; +import { DeprecatePythonPath } from '../client/common/experiments/experimentGroups'; import { IExperimentsManager, IInterpreterPathService } from '../client/common/types'; import { IServiceContainer } from '../client/ioc/types'; import { hasUserDefinedPythonPath } from '../client/startupTelemetry'; diff --git a/src/test/testing/main.unit.test.ts b/src/test/testing/main.unit.test.ts index 1cbea4fddcb2..b9b5ceb6deae 100644 --- a/src/test/testing/main.unit.test.ts +++ b/src/test/testing/main.unit.test.ts @@ -8,7 +8,7 @@ import { anything, instance, mock, verify, when } from 'ts-mockito'; import { Disposable } from 'vscode'; import { CommandManager } from '../../client/common/application/commandManager'; import { ICommandManager } from '../../client/common/application/types'; -import { AlwaysDisplayTestExplorerGroups } from '../../client/common/experimentGroups'; +import { AlwaysDisplayTestExplorerGroups } from '../../client/common/experiments/experimentGroups'; import { ExperimentsManager } from '../../client/common/experiments/manager'; import { IDisposableRegistry, IExperimentsManager } from '../../client/common/types'; import { ServiceContainer } from '../../client/ioc/container'; From 3271dc73a23463473157cdf158ab598a41548396 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Mon, 25 May 2020 14:27:34 -0700 Subject: [PATCH 06/25] Move experiments.unit.tests.ts -> experiments/ --- .../manager.unit.test.ts} | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) rename src/test/common/{experiments.unit.test.ts => experiments/manager.unit.test.ts} (97%) diff --git a/src/test/common/experiments.unit.test.ts b/src/test/common/experiments/manager.unit.test.ts similarity index 97% rename from src/test/common/experiments.unit.test.ts rename to src/test/common/experiments/manager.unit.test.ts index 14b03b08fb70..0243a12b991b 100644 --- a/src/test/common/experiments.unit.test.ts +++ b/src/test/common/experiments/manager.unit.test.ts @@ -9,12 +9,12 @@ import { assert, expect } from 'chai'; import * as sinon from 'sinon'; import { anything, instance, mock, verify, when } from 'ts-mockito'; import * as TypeMoq from 'typemoq'; -import { ApplicationEnvironment } from '../../client/common/application/applicationEnvironment'; -import { IApplicationEnvironment } from '../../client/common/application/types'; -import { PythonSettings } from '../../client/common/configSettings'; -import { ConfigurationService } from '../../client/common/configuration/service'; -import { CryptoUtils } from '../../client/common/crypto'; -import { NativeNotebook } from '../../client/common/experiments/experimentGroups'; +import { ApplicationEnvironment } from '../../../client/common/application/applicationEnvironment'; +import { IApplicationEnvironment } from '../../../client/common/application/types'; +import { PythonSettings } from '../../../client/common/configSettings'; +import { ConfigurationService } from '../../../client/common/configuration/service'; +import { CryptoUtils } from '../../../client/common/crypto'; +import { NativeNotebook } from '../../../client/common/experiments/experimentGroups'; import { configUri, downloadedExperimentStorageKey, @@ -22,11 +22,11 @@ import { experimentStorageKey, isDownloadedStorageValidKey, oldExperimentSalts -} from '../../client/common/experiments/manager'; -import { HttpClient } from '../../client/common/net/httpClient'; -import { PersistentStateFactory } from '../../client/common/persistentState'; -import { FileSystem } from '../../client/common/platform/fileSystem'; -import { IFileSystem } from '../../client/common/platform/types'; +} from '../../../client/common/experiments/manager'; +import { HttpClient } from '../../../client/common/net/httpClient'; +import { PersistentStateFactory } from '../../../client/common/persistentState'; +import { FileSystem } from '../../../client/common/platform/fileSystem'; +import { IFileSystem } from '../../../client/common/platform/types'; import { ICryptoUtils, IExperiments, @@ -34,10 +34,10 @@ import { IOutputChannel, IPersistentState, IPersistentStateFactory -} from '../../client/common/types'; -import { createDeferred, createDeferredFromPromise } from '../../client/common/utils/async'; -import { sleep } from '../common'; -import { noop } from '../core'; +} from '../../../client/common/types'; +import { createDeferred, createDeferredFromPromise } from '../../../client/common/utils/async'; +import { sleep } from '../../common'; +import { noop } from '../../core'; // tslint:disable: max-func-body-length From e500572dc7c2f4d82a890eaf3a802b7c41d61f04 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 26 May 2020 15:51:15 -0700 Subject: [PATCH 07/25] Commit new files --- src/client/common/experiments/service.ts | 56 +++++++++++++++++++ src/client/common/experiments/telemetry.ts | 23 ++++++++ .../common/experiments/service.unit.test.ts | 4 ++ .../common/experiments/telemetry.unit.test.ts | 4 ++ 4 files changed, 87 insertions(+) create mode 100644 src/client/common/experiments/service.ts create mode 100644 src/client/common/experiments/telemetry.ts create mode 100644 src/test/common/experiments/service.unit.test.ts create mode 100644 src/test/common/experiments/telemetry.unit.test.ts diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts new file mode 100644 index 000000000000..d65e1f2f14b1 --- /dev/null +++ b/src/client/common/experiments/service.ts @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { inject, named } from 'inversify'; +import { Memento } from 'vscode'; +import { getExperimentationService, IExperimentationService, TargetPopulation } from 'vscode-tas-client'; +import { PVSC_EXTENSION_ID } from '../constants'; +import { GLOBAL_MEMENTO, IConfigurationService, IExperimentService, IExtensions, IMemento } from '../types'; +import { ExperimentationTelemetry } from './telemetry'; + +export class ExperimentService implements IExperimentService { + private readonly experimentationService?: IExperimentationService; + + constructor( + @inject(IConfigurationService) readonly configurationService: IConfigurationService, + @inject(IExtensions) readonly extensions: IExtensions, + @inject(IMemento) @named(GLOBAL_MEMENTO) readonly globalState: Memento + ) { + const settings = configurationService.getSettings(undefined); + const enabled = settings.experiments.enabled; + + // Don't initialize experiment service if the extension's experiments setting is disabled. + if (!enabled) { + return; + } + + const extension = extensions.getExtension(PVSC_EXTENSION_ID)!; + const version = extension.packageJSON.version!; + + let targetPopulation: TargetPopulation; + + if (/dev/gi.test(version)) { + targetPopulation = TargetPopulation.Insiders; + } else { + targetPopulation = TargetPopulation.Public; + } + + const telemetryReporter = new ExperimentationTelemetry(); + + this.experimentationService = getExperimentationService( + PVSC_EXTENSION_ID, + version, + targetPopulation, + telemetryReporter, + globalState + ); + } + + public async inExperiment(flight: string): Promise { + if (!this.experimentationService) { + return false; + } + + return this.experimentationService.isCachedFlightEnabled(flight); + } +} diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts new file mode 100644 index 000000000000..5352209c31de --- /dev/null +++ b/src/client/common/experiments/telemetry.ts @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { IExperimentationTelemetry } from 'vscode-tas-client'; +import { sendTelemetryEvent } from '../../telemetry'; + +export class ExperimentationTelemetry implements IExperimentationTelemetry { + private readonly sharedProperties: { [key: string]: string } = {}; + + public setSharedProperty(name: string, value: string): void { + this.sharedProperties[name] = value; + } + + public postEvent(eventName: string, props: Map): void { + // Add shared properties to telemetry props (we may overwrite existing ones). + for (const [key, value] of Object.entries(this.sharedProperties)) { + props.set(key, value); + } + + // tslint:disable-next-line: no-any + sendTelemetryEvent(eventName as any, undefined, props); + } +} diff --git a/src/test/common/experiments/service.unit.test.ts b/src/test/common/experiments/service.unit.test.ts new file mode 100644 index 000000000000..f72bcf8a55f6 --- /dev/null +++ b/src/test/common/experiments/service.unit.test.ts @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +suite('Experimentation service', () => {}); diff --git a/src/test/common/experiments/telemetry.unit.test.ts b/src/test/common/experiments/telemetry.unit.test.ts new file mode 100644 index 000000000000..e37f9ced37da --- /dev/null +++ b/src/test/common/experiments/telemetry.unit.test.ts @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +suite('Experimentation telemetry', () => {}); From 3def3dd4575d03a31b39c1f1556ecaa8329dc157 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 26 May 2020 16:02:32 -0700 Subject: [PATCH 08/25] Merge gone sideways --- .../common/experiments/experimentGroups.ts | 104 ------------------ 1 file changed, 104 deletions(-) delete mode 100644 src/client/common/experiments/experimentGroups.ts diff --git a/src/client/common/experiments/experimentGroups.ts b/src/client/common/experiments/experimentGroups.ts deleted file mode 100644 index a1bb54269880..000000000000 --- a/src/client/common/experiments/experimentGroups.ts +++ /dev/null @@ -1,104 +0,0 @@ -export const LSControl = 'LS - control'; -export const LSEnabled = 'LS - enabled'; - -// Experiment to check whether to always display the test explorer. -export enum AlwaysDisplayTestExplorerGroups { - control = 'AlwaysDisplayTestExplorer - control', - experiment = 'AlwaysDisplayTestExplorer - experiment' -} - -// Experiment to check whether to show "Extension Survey prompt" or not. -export enum ShowExtensionSurveyPrompt { - control = 'ShowExtensionSurveyPrompt - control', - enabled = 'ShowExtensionSurveyPrompt - enabled' -} - -// Experiment to check whether the extension should use the new VS Code debug adapter API. -export enum DebugAdapterDescriptorFactory { - control = 'DebugAdapterFactory - control', - experiment = 'DebugAdapterFactory - experiment' -} - -// Experiment to check whether the ptvsd launcher should use pre-installed ptvsd wheels for debugging. -export enum DebugAdapterNewPtvsd { - control = 'PtvsdWheels37 - control', - experiment = 'PtvsdWheels37 - experiment' -} - -// Experiment to check whether to enable re-load for web apps while debugging. -export enum WebAppReload { - control = 'Reload - control', - experiment = 'Reload - experiment' -} - -/** - * Slow roll out, to test use of local web server for serving content in the Native Notebook editor. - * - * @export - * @enum {string} - */ -export enum WebHostNotebook { - control = 'WebHostNotebook - control', - experiment = 'WebHostNotebook - experiment' -} - -// Experiment to use a local ZMQ kernel connection as opposed to starting a Jupyter server locally -export enum LocalZMQKernel { - control = 'LocalZMQKernel - control', - experiment = 'LocalZMQKernel - experiment' -} - -// Experiment to use VSC Notebook Implementation -export enum NativeNotebook { - control = 'NativeNotebook - control', - experiment = 'NativeNotebook - experiment' -} - -// Experiment for supporting run by line in data science notebooks -export enum RunByLine { - control = 'RunByLine - control', - experiment = 'RunByLine - experiment' -} - -/** - * Experiment to check whether to to use a terminal to generate the environment variables of activated environments. - * - * @export - * @enum {number} - */ -export enum UseTerminalToGetActivatedEnvVars { - control = 'UseTerminalToGetActivatedEnvVars - control', - experiment = 'UseTerminalToGetActivatedEnvVars - experiment' -} - -// Dummy experiment added to validate metrics of A/B testing -export enum ValidateABTesting { - control = 'AA_testing - control', - experiment = 'AA_testing - experiment' -} - -// Collect language server request timings. -export enum CollectLSRequestTiming { - control = 'CollectLSRequestTiming - control', - experiment = 'CollectLSRequestTiming - experiment' -} - -// Collect Node language server request timings. -export enum CollectNodeLSRequestTiming { - control = 'CollectNodeLSRequestTiming - control', - experiment = 'CollectNodeLSRequestTiming - experiment' -} - -// Determine if ipywidgets is enabled or not -export enum EnableIPyWidgets { - control = 'EnableIPyWidgets - control', - experiment = 'EnableIPyWidgets - experiment' -} - -/* - * Experiment to check whether the extension should deprecate `python.pythonPath` setting - */ -export enum DeprecatePythonPath { - control = 'DeprecatePythonPath - control', - experiment = 'DeprecatePythonPath - experiment' -} From 821badaa43ab9edea4fdca2b410df164c4466adb Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 26 May 2020 16:03:26 -0700 Subject: [PATCH 09/25] Add types --- src/client/common/types.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/client/common/types.ts b/src/client/common/types.ts index 57c2cee24b85..8186849a7c25 100644 --- a/src/client/common/types.ts +++ b/src/client/common/types.ts @@ -618,6 +618,14 @@ export interface IExperimentsManager { sendTelemetryIfInExperiment(experimentName: string): void; } +/** + * Experiment service leveraging VS Code's experiment framework. + */ +export const IExperimentService = Symbol('IExperimentService'); +export interface IExperimentService { + inExperiment(experimentName: string): Promise; +} + export type InterpreterConfigurationScope = { uri: Resource; configTarget: ConfigurationTarget }; export type InspectInterpreterSettingType = { globalValue?: string; From 168c028a58979078ebbc835e78e3f3af0d0aef12 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 26 May 2020 17:19:55 -0700 Subject: [PATCH 10/25] Add opt in/out handling --- src/client/common/experiments/service.ts | 55 +++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts index d65e1f2f14b1..76a97cd8fe34 100644 --- a/src/client/common/experiments/service.ts +++ b/src/client/common/experiments/service.ts @@ -4,22 +4,47 @@ import { inject, named } from 'inversify'; import { Memento } from 'vscode'; import { getExperimentationService, IExperimentationService, TargetPopulation } from 'vscode-tas-client'; +import { sendTelemetryEvent } from '../../telemetry'; +import { EventName } from '../../telemetry/constants'; import { PVSC_EXTENSION_ID } from '../constants'; -import { GLOBAL_MEMENTO, IConfigurationService, IExperimentService, IExtensions, IMemento } from '../types'; +import { + GLOBAL_MEMENTO, + IConfigurationService, + IExperimentService, + IExtensions, + IMemento, + IPythonSettings +} from '../types'; import { ExperimentationTelemetry } from './telemetry'; export class ExperimentService implements IExperimentService { + /** + * Experiments the user requested to opt into manually. + */ + public _optInto: string[] = []; + /** + * Experiments the user requested to opt out from manually. + */ + public _optOutFrom: string[] = []; + private readonly experimentationService?: IExperimentationService; + private settings!: IPythonSettings; constructor( @inject(IConfigurationService) readonly configurationService: IConfigurationService, @inject(IExtensions) readonly extensions: IExtensions, @inject(IMemento) @named(GLOBAL_MEMENTO) readonly globalState: Memento ) { - const settings = configurationService.getSettings(undefined); - const enabled = settings.experiments.enabled; + this.settings = configurationService.getSettings(undefined); + + // Users can only opt in or out of experiment groups, not control groups. + const optInto = this.settings.experiments.optInto; + const optOutFrom = this.settings.experiments.optOutFrom; + this._optInto = optInto.filter((exp) => exp.endsWith('control')); + this._optOutFrom = optOutFrom.filter((exp) => exp.endsWith('control')); - // Don't initialize experiment service if the extension's experiments setting is disabled. + // Don't initialize the experiment service if the extension's experiments setting is disabled. + const enabled = this.settings.experiments.enabled; if (!enabled) { return; } @@ -51,6 +76,26 @@ export class ExperimentService implements IExperimentService { return false; } - return this.experimentationService.isCachedFlightEnabled(flight); + const isFlightEnabled = this.experimentationService.isCachedFlightEnabled(flight); + + // Currently the service doesn't support opting in and out of experiments, + // so we need to perform these checks and send the corresponding telemetry manually. + if (this._optOutFrom.includes('All') || this._optOutFrom.includes(flight)) { + sendTelemetryEvent(EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, undefined, { + expNameOptedOutOf: flight + }); + + return false; + } + + if (this._optInto.includes('All') || this._optInto.includes(flight)) { + sendTelemetryEvent(EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, undefined, { + expNameOptedInto: flight + }); + + return true; + } + + return isFlightEnabled; } } From cd37cba6ecbf4586953396d9d89f97d972cd2391 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 26 May 2020 17:20:19 -0700 Subject: [PATCH 11/25] Activation (service registry) --- src/client/common/serviceRegistry.ts | 4 +++- src/test/common/installer.test.ts | 3 +++ src/test/common/moduleInstaller.test.ts | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/client/common/serviceRegistry.ts b/src/client/common/serviceRegistry.ts index 87ac23f8229a..444b666c70e3 100644 --- a/src/client/common/serviceRegistry.ts +++ b/src/client/common/serviceRegistry.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. import { IExtensionSingleActivationService } from '../activation/types'; -import { IFileDownloader, IHttpClient, IInterpreterPathService } from '../common/types'; +import { IExperimentService, IFileDownloader, IHttpClient, IInterpreterPathService } from '../common/types'; import { LiveShareApi } from '../datascience/liveshare/liveshare'; import { INotebookExecutionLogger } from '../datascience/types'; import { IServiceManager } from '../ioc/types'; @@ -42,6 +42,7 @@ import { ConfigurationService } from './configuration/service'; import { CryptoUtils } from './crypto'; import { EditorUtils } from './editor'; import { ExperimentsManager } from './experiments/manager'; +import { ExperimentService } from './experiments/service'; import { FeatureDeprecationManager } from './featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, @@ -149,6 +150,7 @@ export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(ILiveShareApi, LiveShareApi); serviceManager.addSingleton(ICryptoUtils, CryptoUtils); serviceManager.addSingleton(IExperimentsManager, ExperimentsManager); + serviceManager.addSingleton(IExperimentService, ExperimentService); serviceManager.addSingleton(ITerminalHelper, TerminalHelper); serviceManager.addSingleton( diff --git a/src/test/common/installer.test.ts b/src/test/common/installer.test.ts index 2bd92b8bba5e..74aef58ebce5 100644 --- a/src/test/common/installer.test.ts +++ b/src/test/common/installer.test.ts @@ -30,6 +30,7 @@ import { ConfigurationService } from '../../client/common/configuration/service' import { CryptoUtils } from '../../client/common/crypto'; import { EditorUtils } from '../../client/common/editor'; import { ExperimentsManager } from '../../client/common/experiments/manager'; +import { ExperimentService } from '../../client/common/experiments/service'; import { FeatureDeprecationManager } from '../../client/common/featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, @@ -102,6 +103,7 @@ import { ICryptoUtils, ICurrentProcess, IEditorUtils, + IExperimentService, IExperimentsManager, IExtensions, IFeatureDeprecationManager, @@ -253,6 +255,7 @@ suite('Installer', () => { ioc.serviceManager.addSingleton(ILiveShareApi, LiveShareApi); ioc.serviceManager.addSingleton(ICryptoUtils, CryptoUtils); ioc.serviceManager.addSingleton(IExperimentsManager, ExperimentsManager); + ioc.serviceManager.addSingleton(IExperimentService, ExperimentService); ioc.serviceManager.addSingleton(ITerminalHelper, TerminalHelper); ioc.serviceManager.addSingleton( diff --git a/src/test/common/moduleInstaller.test.ts b/src/test/common/moduleInstaller.test.ts index 9a84713e3e89..ea17d493af03 100644 --- a/src/test/common/moduleInstaller.test.ts +++ b/src/test/common/moduleInstaller.test.ts @@ -37,6 +37,7 @@ import { ConfigurationService } from '../../client/common/configuration/service' import { CryptoUtils } from '../../client/common/crypto'; import { EditorUtils } from '../../client/common/editor'; import { ExperimentsManager } from '../../client/common/experiments/manager'; +import { ExperimentService } from '../../client/common/experiments/service'; import { FeatureDeprecationManager } from '../../client/common/featureDeprecationManager'; import { ExtensionInsidersDailyChannelRule, @@ -100,6 +101,7 @@ import { ICryptoUtils, ICurrentProcess, IEditorUtils, + IExperimentService, IExperimentsManager, IExtensions, IFeatureDeprecationManager, @@ -263,6 +265,7 @@ suite('Module Installer', () => { ioc.serviceManager.addSingleton(ILiveShareApi, LiveShareApi); ioc.serviceManager.addSingleton(ICryptoUtils, CryptoUtils); ioc.serviceManager.addSingleton(IExperimentsManager, ExperimentsManager); + ioc.serviceManager.addSingleton(IExperimentService, ExperimentService); ioc.serviceManager.addSingleton( ITerminalActivationCommandProvider, From 7a374738e50031e14b21291c0cc31efbb7b730d9 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 26 May 2020 17:21:37 -0700 Subject: [PATCH 12/25] Don't pin tas-client to one version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eead9154c020..bccb329ccc50 100644 --- a/package.json +++ b/package.json @@ -3060,7 +3060,7 @@ "vscode-languageclient": "^6.2.0-next.2", "vscode-languageserver": "^6.2.0-next.2", "vscode-languageserver-protocol": "^3.16.0-next.2", - "vscode-tas-client": "0.0.757", + "vscode-tas-client": "^0.0.757", "vsls": "^0.3.1291", "winreg": "^1.2.4", "winston": "^3.2.1", From 79f5a24fd6de52139542bc4e29a1472b09bca202 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Wed, 27 May 2020 14:38:31 -0700 Subject: [PATCH 13/25] Unit tests + fixes --- src/client/common/experiments/service.ts | 8 +- src/client/common/experiments/telemetry.ts | 11 +- .../common/experiments/service.unit.test.ts | 295 +++++++++++++++++- .../common/experiments/telemetry.unit.test.ts | 63 +++- 4 files changed, 367 insertions(+), 10 deletions(-) diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts index 76a97cd8fe34..865140c0f745 100644 --- a/src/client/common/experiments/service.ts +++ b/src/client/common/experiments/service.ts @@ -40,8 +40,8 @@ export class ExperimentService implements IExperimentService { // Users can only opt in or out of experiment groups, not control groups. const optInto = this.settings.experiments.optInto; const optOutFrom = this.settings.experiments.optOutFrom; - this._optInto = optInto.filter((exp) => exp.endsWith('control')); - this._optOutFrom = optOutFrom.filter((exp) => exp.endsWith('control')); + this._optInto = optInto.filter((exp) => !exp.endsWith('control')); + this._optOutFrom = optOutFrom.filter((exp) => !exp.endsWith('control')); // Don't initialize the experiment service if the extension's experiments setting is disabled. const enabled = this.settings.experiments.enabled; @@ -76,8 +76,6 @@ export class ExperimentService implements IExperimentService { return false; } - const isFlightEnabled = this.experimentationService.isCachedFlightEnabled(flight); - // Currently the service doesn't support opting in and out of experiments, // so we need to perform these checks and send the corresponding telemetry manually. if (this._optOutFrom.includes('All') || this._optOutFrom.includes(flight)) { @@ -96,6 +94,6 @@ export class ExperimentService implements IExperimentService { return true; } - return isFlightEnabled; + return this.experimentationService.isCachedFlightEnabled(flight); } } diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index 5352209c31de..fd35231dca54 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -11,13 +11,18 @@ export class ExperimentationTelemetry implements IExperimentationTelemetry { this.sharedProperties[name] = value; } - public postEvent(eventName: string, props: Map): void { + public postEvent(eventName: string, properties: Map): void { // Add shared properties to telemetry props (we may overwrite existing ones). for (const [key, value] of Object.entries(this.sharedProperties)) { - props.set(key, value); + properties.set(key, value); } + const formattedProperties: { [key: string]: string } = {}; + properties.forEach((value, key) => { + formattedProperties[key] = value; + }); + // tslint:disable-next-line: no-any - sendTelemetryEvent(eventName as any, undefined, props); + sendTelemetryEvent(eventName as any, undefined, formattedProperties); } } diff --git a/src/test/common/experiments/service.unit.test.ts b/src/test/common/experiments/service.unit.test.ts index f72bcf8a55f6..a016e9b72336 100644 --- a/src/test/common/experiments/service.unit.test.ts +++ b/src/test/common/experiments/service.unit.test.ts @@ -1,4 +1,297 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -suite('Experimentation service', () => {}); +import { assert } from 'chai'; +import * as sinon from 'sinon'; +import { instance, mock, when } from 'ts-mockito'; +import * as tasClient from 'vscode-tas-client'; +import { Extensions } from '../../../client/common/application/extensions'; +import { ConfigurationService } from '../../../client/common/configuration/service'; +import { PVSC_EXTENSION_ID } from '../../../client/common/constants'; +import { ExperimentService } from '../../../client/common/experiments/service'; +import { IConfigurationService, IExtensions } from '../../../client/common/types'; +import * as Telemetry from '../../../client/telemetry'; +import { EventName } from '../../../client/telemetry/constants'; +import { MockMemento } from '../../mocks/mementos'; + +// tslint:disable: no-unused-expression + +suite('Experimentation service', () => { + const extensionVersion = '1.2.3'; + + let configurationService: IConfigurationService; + let extensions: IExtensions; + let globalMemento: MockMemento; + + setup(() => { + configurationService = mock(ConfigurationService); + extensions = mock(Extensions); + globalMemento = new MockMemento(); + }); + + teardown(() => { + sinon.restore(); + }); + + function configureSettings(enabled: boolean, optInto: string[], optOutFrom: string[]) { + when(configurationService.getSettings(undefined)).thenReturn({ + experiments: { + enabled, + optInto, + optOutFrom + } + // tslint:disable-next-line: no-any + } as any); + } + + function configureExtensionVersion(version: string) { + when(extensions.getExtension(PVSC_EXTENSION_ID)).thenReturn({ + packageJSON: { version } + // tslint:disable-next-line: no-any + } as any); + } + + suite('Initialization', () => { + test('Instantiating a new ExperimentService should call methods from the experimentation framework', () => { + const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); + + configureSettings(true, [], []); + configureExtensionVersion(extensionVersion); + + new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + + sinon.assert.calledOnce(getExperimentationServiceStub); + }); + + test('Instantiating a new ExperimentService with the experiment settings being disabled should not call methods from the experimentation framework', () => { + const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); + + configureSettings(false, [], []); + configureExtensionVersion(extensionVersion); + + new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + + sinon.assert.notCalled(getExperimentationServiceStub); + }); + + test('Users with a release version of the extension should be in the Public target population', () => { + const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); + + configureSettings(true, [], []); + configureExtensionVersion(extensionVersion); + + new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + + sinon.assert.calledWithExactly( + getExperimentationServiceStub, + PVSC_EXTENSION_ID, + extensionVersion, + tasClient.TargetPopulation.Public, + sinon.match.any, + globalMemento + ); + }); + + test('Users with an Insiders version of the extension should be the Insiders target population', () => { + const version = '1.2.3-dev'; + const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); + + configureSettings(true, [], []); + configureExtensionVersion(version); + + new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + + sinon.assert.calledWithExactly( + getExperimentationServiceStub, + PVSC_EXTENSION_ID, + version, + tasClient.TargetPopulation.Insiders, + sinon.match.any, + globalMemento + ); + }); + + test('Users can only opt into experiment groups', () => { + sinon.stub(tasClient, 'getExperimentationService'); + + configureSettings(true, ['Foo - experiment', 'Bar - control'], []); + configureExtensionVersion(extensionVersion); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + + assert.deepEqual(experimentService._optInto, ['Foo - experiment']); + }); + + test('Users can only opt out of experiment groups', () => { + sinon.stub(tasClient, 'getExperimentationService'); + configureSettings(true, [], ['Foo - experiment', 'Bar - control']); + configureExtensionVersion(extensionVersion); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + + assert.deepEqual(experimentService._optOutFrom, ['Foo - experiment']); + }); + }); + + /** + * + when calling inExperiment with opt in and opt out empty it should return the value of isCachedFlightEnabled + * + when calling constructor with experiments disabled then inExperiment should return false + * + when calling inExperiment with opt out with all it should return false (check telemetry sent) + * + when calling inExperiment with exp name in opt out it should return false even if isCachedFlightEnabled return true (check telemetry sent) + * when calling inExperiment with opt in with all it should return true (check telemetry sent) + * when calling inExperiment with exp name in opt in it should return true even if isCachedFlightEnabled is false (check telemetry sent) + */ + + suite('In-experiment check', () => { + const experiment = 'Test Experiment - experiment'; + let isCachedFlightEnabledCalled = false; + let telemetryEvents: { eventName: string; properties: object }[] = []; + let sendTelemetryEventStub: sinon.SinonStub; + + setup(() => { + sendTelemetryEventStub = sinon + .stub(Telemetry, 'sendTelemetryEvent') + .callsFake((eventName: string, _, properties: object) => { + const telemetry = { eventName, properties }; + telemetryEvents.push(telemetry); + }); + + configureExtensionVersion(extensionVersion); + }); + + teardown(() => { + isCachedFlightEnabledCalled = false; + telemetryEvents = []; + }); + + function configureIsCachedFlightEnabledStub(result: boolean) { + sinon.stub(tasClient, 'getExperimentationService').returns({ + isCachedFlightEnabled: (_: string) => { + isCachedFlightEnabledCalled = true; + return Promise.resolve(result); + } + // tslint:disable-next-line: no-any + } as any); + } + + test('If the experiment setting is disabled, inExperiment should return false', async () => { + configureSettings(false, [], []); + configureIsCachedFlightEnabledStub(true); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + const result = await experimentService.inExperiment(experiment); + + assert.isFalse(result); + assert.isFalse(isCachedFlightEnabledCalled); + sinon.assert.notCalled(sendTelemetryEventStub); + }); + + test('If the opt-in and opt-out arrays are empty, return the value from the experimentation framework for a given experiment', async () => { + configureSettings(true, [], []); + configureIsCachedFlightEnabledStub(true); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + const result = await experimentService.inExperiment(experiment); + + assert.isTrue(result); + assert.isTrue(isCachedFlightEnabledCalled); + sinon.assert.notCalled(sendTelemetryEventStub); + }); + + test('If the opt-in setting contains "All", inExperiment should return true', async () => { + configureSettings(true, ['All'], []); + configureIsCachedFlightEnabledStub(false); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + const result = await experimentService.inExperiment(experiment); + + assert.isTrue(result); + assert.isFalse(isCachedFlightEnabledCalled); + assert.equal(telemetryEvents.length, 1); + assert.deepEqual(telemetryEvents[0], { + eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, + properties: { expNameOptedInto: experiment } + }); + }); + + test('If the opt-in setting contains the experiment name, inExperiment should return true', async () => { + configureSettings(true, [experiment], []); + configureIsCachedFlightEnabledStub(false); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + const result = await experimentService.inExperiment(experiment); + + assert.isTrue(result); + assert.isFalse(isCachedFlightEnabledCalled); + assert.equal(telemetryEvents.length, 1); + assert.deepEqual(telemetryEvents[0], { + eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, + properties: { expNameOptedInto: experiment } + }); + }); + + test('If the opt-out setting contains "All", inExperiment should return false', async () => { + configureSettings(true, [], ['All']); + configureIsCachedFlightEnabledStub(true); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + const result = await experimentService.inExperiment(experiment); + + assert.isFalse(result); + assert.isFalse(isCachedFlightEnabledCalled); + assert.equal(telemetryEvents.length, 1); + assert.deepEqual(telemetryEvents[0], { + eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, + properties: { expNameOptedOutOf: experiment } + }); + }); + + test('If the opt-out setting contains the experiment name, inExperiment should return false', async () => { + configureSettings(true, [], [experiment]); + configureIsCachedFlightEnabledStub(true); + + const experimentService = new ExperimentService( + instance(configurationService), + instance(extensions), + globalMemento + ); + const result = await experimentService.inExperiment(experiment); + + assert.isFalse(result); + assert.isFalse(isCachedFlightEnabledCalled); + assert.equal(telemetryEvents.length, 1); + assert.deepEqual(telemetryEvents[0], { + eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, + properties: { expNameOptedOutOf: experiment } + }); + }); + }); +}); diff --git a/src/test/common/experiments/telemetry.unit.test.ts b/src/test/common/experiments/telemetry.unit.test.ts index e37f9ced37da..aea549c6d858 100644 --- a/src/test/common/experiments/telemetry.unit.test.ts +++ b/src/test/common/experiments/telemetry.unit.test.ts @@ -1,4 +1,65 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import { assert } from 'chai'; +import * as sinon from 'sinon'; +import { ExperimentationTelemetry } from '../../../client/common/experiments/telemetry'; +import * as Telemetry from '../../../client/telemetry'; -suite('Experimentation telemetry', () => {}); +suite('Experimentation telemetry', () => { + const event = 'SomeEventName'; + + let telemetryEvents: { eventName: string; properties: object }[] = []; + let sendTelemetryEventStub: sinon.SinonStub; + let experimentTelemetry: ExperimentationTelemetry; + let eventProperties: Map; + + setup(() => { + sendTelemetryEventStub = sinon + .stub(Telemetry, 'sendTelemetryEvent') + .callsFake((eventName: string, _, properties: object) => { + const telemetry = { eventName, properties }; + telemetryEvents.push(telemetry); + }); + + eventProperties = new Map(); + eventProperties.set('foo', 'one'); + eventProperties.set('bar', 'two'); + + experimentTelemetry = new ExperimentationTelemetry(); + }); + + teardown(() => { + telemetryEvents = []; + sinon.restore(); + }); + + test('Calling postEvent should send a telemetry event', () => { + experimentTelemetry.postEvent(event, eventProperties); + + sinon.assert.calledOnce(sendTelemetryEventStub); + assert.equal(telemetryEvents.length, 1); + assert.deepEqual(telemetryEvents[0], { + eventName: event, + properties: { + foo: 'one', + bar: 'two' + } + }); + }); + + test('Shared properties should be sent in the telemetry event', () => { + const shared = { key: 'shared', value: 'three' }; + + experimentTelemetry.setSharedProperty(shared.key, shared.value); + experimentTelemetry.postEvent(event, eventProperties); + + assert.deepEqual(telemetryEvents[0], { + eventName: event, + properties: { + foo: 'one', + bar: 'two', + shared: 'three' + } + }); + }); +}); From d9ca2ca612ea25e76cfe8282808447b3e5c5213e Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Wed, 27 May 2020 16:16:18 -0700 Subject: [PATCH 14/25] Lol forgot to remove a comment + add headers --- src/client/common/experiments/telemetry.ts | 2 ++ src/test/common/experiments/service.unit.test.ts | 11 ++--------- src/test/common/experiments/telemetry.unit.test.ts | 3 +++ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index fd35231dca54..1efc5bda9982 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +'use strict'; + import { IExperimentationTelemetry } from 'vscode-tas-client'; import { sendTelemetryEvent } from '../../telemetry'; diff --git a/src/test/common/experiments/service.unit.test.ts b/src/test/common/experiments/service.unit.test.ts index a016e9b72336..47b3abd4ea53 100644 --- a/src/test/common/experiments/service.unit.test.ts +++ b/src/test/common/experiments/service.unit.test.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +'use strict'; + import { assert } from 'chai'; import * as sinon from 'sinon'; import { instance, mock, when } from 'ts-mockito'; @@ -141,15 +143,6 @@ suite('Experimentation service', () => { }); }); - /** - * + when calling inExperiment with opt in and opt out empty it should return the value of isCachedFlightEnabled - * + when calling constructor with experiments disabled then inExperiment should return false - * + when calling inExperiment with opt out with all it should return false (check telemetry sent) - * + when calling inExperiment with exp name in opt out it should return false even if isCachedFlightEnabled return true (check telemetry sent) - * when calling inExperiment with opt in with all it should return true (check telemetry sent) - * when calling inExperiment with exp name in opt in it should return true even if isCachedFlightEnabled is false (check telemetry sent) - */ - suite('In-experiment check', () => { const experiment = 'Test Experiment - experiment'; let isCachedFlightEnabledCalled = false; diff --git a/src/test/common/experiments/telemetry.unit.test.ts b/src/test/common/experiments/telemetry.unit.test.ts index aea549c6d858..21b8441e07fa 100644 --- a/src/test/common/experiments/telemetry.unit.test.ts +++ b/src/test/common/experiments/telemetry.unit.test.ts @@ -1,5 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + +'use strict'; + import { assert } from 'chai'; import * as sinon from 'sinon'; import { ExperimentationTelemetry } from '../../../client/common/experiments/telemetry'; From e73f68e02fe86f214ba6e81078ef6e05a4494343 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Wed, 27 May 2020 16:17:38 -0700 Subject: [PATCH 15/25] Forgot 'use strict' in service.ts --- src/client/common/experiments/service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts index 865140c0f745..634ad19f9b17 100644 --- a/src/client/common/experiments/service.ts +++ b/src/client/common/experiments/service.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +'use strict'; + import { inject, named } from 'inversify'; import { Memento } from 'vscode'; import { getExperimentationService, IExperimentationService, TargetPopulation } from 'vscode-tas-client'; From c3035068d95a3415e77db376d3cd47709d065f94 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 09:09:24 -0700 Subject: [PATCH 16/25] Use IApplicationEnvironment instead of IExtensions --- src/client/common/experiments/service.ts | 22 ++----- .../common/experiments/service.unit.test.ts | 66 +++++++++---------- 2 files changed, 39 insertions(+), 49 deletions(-) diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts index 634ad19f9b17..5ba4f0240618 100644 --- a/src/client/common/experiments/service.ts +++ b/src/client/common/experiments/service.ts @@ -8,15 +8,8 @@ import { Memento } from 'vscode'; import { getExperimentationService, IExperimentationService, TargetPopulation } from 'vscode-tas-client'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; -import { PVSC_EXTENSION_ID } from '../constants'; -import { - GLOBAL_MEMENTO, - IConfigurationService, - IExperimentService, - IExtensions, - IMemento, - IPythonSettings -} from '../types'; +import { IApplicationEnvironment } from '../application/types'; +import { GLOBAL_MEMENTO, IConfigurationService, IExperimentService, IMemento, IPythonSettings } from '../types'; import { ExperimentationTelemetry } from './telemetry'; export class ExperimentService implements IExperimentService { @@ -34,7 +27,7 @@ export class ExperimentService implements IExperimentService { constructor( @inject(IConfigurationService) readonly configurationService: IConfigurationService, - @inject(IExtensions) readonly extensions: IExtensions, + @inject(IApplicationEnvironment) private readonly appEnvironment: IApplicationEnvironment, @inject(IMemento) @named(GLOBAL_MEMENTO) readonly globalState: Memento ) { this.settings = configurationService.getSettings(undefined); @@ -51,12 +44,9 @@ export class ExperimentService implements IExperimentService { return; } - const extension = extensions.getExtension(PVSC_EXTENSION_ID)!; - const version = extension.packageJSON.version!; - let targetPopulation: TargetPopulation; - if (/dev/gi.test(version)) { + if (this.appEnvironment.channel === 'insiders') { targetPopulation = TargetPopulation.Insiders; } else { targetPopulation = TargetPopulation.Public; @@ -65,8 +55,8 @@ export class ExperimentService implements IExperimentService { const telemetryReporter = new ExperimentationTelemetry(); this.experimentationService = getExperimentationService( - PVSC_EXTENSION_ID, - version, + this.appEnvironment.extensionName, + this.appEnvironment.packageJson.version!, targetPopulation, telemetryReporter, globalState diff --git a/src/test/common/experiments/service.unit.test.ts b/src/test/common/experiments/service.unit.test.ts index 47b3abd4ea53..fc36ac85aa6b 100644 --- a/src/test/common/experiments/service.unit.test.ts +++ b/src/test/common/experiments/service.unit.test.ts @@ -7,13 +7,14 @@ import { assert } from 'chai'; import * as sinon from 'sinon'; import { instance, mock, when } from 'ts-mockito'; import * as tasClient from 'vscode-tas-client'; -import { Extensions } from '../../../client/common/application/extensions'; +import { ApplicationEnvironment } from '../../../client/common/application/applicationEnvironment'; +import { Channel, IApplicationEnvironment } from '../../../client/common/application/types'; import { ConfigurationService } from '../../../client/common/configuration/service'; -import { PVSC_EXTENSION_ID } from '../../../client/common/constants'; import { ExperimentService } from '../../../client/common/experiments/service'; -import { IConfigurationService, IExtensions } from '../../../client/common/types'; +import { IConfigurationService } from '../../../client/common/types'; import * as Telemetry from '../../../client/telemetry'; import { EventName } from '../../../client/telemetry/constants'; +import { PVSC_EXTENSION_ID_FOR_TESTS } from '../../constants'; import { MockMemento } from '../../mocks/mementos'; // tslint:disable: no-unused-expression @@ -22,12 +23,12 @@ suite('Experimentation service', () => { const extensionVersion = '1.2.3'; let configurationService: IConfigurationService; - let extensions: IExtensions; + let appEnvironment: IApplicationEnvironment; let globalMemento: MockMemento; setup(() => { configurationService = mock(ConfigurationService); - extensions = mock(Extensions); + appEnvironment = mock(ApplicationEnvironment); globalMemento = new MockMemento(); }); @@ -46,11 +47,10 @@ suite('Experimentation service', () => { } as any); } - function configureExtensionVersion(version: string) { - when(extensions.getExtension(PVSC_EXTENSION_ID)).thenReturn({ - packageJSON: { version } - // tslint:disable-next-line: no-any - } as any); + function configureApplicationEnvironment(channel: Channel, version: string) { + when(appEnvironment.channel).thenReturn(channel); + when(appEnvironment.extensionName).thenReturn(PVSC_EXTENSION_ID_FOR_TESTS); + when(appEnvironment.packageJson).thenReturn({ version }); } suite('Initialization', () => { @@ -58,9 +58,9 @@ suite('Experimentation service', () => { const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, [], []); - configureExtensionVersion(extensionVersion); + configureApplicationEnvironment('stable', extensionVersion); - new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); sinon.assert.calledOnce(getExperimentationServiceStub); }); @@ -69,9 +69,9 @@ suite('Experimentation service', () => { const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); configureSettings(false, [], []); - configureExtensionVersion(extensionVersion); + configureApplicationEnvironment('stable', extensionVersion); - new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); sinon.assert.notCalled(getExperimentationServiceStub); }); @@ -80,13 +80,13 @@ suite('Experimentation service', () => { const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, [], []); - configureExtensionVersion(extensionVersion); + configureApplicationEnvironment('stable', extensionVersion); - new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); sinon.assert.calledWithExactly( getExperimentationServiceStub, - PVSC_EXTENSION_ID, + PVSC_EXTENSION_ID_FOR_TESTS, extensionVersion, tasClient.TargetPopulation.Public, sinon.match.any, @@ -95,18 +95,18 @@ suite('Experimentation service', () => { }); test('Users with an Insiders version of the extension should be the Insiders target population', () => { - const version = '1.2.3-dev'; + // const version = '1.2.3-dev'; const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, [], []); - configureExtensionVersion(version); + configureApplicationEnvironment('insiders', extensionVersion); - new ExperimentService(instance(configurationService), instance(extensions), globalMemento); + new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); sinon.assert.calledWithExactly( getExperimentationServiceStub, - PVSC_EXTENSION_ID, - version, + PVSC_EXTENSION_ID_FOR_TESTS, + extensionVersion, tasClient.TargetPopulation.Insiders, sinon.match.any, globalMemento @@ -117,11 +117,11 @@ suite('Experimentation service', () => { sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, ['Foo - experiment', 'Bar - control'], []); - configureExtensionVersion(extensionVersion); + configureApplicationEnvironment('stable', extensionVersion); const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); @@ -131,11 +131,11 @@ suite('Experimentation service', () => { test('Users can only opt out of experiment groups', () => { sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, [], ['Foo - experiment', 'Bar - control']); - configureExtensionVersion(extensionVersion); + configureApplicationEnvironment('stable', extensionVersion); const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); @@ -157,7 +157,7 @@ suite('Experimentation service', () => { telemetryEvents.push(telemetry); }); - configureExtensionVersion(extensionVersion); + configureApplicationEnvironment('stable', extensionVersion); }); teardown(() => { @@ -181,7 +181,7 @@ suite('Experimentation service', () => { const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); const result = await experimentService.inExperiment(experiment); @@ -197,7 +197,7 @@ suite('Experimentation service', () => { const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); const result = await experimentService.inExperiment(experiment); @@ -213,7 +213,7 @@ suite('Experimentation service', () => { const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); const result = await experimentService.inExperiment(experiment); @@ -233,7 +233,7 @@ suite('Experimentation service', () => { const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); const result = await experimentService.inExperiment(experiment); @@ -253,7 +253,7 @@ suite('Experimentation service', () => { const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); const result = await experimentService.inExperiment(experiment); @@ -273,7 +273,7 @@ suite('Experimentation service', () => { const experimentService = new ExperimentService( instance(configurationService), - instance(extensions), + instance(appEnvironment), globalMemento ); const result = await experimentService.inExperiment(experiment); From fbe5ff369a909ece976bbf6af437b05cfcc71648 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com> Date: Thu, 28 May 2020 13:19:58 -0700 Subject: [PATCH 17/25] Apply suggestions from code review Co-authored-by: Don Jayamanne --- src/client/common/experiments/service.ts | 2 +- src/client/common/experiments/telemetry.ts | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts index 5ba4f0240618..e8b33719f6e3 100644 --- a/src/client/common/experiments/service.ts +++ b/src/client/common/experiments/service.ts @@ -23,7 +23,7 @@ export class ExperimentService implements IExperimentService { public _optOutFrom: string[] = []; private readonly experimentationService?: IExperimentationService; - private settings!: IPythonSettings; + private readonly settings: IPythonSettings; constructor( @inject(IConfigurationService) readonly configurationService: IConfigurationService, diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index 1efc5bda9982..7a6733e64329 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -7,7 +7,7 @@ import { IExperimentationTelemetry } from 'vscode-tas-client'; import { sendTelemetryEvent } from '../../telemetry'; export class ExperimentationTelemetry implements IExperimentationTelemetry { - private readonly sharedProperties: { [key: string]: string } = {}; + private readonly sharedProperties: Record = {}; public setSharedProperty(name: string, value: string): void { this.sharedProperties[name] = value; @@ -15,9 +15,7 @@ export class ExperimentationTelemetry implements IExperimentationTelemetry { public postEvent(eventName: string, properties: Map): void { // Add shared properties to telemetry props (we may overwrite existing ones). - for (const [key, value] of Object.entries(this.sharedProperties)) { - properties.set(key, value); - } + Object.assign(properties, this.sharedProperties); const formattedProperties: { [key: string]: string } = {}; properties.forEach((value, key) => { From c0a2337ca21b28cc856ec79b4b9358cda5e1d359 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 13:21:28 -0700 Subject: [PATCH 18/25] Remove unnecessary formatted props --- src/client/common/experiments/telemetry.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index 7a6733e64329..b734d6a22a22 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -17,12 +17,7 @@ export class ExperimentationTelemetry implements IExperimentationTelemetry { // Add shared properties to telemetry props (we may overwrite existing ones). Object.assign(properties, this.sharedProperties); - const formattedProperties: { [key: string]: string } = {}; - properties.forEach((value, key) => { - formattedProperties[key] = value; - }); - // tslint:disable-next-line: no-any - sendTelemetryEvent(eventName as any, undefined, formattedProperties); + sendTelemetryEvent(eventName as any, undefined, properties); } } From a9e1267f2720652e6e41df7727f01018802f1f29 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 13:42:50 -0700 Subject: [PATCH 19/25] n e v e r m i n d --- src/client/common/experiments/telemetry.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index b734d6a22a22..7a6733e64329 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -17,7 +17,12 @@ export class ExperimentationTelemetry implements IExperimentationTelemetry { // Add shared properties to telemetry props (we may overwrite existing ones). Object.assign(properties, this.sharedProperties); + const formattedProperties: { [key: string]: string } = {}; + properties.forEach((value, key) => { + formattedProperties[key] = value; + }); + // tslint:disable-next-line: no-any - sendTelemetryEvent(eventName as any, undefined, properties); + sendTelemetryEvent(eventName as any, undefined, formattedProperties); } } From cc1f1655b7d1d5d69e0937fb1003c6e9561723e4 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 14:31:33 -0700 Subject: [PATCH 20/25] Aight fixed it --- src/client/common/experiments/telemetry.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index 7a6733e64329..4374985196de 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -14,14 +14,14 @@ export class ExperimentationTelemetry implements IExperimentationTelemetry { } public postEvent(eventName: string, properties: Map): void { - // Add shared properties to telemetry props (we may overwrite existing ones). - Object.assign(properties, this.sharedProperties); - const formattedProperties: { [key: string]: string } = {}; properties.forEach((value, key) => { formattedProperties[key] = value; }); + // Add shared properties to telemetry props (we may overwrite existing ones). + Object.assign(formattedProperties, this.sharedProperties); + // tslint:disable-next-line: no-any sendTelemetryEvent(eventName as any, undefined, formattedProperties); } From 060c06279585a7d5337d7ea70725750cf2173e72 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 15:14:34 -0700 Subject: [PATCH 21/25] flight -> experiment --- src/client/common/experiments/service.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/client/common/experiments/service.ts b/src/client/common/experiments/service.ts index e8b33719f6e3..68e01e5b2ea3 100644 --- a/src/client/common/experiments/service.ts +++ b/src/client/common/experiments/service.ts @@ -63,29 +63,29 @@ export class ExperimentService implements IExperimentService { ); } - public async inExperiment(flight: string): Promise { + public async inExperiment(experiment: string): Promise { if (!this.experimentationService) { return false; } // Currently the service doesn't support opting in and out of experiments, // so we need to perform these checks and send the corresponding telemetry manually. - if (this._optOutFrom.includes('All') || this._optOutFrom.includes(flight)) { + if (this._optOutFrom.includes('All') || this._optOutFrom.includes(experiment)) { sendTelemetryEvent(EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, undefined, { - expNameOptedOutOf: flight + expNameOptedOutOf: experiment }); return false; } - if (this._optInto.includes('All') || this._optInto.includes(flight)) { + if (this._optInto.includes('All') || this._optInto.includes(experiment)) { sendTelemetryEvent(EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, undefined, { - expNameOptedInto: flight + expNameOptedInto: experiment }); return true; } - return this.experimentationService.isCachedFlightEnabled(flight); + return this.experimentationService.isCachedFlightEnabled(experiment); } } From fc29418145cdb829dc46c2650217cd070c70956e Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 17:04:18 -0700 Subject: [PATCH 22/25] Check stub calls instead of ctor impl --- .../common/experiments/service.unit.test.ts | 77 ++++++------------- 1 file changed, 22 insertions(+), 55 deletions(-) diff --git a/src/test/common/experiments/service.unit.test.ts b/src/test/common/experiments/service.unit.test.ts index fc36ac85aa6b..633cb224d22a 100644 --- a/src/test/common/experiments/service.unit.test.ts +++ b/src/test/common/experiments/service.unit.test.ts @@ -17,8 +17,6 @@ import { EventName } from '../../../client/telemetry/constants'; import { PVSC_EXTENSION_ID_FOR_TESTS } from '../../constants'; import { MockMemento } from '../../mocks/mementos'; -// tslint:disable: no-unused-expression - suite('Experimentation service', () => { const extensionVersion = '1.2.3'; @@ -54,34 +52,13 @@ suite('Experimentation service', () => { } suite('Initialization', () => { - test('Instantiating a new ExperimentService should call methods from the experimentation framework', () => { - const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); - - configureSettings(true, [], []); - configureApplicationEnvironment('stable', extensionVersion); - - new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); - - sinon.assert.calledOnce(getExperimentationServiceStub); - }); - - test('Instantiating a new ExperimentService with the experiment settings being disabled should not call methods from the experimentation framework', () => { - const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); - - configureSettings(false, [], []); - configureApplicationEnvironment('stable', extensionVersion); - - new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); - - sinon.assert.notCalled(getExperimentationServiceStub); - }); - test('Users with a release version of the extension should be in the Public target population', () => { const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, [], []); configureApplicationEnvironment('stable', extensionVersion); + // tslint:disable-next-line: no-unused-expression new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); sinon.assert.calledWithExactly( @@ -95,12 +72,12 @@ suite('Experimentation service', () => { }); test('Users with an Insiders version of the extension should be the Insiders target population', () => { - // const version = '1.2.3-dev'; const getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService'); configureSettings(true, [], []); configureApplicationEnvironment('insiders', extensionVersion); + // tslint:disable-next-line: no-unused-expression new ExperimentService(instance(configurationService), instance(appEnvironment), globalMemento); sinon.assert.calledWithExactly( @@ -145,8 +122,9 @@ suite('Experimentation service', () => { suite('In-experiment check', () => { const experiment = 'Test Experiment - experiment'; - let isCachedFlightEnabledCalled = false; let telemetryEvents: { eventName: string; properties: object }[] = []; + let getExperimentationServiceStub: sinon.SinonStub; + let isCachedFlightEnabledStub: sinon.SinonStub; let sendTelemetryEventStub: sinon.SinonStub; setup(() => { @@ -157,27 +135,21 @@ suite('Experimentation service', () => { telemetryEvents.push(telemetry); }); + isCachedFlightEnabledStub = sinon.stub().returns(Promise.resolve(true)); + getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService').returns({ + isCachedFlightEnabled: isCachedFlightEnabledStub + // tslint:disable-next-line: no-any + } as any); + configureApplicationEnvironment('stable', extensionVersion); }); teardown(() => { - isCachedFlightEnabledCalled = false; telemetryEvents = []; }); - function configureIsCachedFlightEnabledStub(result: boolean) { - sinon.stub(tasClient, 'getExperimentationService').returns({ - isCachedFlightEnabled: (_: string) => { - isCachedFlightEnabledCalled = true; - return Promise.resolve(result); - } - // tslint:disable-next-line: no-any - } as any); - } - - test('If the experiment setting is disabled, inExperiment should return false', async () => { - configureSettings(false, [], []); - configureIsCachedFlightEnabledStub(true); + test('If the opt-in and opt-out arrays are empty, return the value from the experimentation framework for a given experiment', async () => { + configureSettings(true, [], []); const experimentService = new ExperimentService( instance(configurationService), @@ -186,14 +158,13 @@ suite('Experimentation service', () => { ); const result = await experimentService.inExperiment(experiment); - assert.isFalse(result); - assert.isFalse(isCachedFlightEnabledCalled); + assert.isTrue(result); sinon.assert.notCalled(sendTelemetryEventStub); + sinon.assert.calledOnce(isCachedFlightEnabledStub); }); - test('If the opt-in and opt-out arrays are empty, return the value from the experimentation framework for a given experiment', async () => { - configureSettings(true, [], []); - configureIsCachedFlightEnabledStub(true); + test('If the experiment setting is disabled, inExperiment should return false', async () => { + configureSettings(false, [], []); const experimentService = new ExperimentService( instance(configurationService), @@ -202,14 +173,13 @@ suite('Experimentation service', () => { ); const result = await experimentService.inExperiment(experiment); - assert.isTrue(result); - assert.isTrue(isCachedFlightEnabledCalled); + assert.isFalse(result); sinon.assert.notCalled(sendTelemetryEventStub); + sinon.assert.notCalled(getExperimentationServiceStub); }); test('If the opt-in setting contains "All", inExperiment should return true', async () => { configureSettings(true, ['All'], []); - configureIsCachedFlightEnabledStub(false); const experimentService = new ExperimentService( instance(configurationService), @@ -219,17 +189,16 @@ suite('Experimentation service', () => { const result = await experimentService.inExperiment(experiment); assert.isTrue(result); - assert.isFalse(isCachedFlightEnabledCalled); assert.equal(telemetryEvents.length, 1); assert.deepEqual(telemetryEvents[0], { eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, properties: { expNameOptedInto: experiment } }); + sinon.assert.notCalled(isCachedFlightEnabledStub); }); test('If the opt-in setting contains the experiment name, inExperiment should return true', async () => { configureSettings(true, [experiment], []); - configureIsCachedFlightEnabledStub(false); const experimentService = new ExperimentService( instance(configurationService), @@ -239,17 +208,16 @@ suite('Experimentation service', () => { const result = await experimentService.inExperiment(experiment); assert.isTrue(result); - assert.isFalse(isCachedFlightEnabledCalled); assert.equal(telemetryEvents.length, 1); assert.deepEqual(telemetryEvents[0], { eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, properties: { expNameOptedInto: experiment } }); + sinon.assert.notCalled(isCachedFlightEnabledStub); }); test('If the opt-out setting contains "All", inExperiment should return false', async () => { configureSettings(true, [], ['All']); - configureIsCachedFlightEnabledStub(true); const experimentService = new ExperimentService( instance(configurationService), @@ -259,17 +227,16 @@ suite('Experimentation service', () => { const result = await experimentService.inExperiment(experiment); assert.isFalse(result); - assert.isFalse(isCachedFlightEnabledCalled); assert.equal(telemetryEvents.length, 1); assert.deepEqual(telemetryEvents[0], { eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, properties: { expNameOptedOutOf: experiment } }); + sinon.assert.notCalled(isCachedFlightEnabledStub); }); test('If the opt-out setting contains the experiment name, inExperiment should return false', async () => { configureSettings(true, [], [experiment]); - configureIsCachedFlightEnabledStub(true); const experimentService = new ExperimentService( instance(configurationService), @@ -279,12 +246,12 @@ suite('Experimentation service', () => { const result = await experimentService.inExperiment(experiment); assert.isFalse(result); - assert.isFalse(isCachedFlightEnabledCalled); assert.equal(telemetryEvents.length, 1); assert.deepEqual(telemetryEvents[0], { eventName: EventName.PYTHON_EXPERIMENTS_OPT_IN_OUT, properties: { expNameOptedOutOf: experiment } }); + sinon.assert.notCalled(isCachedFlightEnabledStub); }); }); }); From fd28d4b816bbd921072beedfd0717b874faf6b43 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Thu, 28 May 2020 17:07:56 -0700 Subject: [PATCH 23/25] removed getExperimentService stub check --- src/test/common/experiments/service.unit.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/common/experiments/service.unit.test.ts b/src/test/common/experiments/service.unit.test.ts index 633cb224d22a..7cc26dcd0fc7 100644 --- a/src/test/common/experiments/service.unit.test.ts +++ b/src/test/common/experiments/service.unit.test.ts @@ -123,7 +123,6 @@ suite('Experimentation service', () => { suite('In-experiment check', () => { const experiment = 'Test Experiment - experiment'; let telemetryEvents: { eventName: string; properties: object }[] = []; - let getExperimentationServiceStub: sinon.SinonStub; let isCachedFlightEnabledStub: sinon.SinonStub; let sendTelemetryEventStub: sinon.SinonStub; @@ -136,7 +135,7 @@ suite('Experimentation service', () => { }); isCachedFlightEnabledStub = sinon.stub().returns(Promise.resolve(true)); - getExperimentationServiceStub = sinon.stub(tasClient, 'getExperimentationService').returns({ + sinon.stub(tasClient, 'getExperimentationService').returns({ isCachedFlightEnabled: isCachedFlightEnabledStub // tslint:disable-next-line: no-any } as any); @@ -175,7 +174,7 @@ suite('Experimentation service', () => { assert.isFalse(result); sinon.assert.notCalled(sendTelemetryEventStub); - sinon.assert.notCalled(getExperimentationServiceStub); + sinon.assert.notCalled(isCachedFlightEnabledStub); }); test('If the opt-in setting contains "All", inExperiment should return true', async () => { From ccb8f679a12040bbd447735061a21697451e7d70 Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Fri, 29 May 2020 09:29:23 -0700 Subject: [PATCH 24/25] Set shared properties for all telemetry events --- src/client/common/experiments/telemetry.ts | 10 +++---- src/client/telemetry/index.ts | 12 +++++++++ .../common/experiments/telemetry.unit.test.ts | 14 +++------- src/test/telemetry/index.unit.test.ts | 27 +++++++++++++++++-- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/client/common/experiments/telemetry.ts b/src/client/common/experiments/telemetry.ts index 4374985196de..f6e13c9b8947 100644 --- a/src/client/common/experiments/telemetry.ts +++ b/src/client/common/experiments/telemetry.ts @@ -4,13 +4,12 @@ 'use strict'; import { IExperimentationTelemetry } from 'vscode-tas-client'; -import { sendTelemetryEvent } from '../../telemetry'; +import { sendTelemetryEvent, setSharedProperty } from '../../telemetry'; export class ExperimentationTelemetry implements IExperimentationTelemetry { - private readonly sharedProperties: Record = {}; - public setSharedProperty(name: string, value: string): void { - this.sharedProperties[name] = value; + // Add the shared property to all telemetry being sent, not just events being sent by the experimentation package. + setSharedProperty(name, value); } public postEvent(eventName: string, properties: Map): void { @@ -19,9 +18,6 @@ export class ExperimentationTelemetry implements IExperimentationTelemetry { formattedProperties[key] = value; }); - // Add shared properties to telemetry props (we may overwrite existing ones). - Object.assign(formattedProperties, this.sharedProperties); - // tslint:disable-next-line: no-any sendTelemetryEvent(eventName as any, undefined, formattedProperties); } diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts index 37763b71e5fd..a9def8f57ba0 100644 --- a/src/client/telemetry/index.ts +++ b/src/client/telemetry/index.ts @@ -58,6 +58,15 @@ export function isTelemetryDisabled(workspaceService: IWorkspaceService): boolea return settings.globalValue === false ? true : false; } +// Shared properties set by the IExperimentationTelemetry implementation. +const sharedProperties: Record = {}; +/** + * Set shared properties for all telemetry events. + */ +export function setSharedProperty(name: string, value: string): void { + sharedProperties[name] = value; +} + let telemetryReporter: TelemetryReporter | undefined; function getTelemetryReporter() { if (!isTestExecution() && telemetryReporter) { @@ -123,6 +132,9 @@ export function sendTelemetryEvent

{ let telemetryEvents: { eventName: string; properties: object }[] = []; let sendTelemetryEventStub: sinon.SinonStub; + let setSharedPropertyStub: sinon.SinonStub; let experimentTelemetry: ExperimentationTelemetry; let eventProperties: Map; @@ -23,6 +24,7 @@ suite('Experimentation telemetry', () => { const telemetry = { eventName, properties }; telemetryEvents.push(telemetry); }); + setSharedPropertyStub = sinon.stub(Telemetry, 'setSharedProperty'); eventProperties = new Map(); eventProperties.set('foo', 'one'); @@ -50,19 +52,11 @@ suite('Experimentation telemetry', () => { }); }); - test('Shared properties should be sent in the telemetry event', () => { + test('Shared properties should be set for all telemetry events', () => { const shared = { key: 'shared', value: 'three' }; experimentTelemetry.setSharedProperty(shared.key, shared.value); - experimentTelemetry.postEvent(event, eventProperties); - assert.deepEqual(telemetryEvents[0], { - eventName: event, - properties: { - foo: 'one', - bar: 'two', - shared: 'three' - } - }); + sinon.assert.calledOnce(setSharedPropertyStub); }); }); diff --git a/src/test/telemetry/index.unit.test.ts b/src/test/telemetry/index.unit.test.ts index 0bc9d757649e..ab0aa5f95b9b 100644 --- a/src/test/telemetry/index.unit.test.ts +++ b/src/test/telemetry/index.unit.test.ts @@ -12,7 +12,12 @@ import { WorkspaceConfiguration } from 'vscode'; import { IWorkspaceService } from '../../client/common/application/types'; import { WorkspaceService } from '../../client/common/application/workspace'; import { EXTENSION_ROOT_DIR } from '../../client/constants'; -import { clearTelemetryReporter, isTelemetryDisabled, sendTelemetryEvent } from '../../client/telemetry'; +import { + clearTelemetryReporter, + isTelemetryDisabled, + sendTelemetryEvent, + setSharedProperty +} from '../../client/telemetry'; suite('Telemetry', () => { let workspaceService: IWorkspaceService; @@ -100,7 +105,7 @@ suite('Telemetry', () => { expect(Reporter.measures).to.deep.equal([measures]); expect(Reporter.properties).to.deep.equal([properties]); }); - test('Send Telemetry with properties', () => { + test('Send Telemetry with no properties', () => { rewiremock.enable(); rewiremock('vscode-extension-telemetry').with({ default: Reporter }); @@ -112,6 +117,24 @@ suite('Telemetry', () => { expect(Reporter.measures).to.deep.equal([undefined], 'Measures should be empty'); expect(Reporter.properties).to.deep.equal([{}], 'Properties should be empty'); }); + test('Send Telemetry with shared properties', () => { + rewiremock.enable(); + rewiremock('vscode-extension-telemetry').with({ default: Reporter }); + + const eventName = 'Testing'; + const properties = { hello: 'world', foo: 'bar' }; + const measures = { start: 123, end: 987 }; + const expectedProperties = { ...properties, one: 'two' }; + + setSharedProperty('one', 'two'); + + // tslint:disable-next-line:no-any + sendTelemetryEvent(eventName as any, measures, properties as any); + + expect(Reporter.eventName).to.deep.equal([eventName]); + expect(Reporter.measures).to.deep.equal([measures]); + expect(Reporter.properties).to.deep.equal([expectedProperties]); + }); test('Send Error Telemetry', () => { rewiremock.enable(); const error = new Error('Boo'); From 4b2d9319556c6440f94f67a191151d812f6df50b Mon Sep 17 00:00:00 2001 From: Kim-Adeline Miguel Date: Tue, 2 Jun 2020 08:32:40 -0700 Subject: [PATCH 25/25] Add test for shared properties --- src/client/telemetry/index.ts | 9 +++++++++ src/test/telemetry/index.unit.test.ts | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts index a9def8f57ba0..bb2a4eae7f60 100644 --- a/src/client/telemetry/index.ts +++ b/src/client/telemetry/index.ts @@ -67,6 +67,15 @@ export function setSharedProperty(name: string, value: string): void { sharedProperties[name] = value; } +/** + * Reset shared properties for testing purposes. + */ +export function _resetSharedProperties(): void { + for (const key of Object.keys(sharedProperties)) { + delete sharedProperties[key]; + } +} + let telemetryReporter: TelemetryReporter | undefined; function getTelemetryReporter() { if (!isTestExecution() && telemetryReporter) { diff --git a/src/test/telemetry/index.unit.test.ts b/src/test/telemetry/index.unit.test.ts index ab0aa5f95b9b..3034f75f2446 100644 --- a/src/test/telemetry/index.unit.test.ts +++ b/src/test/telemetry/index.unit.test.ts @@ -13,6 +13,7 @@ import { IWorkspaceService } from '../../client/common/application/types'; import { WorkspaceService } from '../../client/common/application/workspace'; import { EXTENSION_ROOT_DIR } from '../../client/constants'; import { + _resetSharedProperties, clearTelemetryReporter, isTelemetryDisabled, sendTelemetryEvent, @@ -57,6 +58,7 @@ suite('Telemetry', () => { process.env.VSC_PYTHON_UNIT_TEST = oldValueOfVSC_PYTHON_UNIT_TEST; process.env.VSC_PYTHON_CI_TEST = oldValueOfVSC_PYTHON_CI_TEST; rewiremock.disable(); + _resetSharedProperties(); }); const testsForisTelemetryDisabled = [ @@ -135,6 +137,24 @@ suite('Telemetry', () => { expect(Reporter.measures).to.deep.equal([measures]); expect(Reporter.properties).to.deep.equal([expectedProperties]); }); + test('Shared properties will replace existing ones', () => { + rewiremock.enable(); + rewiremock('vscode-extension-telemetry').with({ default: Reporter }); + + const eventName = 'Testing'; + const properties = { hello: 'world', foo: 'bar' }; + const measures = { start: 123, end: 987 }; + const expectedProperties = { ...properties, foo: 'baz' }; + + setSharedProperty('foo', 'baz'); + + // tslint:disable-next-line:no-any + sendTelemetryEvent(eventName as any, measures, properties as any); + + expect(Reporter.eventName).to.deep.equal([eventName]); + expect(Reporter.measures).to.deep.equal([measures]); + expect(Reporter.properties).to.deep.equal([expectedProperties]); + }); test('Send Error Telemetry', () => { rewiremock.enable(); const error = new Error('Boo');