Path: blob/main/src/vs/platform/assignment/common/assignment.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Event } from '../../../base/common/event.js';6import * as platform from '../../../base/common/platform.js';7import type { IExperimentationFilterProvider } from 'tas-client-umd';89export const ASSIGNMENT_STORAGE_KEY = 'VSCode.ABExp.FeatureData';10export const ASSIGNMENT_REFETCH_INTERVAL = 60 * 60 * 1000; // 1 hour1112export interface IAssignmentService {13readonly _serviceBrand: undefined;1415readonly onDidRefetchAssignments: Event<void>;16getTreatment<T extends string | number | boolean>(name: string): Promise<T | undefined>;17}1819export enum TargetPopulation {20Insiders = 'insider',21Public = 'public',22Exploration = 'exploration'23}2425/*26Based upon the official VSCode currently existing filters in the27ExP backend for the VSCode cluster.28https://experimentation.visualstudio.com/Analysis%20and%20Experimentation/_git/AnE.ExP.TAS.TachyonHost.Configuration?path=%2FConfigurations%2Fvscode%2Fvscode.json&version=GBmaster29"X-MSEdge-Market": "detection.market",30"X-FD-Corpnet": "detection.corpnet",31"X-VSCode-AppVersion": "appversion",32"X-VSCode-Build": "build",33"X-MSEdge-ClientId": "clientid",34"X-VSCode-ExtensionName": "extensionname",35"X-VSCode-ExtensionVersion": "extensionversion",36"X-VSCode-TargetPopulation": "targetpopulation",37"X-VSCode-Language": "language"38*/39export enum Filters {40/**41* The market in which the extension is distributed.42*/43Market = 'X-MSEdge-Market',4445/**46* The corporation network.47*/48CorpNet = 'X-FD-Corpnet',4950/**51* Version of the application which uses experimentation service.52*/53ApplicationVersion = 'X-VSCode-AppVersion',5455/**56* Insiders vs Stable.57*/58Build = 'X-VSCode-Build',5960/**61* Client Id which is used as primary unit for the experimentation.62*/63ClientId = 'X-MSEdge-ClientId',6465/**66* Extension header.67*/68ExtensionName = 'X-VSCode-ExtensionName',6970/**71* The version of the extension.72*/73ExtensionVersion = 'X-VSCode-ExtensionVersion',7475/**76* The language in use by VS Code77*/78Language = 'X-VSCode-Language',7980/**81* The target population.82* This is used to separate internal, early preview, GA, etc.83*/84TargetPopulation = 'X-VSCode-TargetPopulation',85}8687export class AssignmentFilterProvider implements IExperimentationFilterProvider {88constructor(89private version: string,90private appName: string,91private machineId: string,92private targetPopulation: TargetPopulation93) { }9495/**96* Returns a version string that can be parsed by the TAS client.97* The tas client cannot handle suffixes lke "-insider"98* Ref: https://github.com/microsoft/tas-client/blob/30340d5e1da37c2789049fcf45928b954680606f/vscode-tas-client/src/vscode-tas-client/VSCodeFilterProvider.ts#L3599*100* @param version Version string to be trimmed.101*/102private static trimVersionSuffix(version: string): string {103const regex = /\-[a-zA-Z0-9]+$/;104const result = version.split(regex);105106return result[0];107}108109getFilterValue(filter: string): string | null {110switch (filter) {111case Filters.ApplicationVersion:112return AssignmentFilterProvider.trimVersionSuffix(this.version); // productService.version113case Filters.Build:114return this.appName; // productService.nameLong115case Filters.ClientId:116return this.machineId;117case Filters.Language:118return platform.language;119case Filters.ExtensionName:120return 'vscode-core'; // always return vscode-core for exp service121case Filters.ExtensionVersion:122return '999999.0'; // always return a very large number for cross-extension experimentation123case Filters.TargetPopulation:124return this.targetPopulation;125default:126return '';127}128}129130getFilters(): Map<string, any> {131const filters: Map<string, any> = new Map<string, any>();132const filterValues = Object.values(Filters);133for (const value of filterValues) {134filters.set(value, this.getFilterValue(value));135}136137return filters;138}139}140141142