|
| 1 | +Add support for telemetry endpoint |
| 2 | + |
| 3 | +Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts |
| 4 | +=================================================================== |
| 5 | +--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts |
| 6 | ++++ code-server/lib/vscode/src/vs/server/node/serverServices.ts |
| 7 | +@@ -68,6 +68,7 @@ import { REMOTE_TERMINAL_CHANNEL_NAME } |
| 8 | + import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService'; |
| 9 | + import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/workbench/services/remote/common/remoteFileSystemProviderClient'; |
| 10 | + import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService'; |
| 11 | ++import { TelemetryClient } from "vs/server/node/telemetryClient"; |
| 12 | + |
| 13 | + const eventPrefix = 'monacoworkbench'; |
| 14 | + |
| 15 | +@@ -120,7 +121,11 @@ export async function setupServerService |
| 16 | + let appInsightsAppender: ITelemetryAppender = NullAppender; |
| 17 | + const machineId = await getMachineId(); |
| 18 | + if (supportsTelemetry(productService, environmentService)) { |
| 19 | +- if (productService.aiConfig && productService.aiConfig.asimovKey) { |
| 20 | ++ const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track"; |
| 21 | ++ if (telemetryEndpoint) { |
| 22 | ++ appInsightsAppender = new AppInsightsAppender(eventPrefix, null, () => new TelemetryClient(telemetryEndpoint) as any); |
| 23 | ++ disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data |
| 24 | ++ } else if (productService.aiConfig && productService.aiConfig.asimovKey) { |
| 25 | + appInsightsAppender = new AppInsightsAppender(eventPrefix, null, productService.aiConfig.asimovKey); |
| 26 | + disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data |
| 27 | + } |
| 28 | +Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts |
| 29 | +=================================================================== |
| 30 | +--- /dev/null |
| 31 | ++++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts |
| 32 | +@@ -0,0 +1,135 @@ |
| 33 | ++import * as appInsights from 'applicationinsights'; |
| 34 | ++import * as https from 'https'; |
| 35 | ++import * as http from 'http'; |
| 36 | ++import * as os from 'os'; |
| 37 | ++ |
| 38 | ++class Channel { |
| 39 | ++ public get _sender() { |
| 40 | ++ throw new Error('unimplemented'); |
| 41 | ++ } |
| 42 | ++ public get _buffer() { |
| 43 | ++ throw new Error('unimplemented'); |
| 44 | ++ } |
| 45 | ++ |
| 46 | ++ public setUseDiskRetryCaching(): void { |
| 47 | ++ throw new Error('unimplemented'); |
| 48 | ++ } |
| 49 | ++ public send(): void { |
| 50 | ++ throw new Error('unimplemented'); |
| 51 | ++ } |
| 52 | ++ public triggerSend(): void { |
| 53 | ++ throw new Error('unimplemented'); |
| 54 | ++ } |
| 55 | ++} |
| 56 | ++ |
| 57 | ++// Unable to use implements because TypeScript tells you a private property is |
| 58 | ++// missing but if you add it then it complains they have different private |
| 59 | ++// properties. Uncommenting it during development can be helpful though to see |
| 60 | ++// if anything is missing. |
| 61 | ++export class TelemetryClient /* implements appInsights.TelemetryClient */ { |
| 62 | ++ private _telemetryProcessors: any = undefined; |
| 63 | ++ public context: any = undefined; |
| 64 | ++ public commonProperties: any = undefined; |
| 65 | ++ public config: any = {}; |
| 66 | ++ public quickPulseClient: any = undefined; |
| 67 | ++ |
| 68 | ++ public channel: any = new Channel(); |
| 69 | ++ |
| 70 | ++ public constructor(private readonly endpoint: string) { |
| 71 | ++ // Nothing to do. |
| 72 | ++ } |
| 73 | ++ |
| 74 | ++ public addTelemetryProcessor(): void { |
| 75 | ++ throw new Error('unimplemented'); |
| 76 | ++ } |
| 77 | ++ |
| 78 | ++ public clearTelemetryProcessors(): void { |
| 79 | ++ if (this._telemetryProcessors) { |
| 80 | ++ this._telemetryProcessors = undefined; |
| 81 | ++ } |
| 82 | ++ } |
| 83 | ++ |
| 84 | ++ public runTelemetryProcessors(): void { |
| 85 | ++ throw new Error('unimplemented'); |
| 86 | ++ } |
| 87 | ++ |
| 88 | ++ public trackTrace(): void { |
| 89 | ++ throw new Error('unimplemented'); |
| 90 | ++ } |
| 91 | ++ |
| 92 | ++ public trackMetric(): void { |
| 93 | ++ throw new Error('unimplemented'); |
| 94 | ++ } |
| 95 | ++ |
| 96 | ++ public trackException(): void { |
| 97 | ++ throw new Error('unimplemented'); |
| 98 | ++ } |
| 99 | ++ |
| 100 | ++ public trackRequest(): void { |
| 101 | ++ throw new Error('unimplemented'); |
| 102 | ++ } |
| 103 | ++ |
| 104 | ++ public trackDependency(): void { |
| 105 | ++ throw new Error('unimplemented'); |
| 106 | ++ } |
| 107 | ++ |
| 108 | ++ public track(): void { |
| 109 | ++ throw new Error('unimplemented'); |
| 110 | ++ } |
| 111 | ++ |
| 112 | ++ public trackNodeHttpRequestSync(): void { |
| 113 | ++ throw new Error('unimplemented'); |
| 114 | ++ } |
| 115 | ++ |
| 116 | ++ public trackNodeHttpRequest(): void { |
| 117 | ++ throw new Error('unimplemented'); |
| 118 | ++ } |
| 119 | ++ |
| 120 | ++ public trackNodeHttpDependency(): void { |
| 121 | ++ throw new Error('unimplemented'); |
| 122 | ++ } |
| 123 | ++ |
| 124 | ++ public trackEvent(options: appInsights.Contracts.EventTelemetry): void { |
| 125 | ++ if (!options.properties) { |
| 126 | ++ options.properties = {}; |
| 127 | ++ } |
| 128 | ++ if (!options.measurements) { |
| 129 | ++ options.measurements = {}; |
| 130 | ++ } |
| 131 | ++ |
| 132 | ++ try { |
| 133 | ++ const cpus = os.cpus(); |
| 134 | ++ options.measurements.cores = cpus.length; |
| 135 | ++ options.properties['common.cpuModel'] = cpus[0].model; |
| 136 | ++ } catch (error) {} |
| 137 | ++ |
| 138 | ++ try { |
| 139 | ++ options.measurements.memoryFree = os.freemem(); |
| 140 | ++ options.measurements.memoryTotal = os.totalmem(); |
| 141 | ++ } catch (error) {} |
| 142 | ++ |
| 143 | ++ try { |
| 144 | ++ options.properties['common.shell'] = os.userInfo().shell; |
| 145 | ++ options.properties['common.release'] = os.release(); |
| 146 | ++ options.properties['common.arch'] = os.arch(); |
| 147 | ++ } catch (error) {} |
| 148 | ++ |
| 149 | ++ try { |
| 150 | ++ const request = (/^http:/.test(this.endpoint) ? http : https).request(this.endpoint, { |
| 151 | ++ method: 'POST', |
| 152 | ++ headers: { |
| 153 | ++ 'Content-Type': 'application/json', |
| 154 | ++ }, |
| 155 | ++ }); |
| 156 | ++ request.on('error', () => { /* We don't care. */ }); |
| 157 | ++ request.write(JSON.stringify(options)); |
| 158 | ++ request.end(); |
| 159 | ++ } catch (error) {} |
| 160 | ++ } |
| 161 | ++ |
| 162 | ++ public flush(options: { callback: (v: string) => void }): void { |
| 163 | ++ if (options.callback) { |
| 164 | ++ options.callback(''); |
| 165 | ++ } |
| 166 | ++ } |
| 167 | ++} |
| 168 | +Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts |
| 169 | +=================================================================== |
| 170 | +--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts |
| 171 | ++++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts |
| 172 | +@@ -304,6 +304,7 @@ export class WebClientServer { |
| 173 | + logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined, |
| 174 | + proxyEndpointTemplate: base + '/proxy/{{port}}', |
| 175 | + codeServerVersion: this._productService.codeServerVersion, |
| 176 | ++ enableTelemetry: this._productService.enableTelemetry, |
| 177 | + embedderIdentifier: 'server-distro', |
| 178 | + serviceWorker: { |
| 179 | + scope: vscodeBase + '/', |
| 180 | +Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts |
| 181 | +=================================================================== |
| 182 | +--- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts |
| 183 | ++++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts |
| 184 | +@@ -119,16 +119,19 @@ export class TelemetryService extends Di |
| 185 | + ) { |
| 186 | + super(); |
| 187 | + |
| 188 | +- if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.asimovKey) { |
| 189 | ++ if (supportsTelemetry(productService, environmentService)) { |
| 190 | + // If remote server is present send telemetry through that, else use the client side appender |
| 191 | +- const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey); |
| 192 | +- const config: ITelemetryServiceConfig = { |
| 193 | +- appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)], |
| 194 | +- commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), |
| 195 | +- sendErrorTelemetry: this.sendErrorTelemetry, |
| 196 | +- }; |
| 197 | +- |
| 198 | +- this.impl = this._register(new BaseTelemetryService(config, configurationService, productService)); |
| 199 | ++ 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; |
| 200 | ++ if (telemetryProvider) { |
| 201 | ++ const config: ITelemetryServiceConfig = { |
| 202 | ++ appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)], |
| 203 | ++ commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties), |
| 204 | ++ sendErrorTelemetry: this.sendErrorTelemetry, |
| 205 | ++ }; |
| 206 | ++ this.impl = this._register(new BaseTelemetryService(config, configurationService, productService)); |
| 207 | ++ } else { |
| 208 | ++ this.impl = NullTelemetryService; |
| 209 | ++ } |
| 210 | + } else { |
| 211 | + this.impl = NullTelemetryService; |
| 212 | + } |
0 commit comments