microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix-ts-error1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/services/experimentService/experimentService.ts

150lines · modeblame

88671796RedMickey5 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as vscode from "vscode";
ab0238b7RedMickey4 years ago5import { TelemetryHelper } from "../../../common/telemetryHelper";
6import { Telemetry } from "../../../common/telemetry";
7import { ExtensionConfigManager } from "../../extensionConfigManager";
f338085detatanova4 years ago8import { IConfig, retryDownloadConfig } from "../remoteConfigHelper";
09f6024fHeniker4 years ago9import { IExperiment } from "./IExperiment";
88671796RedMickey5 years ago10
11export enum ExperimentStatuses {
12ENABLED = "enabled",
13DISABLED = "disabled",
14FAILED = "failed",
15}
16
f338085detatanova4 years ago17export interface ExperimentConfig extends IConfig {
88671796RedMickey5 years ago18experimentName: string;
19popCoveragePercent: number;
20enabled: boolean;
21}
22
23export interface ExperimentParameters extends ExperimentConfig {
24[key: string]: any;
25extensionId?: string;
26}
27
28export interface ExperimentResult {
29resultStatus: ExperimentStatuses;
30updatedExperimentParameters: ExperimentParameters;
31error?: Error;
32}
33
34export class ExperimentService implements vscode.Disposable {
35private static instance: ExperimentService;
36
37private readonly endpointURL: string;
38private downloadedExperimentsConfig: Array<ExperimentConfig> | null;
39private experimentsInstances: Map<string, IExperiment>;
40private downloadConfigRequest: Promise<ExperimentConfig[]>;
41private cancellationTokenSource: vscode.CancellationTokenSource;
42
34472878RedMickey5 years ago43public static create(): ExperimentService {
88671796RedMickey5 years ago44if (!ExperimentService.instance) {
45ExperimentService.instance = new ExperimentService();
46}
47
48return ExperimentService.instance;
49}
50
51public async runExperiments(): Promise<void> {
52if (!this.downloadedExperimentsConfig) {
53this.downloadedExperimentsConfig = await this.downloadConfigRequest;
54this.experimentsInstances = await this.initializeExperimentsInstances();
55}
56
09f6024fHeniker4 years ago57const experimentResults: Array<ExperimentResult> = await Promise.all(
34472878RedMickey5 years ago58this.downloadedExperimentsConfig.map(expConfig => this.executeExperiment(expConfig)),
88671796RedMickey5 years ago59);
60
61this.sendExperimentTelemetry(experimentResults);
62}
63
34472878RedMickey5 years ago64public dispose(): void {
88671796RedMickey5 years ago65this.cancellationTokenSource.cancel();
66this.cancellationTokenSource.dispose();
67}
68
69private constructor() {
34472878RedMickey5 years ago70this.endpointURL =
71"https://microsoft.github.io/vscode-react-native/experiments/experimentsConfig.json";
88671796RedMickey5 years ago72this.cancellationTokenSource = new vscode.CancellationTokenSource();
73this.downloadedExperimentsConfig = null;
74
f338085detatanova4 years ago75this.downloadConfigRequest = retryDownloadConfig<ExperimentConfig[]>(
76this.endpointURL,
77this.cancellationTokenSource,
78);
88671796RedMickey5 years ago79}
80
81private async executeExperiment(expConfig: ExperimentConfig): Promise<ExperimentResult> {
09f6024fHeniker4 years ago82const curExperimentParameters = ExtensionConfigManager.config.get(expConfig.experimentName);
83const expInstance = this.experimentsInstances.get(expConfig.experimentName);
88671796RedMickey5 years ago84
85let expResult: ExperimentResult;
86if (expInstance && expConfig.enabled) {
87try {
88expResult = await expInstance.run(expConfig, curExperimentParameters);
155e1318JiglioNero5 years ago89ExtensionConfigManager.config.set(
90expConfig.experimentName,
91expResult.updatedExperimentParameters,
92);
88671796RedMickey5 years ago93} catch (err) {
94expResult = {
95resultStatus: ExperimentStatuses.FAILED,
96updatedExperimentParameters: expConfig,
97error: err,
98};
99}
100} else {
101expResult = {
102resultStatus: ExperimentStatuses.DISABLED,
103updatedExperimentParameters: expConfig,
104};
105}
106
107return expResult;
108}
109
110private async initializeExperimentsInstances(): Promise<Map<string, IExperiment>> {
09f6024fHeniker4 years ago111const expInstances = new Map<string, IExperiment>();
88671796RedMickey5 years ago112
113if (this.downloadedExperimentsConfig) {
09f6024fHeniker4 years ago114for (const expConfig of this.downloadedExperimentsConfig) {
88671796RedMickey5 years ago115try {
09f6024fHeniker4 years ago116const expClass = await import(`./experiments/${expConfig.experimentName}`);
34472878RedMickey5 years ago117expInstances.set(expConfig.experimentName, new expClass.default());
88671796RedMickey5 years ago118} catch (err) {
119expConfig.enabled = false;
120}
121}
122}
123
124return expInstances;
125}
126
127private sendExperimentTelemetry(experimentsResults: ExperimentResult[]): void {
128const runExperimentsEvent = TelemetryHelper.createTelemetryEvent("runExperiments");
129
130experimentsResults.forEach(expResult => {
34472878RedMickey5 years ago131if (expResult.resultStatus === ExperimentStatuses.FAILED && expResult.error) {
88671796RedMickey5 years ago132TelemetryHelper.addTelemetryEventErrorProperty(
133runExperimentsEvent,
134expResult.error,
135undefined,
34472878RedMickey5 years ago136`${expResult.updatedExperimentParameters.experimentName}.`,
88671796RedMickey5 years ago137);
138} else {
139TelemetryHelper.addTelemetryEventProperty(
140runExperimentsEvent,
141expResult.updatedExperimentParameters.experimentName,
142expResult.resultStatus,
34472878RedMickey5 years ago143false,
88671796RedMickey5 years ago144);
145}
146});
147
148Telemetry.send(runExperimentsEvent);
149}
150}