Skip to content

Commit b623f92

Browse files
Merge pull request #2824 from github/robertbrignull/telemetry
Respect "telemetry.telemetryLevel" as well as "telemetry.enableTelemetry"
2 parents 08342f1 + 2b0bd84 commit b623f92

File tree

4 files changed

+58
-39
lines changed

4 files changed

+58
-39
lines changed

extensions/ql-vscode/package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,20 @@
446446
"type": "boolean",
447447
"default": false,
448448
"scope": "application",
449-
"markdownDescription": "Specifies whether to send CodeQL usage telemetry. This setting AND the global `#telemetry.enableTelemetry#` setting must be checked for telemetry to be sent to GitHub. For more information, see the [telemetry documentation](https://codeql.github.com/docs/codeql-for-visual-studio-code/about-telemetry-in-codeql-for-visual-studio-code)"
449+
"markdownDescription": "Specifies whether to send CodeQL usage telemetry. This setting AND the one of the global telemetry settings (`#telemetry.enableTelemetry#` or `#telemetry.telemetryLevel#`) must be enabled for telemetry to be sent to GitHub. For more information, see the [telemetry documentation](https://codeql.github.com/docs/codeql-for-visual-studio-code/about-telemetry-in-codeql-for-visual-studio-code)",
450+
"tags": [
451+
"telemetry",
452+
"usesOnlineServices"
453+
]
450454
},
451455
"codeQL.telemetry.logTelemetry": {
452456
"type": "boolean",
453457
"default": false,
454458
"scope": "application",
455-
"description": "Specifies whether or not to write telemetry events to the extension log."
459+
"description": "Specifies whether or not to write telemetry events to the extension log.",
460+
"tags": [
461+
"telemetry"
462+
]
456463
}
457464
}
458465
}

extensions/ql-vscode/src/common/vscode/telemetry.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import {
33
Extension,
44
ExtensionContext,
55
ConfigurationChangeEvent,
6+
env,
67
} from "vscode";
78
import TelemetryReporter from "vscode-extension-telemetry";
89
import {
910
ConfigListener,
1011
CANARY_FEATURES,
1112
ENABLE_TELEMETRY,
12-
GLOBAL_ENABLE_TELEMETRY,
1313
LOG_TELEMETRY,
1414
isIntegrationTestMode,
1515
isCanary,
@@ -59,8 +59,6 @@ export class ExtensionTelemetryListener
5959
extends ConfigListener
6060
implements AppTelemetry
6161
{
62-
static relevantSettings = [ENABLE_TELEMETRY, CANARY_FEATURES];
63-
6462
private reporter?: TelemetryReporter;
6563

6664
private cliVersionStr = NOT_SET_CLI_VERSION;
@@ -72,6 +70,10 @@ export class ExtensionTelemetryListener
7270
private readonly ctx: ExtensionContext,
7371
) {
7472
super();
73+
74+
env.onDidChangeTelemetryEnabled(async () => {
75+
await this.initialize();
76+
});
7577
}
7678

7779
/**
@@ -91,18 +93,15 @@ export class ExtensionTelemetryListener
9193
async handleDidChangeConfiguration(
9294
e: ConfigurationChangeEvent,
9395
): Promise<void> {
94-
if (
95-
e.affectsConfiguration("codeQL.telemetry.enableTelemetry") ||
96-
e.affectsConfiguration("telemetry.enableTelemetry")
97-
) {
96+
if (e.affectsConfiguration(ENABLE_TELEMETRY.qualifiedName)) {
9897
await this.initialize();
9998
}
10099

101100
// Re-request telemetry so that users can see the dialog again.
102101
// Re-request if codeQL.canary is being set to `true` and telemetry
103102
// is not currently enabled.
104103
if (
105-
e.affectsConfiguration("codeQL.canary") &&
104+
e.affectsConfiguration(CANARY_FEATURES.qualifiedName) &&
106105
CANARY_FEATURES.getValue() &&
107106
!ENABLE_TELEMETRY.getValue()
108107
) {
@@ -212,7 +211,7 @@ export class ExtensionTelemetryListener
212211
properties.stack = error.stack;
213212
}
214213

215-
this.reporter.sendTelemetryEvent("error", properties, {});
214+
this.reporter.sendTelemetryErrorEvent("error", properties, {});
216215
}
217216

218217
/**
@@ -224,7 +223,7 @@ export class ExtensionTelemetryListener
224223
// if global telemetry is disabled, avoid showing the dialog or making any changes
225224
let result = undefined;
226225
if (
227-
GLOBAL_ENABLE_TELEMETRY.getValue() &&
226+
env.isTelemetryEnabled &&
228227
// Avoid showing the dialog if we are in integration test mode.
229228
!isIntegrationTestMode()
230229
) {

extensions/ql-vscode/src/config.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,27 +72,15 @@ export const VSCODE_SAVE_BEFORE_START_SETTING = new Setting(
7272

7373
const ROOT_SETTING = new Setting("codeQL");
7474

75-
// Global configuration
75+
// Telemetry configuration
7676
const TELEMETRY_SETTING = new Setting("telemetry", ROOT_SETTING);
77-
const AST_VIEWER_SETTING = new Setting("astViewer", ROOT_SETTING);
78-
const CONTEXTUAL_QUERIES_SETTINGS = new Setting(
79-
"contextualQueries",
80-
ROOT_SETTING,
81-
);
82-
const GLOBAL_TELEMETRY_SETTING = new Setting("telemetry");
83-
const LOG_INSIGHTS_SETTING = new Setting("logInsights", ROOT_SETTING);
8477

8578
export const LOG_TELEMETRY = new Setting("logTelemetry", TELEMETRY_SETTING);
8679
export const ENABLE_TELEMETRY = new Setting(
8780
"enableTelemetry",
8881
TELEMETRY_SETTING,
8982
);
9083

91-
export const GLOBAL_ENABLE_TELEMETRY = new Setting(
92-
"enableTelemetry",
93-
GLOBAL_TELEMETRY_SETTING,
94-
);
95-
9684
// Distribution configuration
9785
const DISTRIBUTION_SETTING = new Setting("cli", ROOT_SETTING);
9886
export const CUSTOM_CODEQL_PATH_SETTING = new Setting(
@@ -475,6 +463,7 @@ export function allowCanaryQueryServer() {
475463
return value === undefined ? true : !!value;
476464
}
477465

466+
const LOG_INSIGHTS_SETTING = new Setting("logInsights", ROOT_SETTING);
478467
export const JOIN_ORDER_WARNING_THRESHOLD = new Setting(
479468
"joinOrderWarningThreshold",
480469
LOG_INSIGHTS_SETTING,
@@ -484,6 +473,7 @@ export function joinOrderWarningThreshold(): number {
484473
return JOIN_ORDER_WARNING_THRESHOLD.getValue<number>();
485474
}
486475

476+
const AST_VIEWER_SETTING = new Setting("astViewer", ROOT_SETTING);
487477
/**
488478
* Hidden setting: Avoids caching in the AST viewer if the user is also a canary user.
489479
*/
@@ -492,6 +482,10 @@ export const NO_CACHE_AST_VIEWER = new Setting(
492482
AST_VIEWER_SETTING,
493483
);
494484

485+
const CONTEXTUAL_QUERIES_SETTINGS = new Setting(
486+
"contextualQueries",
487+
ROOT_SETTING,
488+
);
495489
/**
496490
* Hidden setting: Avoids caching in jump to def and find refs contextual queries if the user is also a canary user.
497491
*/

extensions/ql-vscode/test/vscode-tests/no-workspace/telemetry.test.ts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
workspace,
55
ConfigurationTarget,
66
window,
7+
env,
78
} from "vscode";
89
import {
910
ExtensionTelemetryListener,
@@ -30,13 +31,18 @@ describe("telemetry reporting", () => {
3031
let sendTelemetryEventSpy: jest.SpiedFunction<
3132
typeof TelemetryReporter.prototype.sendTelemetryEvent
3233
>;
33-
let sendTelemetryExceptionSpy: jest.SpiedFunction<
34-
typeof TelemetryReporter.prototype.sendTelemetryException
34+
let sendTelemetryErrorEventSpy: jest.SpiedFunction<
35+
typeof TelemetryReporter.prototype.sendTelemetryErrorEvent
3536
>;
3637
let disposeSpy: jest.SpiedFunction<
3738
typeof TelemetryReporter.prototype.dispose
3839
>;
3940

41+
let isTelemetryEnabledSpy: jest.SpyInstance<
42+
typeof env.isTelemetryEnabled,
43+
[]
44+
>;
45+
4046
let showInformationMessageSpy: jest.SpiedFunction<
4147
typeof window.showInformationMessage
4248
>;
@@ -56,8 +62,8 @@ describe("telemetry reporting", () => {
5662
sendTelemetryEventSpy = jest
5763
.spyOn(TelemetryReporter.prototype, "sendTelemetryEvent")
5864
.mockReturnValue(undefined);
59-
sendTelemetryExceptionSpy = jest
60-
.spyOn(TelemetryReporter.prototype, "sendTelemetryException")
65+
sendTelemetryErrorEventSpy = jest
66+
.spyOn(TelemetryReporter.prototype, "sendTelemetryErrorEvent")
6167
.mockReturnValue(undefined);
6268
disposeSpy = jest
6369
.spyOn(TelemetryReporter.prototype, "dispose")
@@ -78,6 +84,9 @@ describe("telemetry reporting", () => {
7884
.get<boolean>("codeQL.canary")).toString();
7985

8086
// each test will default to telemetry being enabled
87+
isTelemetryEnabledSpy = jest
88+
.spyOn(env, "isTelemetryEnabled", "get")
89+
.mockReturnValue(true);
8190
await enableTelemetry("telemetry", true);
8291
await enableTelemetry("codeQL.telemetry", true);
8392

@@ -116,6 +125,7 @@ describe("telemetry reporting", () => {
116125
});
117126

118127
it("should initialize telemetry when global option disabled", async () => {
128+
isTelemetryEnabledSpy.mockReturnValue(false);
119129
await enableTelemetry("telemetry", false);
120130
await telemetryListener.initialize();
121131
expect(telemetryListener._reporter).toBeDefined();
@@ -133,6 +143,7 @@ describe("telemetry reporting", () => {
133143

134144
it("should not initialize telemetry when both options disabled", async () => {
135145
await enableTelemetry("codeQL.telemetry", false);
146+
isTelemetryEnabledSpy.mockReturnValue(false);
136147
await enableTelemetry("telemetry", false);
137148
await telemetryListener.initialize();
138149
expect(telemetryListener._reporter).toBeUndefined();
@@ -179,6 +190,7 @@ describe("telemetry reporting", () => {
179190
const reporter: any = telemetryListener._reporter;
180191
expect(reporter.userOptIn).toBe(true); // enabled
181192

193+
isTelemetryEnabledSpy.mockReturnValue(false);
182194
await enableTelemetry("telemetry", false);
183195
expect(reporter.userOptIn).toBe(false); // disabled
184196
});
@@ -198,8 +210,7 @@ describe("telemetry reporting", () => {
198210
},
199211
{ executionTime: 1234 },
200212
);
201-
202-
expect(sendTelemetryExceptionSpy).not.toBeCalled();
213+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
203214
});
204215

205216
it("should send a command usage event with an error", async () => {
@@ -221,8 +232,7 @@ describe("telemetry reporting", () => {
221232
},
222233
{ executionTime: 1234 },
223234
);
224-
225-
expect(sendTelemetryExceptionSpy).not.toBeCalled();
235+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
226236
});
227237

228238
it("should send a command usage event with a cli version", async () => {
@@ -245,8 +255,7 @@ describe("telemetry reporting", () => {
245255
},
246256
{ executionTime: 1234 },
247257
);
248-
249-
expect(sendTelemetryExceptionSpy).not.toBeCalled();
258+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
250259

251260
// Verify that if the cli version is not set, then the telemetry falls back to "not-set"
252261
sendTelemetryEventSpy.mockClear();
@@ -268,6 +277,7 @@ describe("telemetry reporting", () => {
268277
},
269278
{ executionTime: 5678 },
270279
);
280+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
271281
});
272282

273283
it("should avoid sending an event when telemetry is disabled", async () => {
@@ -278,7 +288,7 @@ describe("telemetry reporting", () => {
278288
telemetryListener.sendCommandUsage("command-id", 1234, new Error());
279289

280290
expect(sendTelemetryEventSpy).not.toBeCalled();
281-
expect(sendTelemetryExceptionSpy).not.toBeCalled();
291+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
282292
});
283293

284294
it("should send an event when telemetry is re-enabled", async () => {
@@ -298,6 +308,7 @@ describe("telemetry reporting", () => {
298308
},
299309
{ executionTime: 1234 },
300310
);
311+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
301312
});
302313

303314
it("should filter undesired properties from telemetry payload", async () => {
@@ -345,6 +356,8 @@ describe("telemetry reporting", () => {
345356
resolveArg(3 /* "yes" item */),
346357
);
347358
await ctx.globalState.update("telemetry-request-viewed", false);
359+
expect(env.isTelemetryEnabled).toBe(true);
360+
348361
await enableTelemetry("codeQL.telemetry", false);
349362

350363
await telemetryListener.initialize();
@@ -411,6 +424,7 @@ describe("telemetry reporting", () => {
411424
// If the user ever turns global telemetry back on, then we can
412425
// show the dialog.
413426

427+
isTelemetryEnabledSpy.mockReturnValue(false);
414428
await enableTelemetry("telemetry", false);
415429
await ctx.globalState.update("telemetry-request-viewed", false);
416430

@@ -455,6 +469,7 @@ describe("telemetry reporting", () => {
455469
},
456470
{},
457471
);
472+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
458473
});
459474

460475
it("should send a ui-interaction telementry event with a cli version", async () => {
@@ -472,14 +487,16 @@ describe("telemetry reporting", () => {
472487
},
473488
{},
474489
);
490+
expect(sendTelemetryErrorEventSpy).not.toBeCalled();
475491
});
476492

477493
it("should send an error telementry event", async () => {
478494
await telemetryListener.initialize();
479495

480496
telemetryListener.sendError(redactableError`test`);
481497

482-
expect(sendTelemetryEventSpy).toHaveBeenCalledWith(
498+
expect(sendTelemetryEventSpy).not.toBeCalled();
499+
expect(sendTelemetryErrorEventSpy).toHaveBeenCalledWith(
483500
"error",
484501
{
485502
message: "test",
@@ -497,7 +514,8 @@ describe("telemetry reporting", () => {
497514

498515
telemetryListener.sendError(redactableError`test`);
499516

500-
expect(sendTelemetryEventSpy).toHaveBeenCalledWith(
517+
expect(sendTelemetryEventSpy).not.toBeCalled();
518+
expect(sendTelemetryErrorEventSpy).toHaveBeenCalledWith(
501519
"error",
502520
{
503521
message: "test",
@@ -516,7 +534,8 @@ describe("telemetry reporting", () => {
516534
redactableError`test message with secret information: ${42} and more ${"secret"} parts`,
517535
);
518536

519-
expect(sendTelemetryEventSpy).toHaveBeenCalledWith(
537+
expect(sendTelemetryEventSpy).not.toBeCalled();
538+
expect(sendTelemetryErrorEventSpy).toHaveBeenCalledWith(
520539
"error",
521540
{
522541
message:

0 commit comments

Comments
 (0)