mirror of https://github.com/coder/code-server.git
213 lines
8.8 KiB
Diff
213 lines
8.8 KiB
Diff
|
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
|
||
|
@@ -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
|
||
|
- 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;
|
||
|
}
|