Skip to content

Commit 3cf535e

Browse files
committed
Add telemetry and option to disable
1 parent 8a4da54 commit 3cf535e

File tree

7 files changed

+193
-2
lines changed

7 files changed

+193
-2
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ Quickstart guides for [Google Cloud](doc/admin/install/google_cloud.md), [AWS](d
4646
4747
How to [secure your setup](/doc/security/ssl.md).
4848
49+
### Telemetry
50+
51+
Use the `--disable-telemetry` flag to disable tracking ENTIRELY.
52+
53+
We use data collected to improve code-server.
54+
4955
## Development
5056
5157
### Known Issues

packages/server/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"build:binary": "ts-node scripts/nbin.ts"
1010
},
1111
"dependencies": {
12-
"@coder/nbin": "^1.1.1",
12+
"@coder/nbin": "^1.1.2",
1313
"commander": "^2.19.0",
1414
"express": "^4.16.4",
1515
"express-static-gzip": "^1.1.3",

packages/server/src/cli.ts

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ commander.version(process.env.VERSION || "development")
2929
.option("-N, --no-auth", "Start without requiring authentication.", undefined)
3030
.option("-H, --allow-http", "Allow http connections.", false)
3131
.option("-P, --password <value>", "Specify a password for authentication.")
32+
.option("--disable-telemetry", "Disables ALL telemetry.", false)
3233
.option("--bootstrap-fork <name>", "Used for development. Never set.")
3334
.option("--extra-args <args>", "Used for development. Never set.")
3435
.arguments("Specify working directory.")
@@ -51,6 +52,7 @@ const bold = (text: string | number): string | number => {
5152
readonly allowHttp: boolean;
5253
readonly host: string;
5354
readonly port: number;
55+
readonly disableTelemetry: boolean;
5456

5557
readonly userDataDir?: string;
5658
readonly extensionsDir?: string;
@@ -65,6 +67,10 @@ const bold = (text: string | number): string | number => {
6567
readonly extraArgs?: string;
6668
};
6769

70+
if (options.disableTelemetry) {
71+
process.env.DISABLE_TELEMETRY = "true";
72+
}
73+
6874
// Commander has an exception for `--no` prefixes. Here we'll adjust that.
6975
// tslint:disable-next-line:no-any
7076
const noAuthValue = (commander as any).auth;

packages/server/src/vscode/sharedProcess.ts

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class SharedProcess {
9292
env: {
9393
VSCODE_ALLOW_IO: "true",
9494
VSCODE_LOGS: process.env.VSCODE_LOGS,
95+
DISABLE_TELEMETRY: process.env.DISABLE_TELEMETRY,
9596
},
9697
}, this.userDataDir);
9798
this.activeProcess = activeProcess;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/**
2+
* Used by node
3+
*/
4+
import * as https from "https";
5+
import * as os from "os";
6+
7+
export const defaultClient = "filler";
8+
9+
export class TelemetryClient {
10+
public channel = {
11+
setUseDiskRetryCaching: (): void => undefined,
12+
};
13+
14+
public constructor() {
15+
//
16+
}
17+
18+
public trackEvent(options: {
19+
name: string;
20+
properties: object;
21+
measurements: object;
22+
}): void {
23+
if (!options.properties) {
24+
options.properties = {};
25+
}
26+
if (!options.measurements) {
27+
options.measurements = {};
28+
}
29+
30+
try {
31+
const cpus = os.cpus();
32+
// tslint:disable-next-line:no-any
33+
(options.measurements as any).cpu = {
34+
model: cpus[0].model,
35+
cores: cpus.length,
36+
};
37+
} catch (ex) {
38+
// Nothin
39+
}
40+
41+
try {
42+
// tslint:disable-next-line:no-any
43+
(options.measurements as any).memory = {
44+
virtual_free: os.freemem(),
45+
virtual_used: os.totalmem(),
46+
};
47+
} catch (ex) {
48+
//
49+
}
50+
51+
try {
52+
// tslint:disable:no-any
53+
(options.properties as any)["common.shell"] = os.userInfo().shell;
54+
(options.properties as any)["common.release"] = os.release();
55+
(options.properties as any)["common.arch"] = os.arch();
56+
// tslint:enable:no-any
57+
} catch (ex) {
58+
//
59+
}
60+
61+
try {
62+
// tslint:disable-next-line:no-any
63+
(options.properties as any)["common.machineId"] = machineIdSync();
64+
} catch (ex) {
65+
//
66+
}
67+
68+
try {
69+
const request = https.request({
70+
host: "v1.telemetry.coder.com",
71+
port: 443,
72+
path: "/track",
73+
method: "POST",
74+
headers: {
75+
"Content-Type": "application/json",
76+
},
77+
});
78+
request.on("error", () => {
79+
// Do nothing, we don"t really care
80+
});
81+
request.write(JSON.stringify(options));
82+
request.end();
83+
} catch (ex) {
84+
// Suppress all errs
85+
}
86+
}
87+
88+
public flush(options: {
89+
readonly callback: () => void;
90+
}): void {
91+
options.callback();
92+
}
93+
}
94+
95+
// Taken from https://github.com/automation-stack/node-machine-id
96+
import { exec, execSync } from "child_process";
97+
import { createHash } from "crypto";
98+
99+
const isWindowsProcessMixedOrNativeArchitecture = (): "" | "mixed" | "native" => {
100+
// detect if the node binary is the same arch as the Windows OS.
101+
// or if this is 32 bit node on 64 bit windows.
102+
if (process.platform !== "win32") {
103+
return "";
104+
}
105+
if (process.arch === "ia32" && process.env.hasOwnProperty("PROCESSOR_ARCHITEW6432")) {
106+
return "mixed";
107+
}
108+
109+
return "native";
110+
};
111+
112+
let { platform } = process,
113+
win32RegBinPath = {
114+
native: "%windir%\\System32",
115+
mixed: "%windir%\\sysnative\\cmd.exe /c %windir%\\System32",
116+
"": "",
117+
},
118+
guid = {
119+
darwin: "ioreg -rd1 -c IOPlatformExpertDevice",
120+
win32: `${win32RegBinPath[isWindowsProcessMixedOrNativeArchitecture()]}\\REG ` +
121+
"QUERY HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography " +
122+
"/v MachineGuid",
123+
linux: "( cat /var/lib/dbus/machine-id /etc/machine-id 2> /dev/null || hostname ) | head -n 1 || :",
124+
freebsd: "kenv -q smbios.system.uuid || sysctl -n kern.hostuuid",
125+
// tslint:disable-next-line:no-any
126+
} as any;
127+
128+
const hash = (guid: string): string => {
129+
return createHash("sha256").update(guid).digest("hex");
130+
};
131+
132+
const expose = (result: string): string => {
133+
switch (platform) {
134+
case "darwin":
135+
return result
136+
.split("IOPlatformUUID")[1]
137+
.split("\n")[0].replace(/\=|\s+|\"/ig, "")
138+
.toLowerCase();
139+
case "win32":
140+
return result
141+
.toString()
142+
.split("REG_SZ")[1]
143+
.replace(/\r+|\n+|\s+/ig, "")
144+
.toLowerCase();
145+
case "linux":
146+
return result
147+
.toString()
148+
.replace(/\r+|\n+|\s+/ig, "")
149+
.toLowerCase();
150+
case "freebsd":
151+
return result
152+
.toString()
153+
.replace(/\r+|\n+|\s+/ig, "")
154+
.toLowerCase();
155+
default:
156+
throw new Error(`Unsupported platform: ${process.platform}`);
157+
}
158+
};
159+
160+
let cachedMachineId: string | undefined;
161+
162+
const machineIdSync = (): string => {
163+
if (cachedMachineId) {
164+
return cachedMachineId;
165+
}
166+
let id: string = expose(execSync(guid[platform]).toString());
167+
cachedMachineId = hash(id);
168+
169+
return cachedMachineId;
170+
};

packages/vscode/src/fill/product.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ class Product implements IProductConfiguration {
1212
public tipsAndTricksUrl = "https://code.visualstudio.com/docs/getstarted/tips-and-tricks";
1313
public twitterUrl = "https://twitter.com/code";
1414
public licenseUrl = "https://github.com/codercom/code-server/blob/master/LICENSE";
15+
public aiConfig = process.env.DISABLE_TELEMETRY ? undefined! : {
16+
// Only needed so vscode can see that content exists for this value.
17+
// We override the application insights module.
18+
asimovKey: "content",
19+
};
20+
public enableTelemetry = process.env.DISABLE_TELEMETRY ? false : true;
1521

1622
private _dataFolderName: string | undefined;
1723
public get dataFolderName(): string {
@@ -26,7 +32,8 @@ class Product implements IProductConfiguration {
2632
serviceUrl: global && global.process && global.process.env.SERVICE_URL
2733
|| process.env.SERVICE_URL
2834
|| "https://v1.extapi.coder.com",
29-
};
35+
// tslint:disable-next-line:no-any
36+
} as any;
3037

3138
public extensionExecutionEnvironments = {
3239
"wayou.vscode-todo-highlight": "worker",

packages/vscode/webpack.bootstrap.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ module.exports = merge(
5555
"vscode-sqlite3": path.resolve(fills, "empty.ts"),
5656
"vs/base/browser/browser": path.resolve(fills, "empty.ts"),
5757

58+
"applicationinsights": path.join(vsFills, "applicationInsights.ts"),
5859
"electron": path.join(vsFills, "stdioElectron.ts"),
5960
"vscode-ripgrep": path.join(vsFills, "ripgrep.ts"),
6061
"native-keymap": path.join(vsFills, "native-keymap.ts"),

0 commit comments

Comments
 (0)