From 304ae2de062e49eec72747c19bb0fbff8ca41cbe Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 4 May 2022 17:20:26 -0500 Subject: [PATCH 1/2] fix: patch telemetry This seems to have been dropped in the rewrite. --- patches/series | 1 + patches/telemetry.diff | 228 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 patches/telemetry.diff diff --git a/patches/series b/patches/series index 5801db6aea36..318ad7abac9d 100644 --- a/patches/series +++ b/patches/series @@ -18,3 +18,4 @@ service-worker.diff connection-type.diff sourcemaps.diff disable-downloads.diff +telemetry.diff diff --git a/patches/telemetry.diff b/patches/telemetry.diff new file mode 100644 index 000000000000..c8c26f815fdc --- /dev/null +++ b/patches/telemetry.diff @@ -0,0 +1,228 @@ +Add support for telemetry endpoint + +Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts ++++ code-server/lib/vscode/src/vs/server/node/serverServices.ts +@@ -68,6 +68,7 @@ import { REMOTE_TERMINAL_CHANNEL_NAME } + import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService'; + import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/workbench/services/remote/common/remoteFileSystemProviderClient'; + import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService'; ++import { TelemetryClient } from "vs/server/node/telemetryClient"; + + const eventPrefix = 'monacoworkbench'; + +@@ -120,7 +121,11 @@ export async function setupServerService + let appInsightsAppender: ITelemetryAppender = NullAppender; + const machineId = await getMachineId(); + if (supportsTelemetry(productService, environmentService)) { +- if (productService.aiConfig && productService.aiConfig.asimovKey) { ++ const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track"; ++ if (telemetryEndpoint) { ++ appInsightsAppender = new AppInsightsAppender(eventPrefix, null, () => new TelemetryClient(telemetryEndpoint) as any); ++ disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data ++ } else if (productService.aiConfig && productService.aiConfig.asimovKey) { + appInsightsAppender = new AppInsightsAppender(eventPrefix, null, productService.aiConfig.asimovKey); + disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data + } +Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts +=================================================================== +--- /dev/null ++++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts +@@ -0,0 +1,135 @@ ++import * as appInsights from 'applicationinsights'; ++import * as https from 'https'; ++import * as http from 'http'; ++import * as os from 'os'; ++ ++class Channel { ++ public get _sender() { ++ throw new Error('unimplemented'); ++ } ++ public get _buffer() { ++ throw new Error('unimplemented'); ++ } ++ ++ public setUseDiskRetryCaching(): void { ++ throw new Error('unimplemented'); ++ } ++ public send(): void { ++ throw new Error('unimplemented'); ++ } ++ public triggerSend(): void { ++ throw new Error('unimplemented'); ++ } ++} ++ ++// Unable to use implements because TypeScript tells you a private property is ++// missing but if you add it then it complains they have different private ++// properties. Uncommenting it during development can be helpful though to see ++// if anything is missing. ++export class TelemetryClient /* implements appInsights.TelemetryClient */ { ++ private _telemetryProcessors: any = undefined; ++ public context: any = undefined; ++ public commonProperties: any = undefined; ++ public config: any = {}; ++ public quickPulseClient: any = undefined; ++ ++ public channel: any = new Channel(); ++ ++ public constructor(private readonly endpoint: string) { ++ // Nothing to do. ++ } ++ ++ public addTelemetryProcessor(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public clearTelemetryProcessors(): void { ++ if (this._telemetryProcessors) { ++ this._telemetryProcessors = undefined; ++ } ++ } ++ ++ public runTelemetryProcessors(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackTrace(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackMetric(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackException(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackRequest(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackDependency(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public track(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackNodeHttpRequestSync(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackNodeHttpRequest(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackNodeHttpDependency(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackEvent(options: appInsights.Contracts.EventTelemetry): void { ++ if (!options.properties) { ++ options.properties = {}; ++ } ++ if (!options.measurements) { ++ options.measurements = {}; ++ } ++ ++ try { ++ const cpus = os.cpus(); ++ options.measurements.cores = cpus.length; ++ options.properties['common.cpuModel'] = cpus[0].model; ++ } catch (error) {} ++ ++ try { ++ options.measurements.memoryFree = os.freemem(); ++ options.measurements.memoryTotal = os.totalmem(); ++ } catch (error) {} ++ ++ try { ++ options.properties['common.shell'] = os.userInfo().shell; ++ options.properties['common.release'] = os.release(); ++ options.properties['common.arch'] = os.arch(); ++ } catch (error) {} ++ ++ try { ++ const request = (/^http:/.test(this.endpoint) ? http : https).request(this.endpoint, { ++ method: 'POST', ++ headers: { ++ 'Content-Type': 'application/json', ++ }, ++ }); ++ request.on('error', () => { /* We don't care. */ }); ++ request.write(JSON.stringify(options)); ++ request.end(); ++ } catch (error) {} ++ } ++ ++ public flush(options: { callback: (v: string) => void }): void { ++ if (options.callback) { ++ options.callback(''); ++ } ++ } ++} +Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts ++++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +@@ -304,6 +304,7 @@ export class WebClientServer { + logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined, + proxyEndpointTemplate: base + '/proxy/{{port}}', + codeServerVersion: this._productService.codeServerVersion, ++ enableTelemetry: this._productService.enableTelemetry, + embedderIdentifier: 'server-distro', + serviceWorker: { + scope: vscodeBase + '/', +Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts ++++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts +@@ -25,6 +25,7 @@ class WebAppInsightsAppender implements + private _telemetryCache: { eventName: string; data: any }[] = []; + + constructor(private _eventPrefix: string, aiKey: string) { ++ console.log("halp") + const endpointUrl = 'https://vortex.data.microsoft.com/collect/v1'; + import('@microsoft/applicationinsights-web').then(aiLibrary => { + this._aiClient = new aiLibrary.ApplicationInsights({ +@@ -74,6 +75,7 @@ class WebAppInsightsAppender implements + data = { ...data.properties, ...data.measurements }; + + // undefined assertion is ok since above two if statements cover both cases ++ console.log("are we here maybe?") + this._aiClient!.trackEvent({ name: this._eventPrefix + '/' + eventName }, data); + } + +@@ -119,16 +121,19 @@ export class TelemetryService extends Di + ) { + super(); + +- if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.asimovKey) { ++ if (supportsTelemetry(productService, environmentService)) { + // If remote server is present send telemetry through that, else use the client side appender +- const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey); +- const config: ITelemetryServiceConfig = { +- appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)], +- commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), +- sendErrorTelemetry: this.sendErrorTelemetry, +- }; +- +- this.impl = this._register(new BaseTelemetryService(config, configurationService, productService)); ++ const telemetryProvider: ITelemetryAppender | undefined = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : productService.aiConfig?.asimovKey ? new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey) : undefined; ++ if (telemetryProvider) { ++ const config: ITelemetryServiceConfig = { ++ appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)], ++ commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), ++ sendErrorTelemetry: this.sendErrorTelemetry, ++ }; ++ this.impl = this._register(new BaseTelemetryService(config, configurationService, productService)); ++ } else { ++ this.impl = NullTelemetryService; ++ } + } else { + this.impl = NullTelemetryService; + } From 11447aa07e81e1017fe60e5b4cfab948905ee696 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 4 May 2022 17:53:25 -0500 Subject: [PATCH 2/2] fixup! fix: patch telemetry --- patches/telemetry.diff | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/patches/telemetry.diff b/patches/telemetry.diff index c8c26f815fdc..2d0feabac82b 100644 --- a/patches/telemetry.diff +++ b/patches/telemetry.diff @@ -9,9 +9,9 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/workbench/services/remote/common/remoteFileSystemProviderClient'; import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService'; +import { TelemetryClient } from "vs/server/node/telemetryClient"; - + const eventPrefix = 'monacoworkbench'; - + @@ -120,7 +121,11 @@ export async function setupServerService let appInsightsAppender: ITelemetryAppender = NullAppender; const machineId = await getMachineId(); @@ -181,26 +181,10 @@ Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/teleme =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts +++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts -@@ -25,6 +25,7 @@ class WebAppInsightsAppender implements - private _telemetryCache: { eventName: string; data: any }[] = []; - - constructor(private _eventPrefix: string, aiKey: string) { -+ console.log("halp") - const endpointUrl = 'https://vortex.data.microsoft.com/collect/v1'; - import('@microsoft/applicationinsights-web').then(aiLibrary => { - this._aiClient = new aiLibrary.ApplicationInsights({ -@@ -74,6 +75,7 @@ class WebAppInsightsAppender implements - data = { ...data.properties, ...data.measurements }; - - // undefined assertion is ok since above two if statements cover both cases -+ console.log("are we here maybe?") - this._aiClient!.trackEvent({ name: this._eventPrefix + '/' + eventName }, data); - } - -@@ -119,16 +121,19 @@ export class TelemetryService extends Di +@@ -119,16 +119,19 @@ export class TelemetryService extends Di ) { super(); - + - if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.asimovKey) { + if (supportsTelemetry(productService, environmentService)) { // If remote server is present send telemetry through that, else use the client side appender