1
- import type {
2
- Extension ,
3
- ExtensionContext ,
4
- ConfigurationChangeEvent ,
5
- } from "vscode" ;
6
- import { ConfigurationTarget , env } from "vscode" ;
1
+ import type { Extension , ExtensionContext } from "vscode" ;
7
2
import TelemetryReporter from "vscode-extension-telemetry" ;
8
- import {
9
- ConfigListener ,
10
- CANARY_FEATURES ,
11
- ENABLE_TELEMETRY ,
12
- LOG_TELEMETRY ,
13
- isIntegrationTestMode ,
14
- isCanary ,
15
- } from "../../config" ;
3
+ import { LOG_TELEMETRY , isCanary } from "../../config" ;
16
4
import type { TelemetryClient } from "applicationinsights" ;
17
5
import { extLogger } from "../logging/vscode" ;
18
6
import { UserCancellationException } from "./progress" ;
19
- import { showBinaryChoiceWithUrlDialog } from "./dialog" ;
20
7
import type { RedactableError } from "../errors" ;
21
8
import type { SemVer } from "semver" ;
22
9
import type { AppTelemetry } from "../telemetry" ;
23
10
import type { EnvelopeTelemetry } from "applicationinsights/out/Declarations/Contracts" ;
11
+ import type { Disposable } from "../disposable-object" ;
24
12
25
13
// Key is injected at build time through the APP_INSIGHTS_KEY environment variable.
26
14
const key = "REPLACE-APP-INSIGHTS-KEY" ;
@@ -55,80 +43,25 @@ const baseDataPropertiesToRemove = [
55
43
56
44
const NOT_SET_CLI_VERSION = "not-set" ;
57
45
58
- export class ExtensionTelemetryListener
59
- extends ConfigListener
60
- implements AppTelemetry
61
- {
62
- private reporter ?: TelemetryReporter ;
46
+ export class ExtensionTelemetryListener implements AppTelemetry , Disposable {
47
+ private readonly reporter : TelemetryReporter ;
63
48
64
49
private cliVersionStr = NOT_SET_CLI_VERSION ;
65
50
66
- constructor (
67
- private readonly id : string ,
68
- private readonly version : string ,
69
- private readonly key : string ,
70
- private readonly ctx : ExtensionContext ,
71
- ) {
72
- super ( ) ;
73
-
74
- env . onDidChangeTelemetryEnabled ( async ( ) => {
75
- await this . initialize ( ) ;
76
- } ) ;
77
- }
78
-
79
- /**
80
- * This function handles changes to relevant configuration elements. There are 2 configuration
81
- * ids that this function cares about:
82
- *
83
- * * `codeQL.telemetry.enableTelemetry`: If this one has changed, then we need to re-initialize
84
- * the reporter and the reporter may wind up being removed.
85
- * * `codeQL.canary`: A change here could possibly re-trigger a dialog popup.
86
- *
87
- * Note that the global telemetry setting also gate-keeps whether or not to send telemetry events
88
- * to Application Insights. However, this gatekeeping happens inside of the vscode-extension-telemetry
89
- * package. So, this does not need to be handled here.
90
- *
91
- * @param e the configuration change event
92
- */
93
- async handleDidChangeConfiguration (
94
- e : ConfigurationChangeEvent ,
95
- ) : Promise < void > {
96
- if ( e . affectsConfiguration ( ENABLE_TELEMETRY . qualifiedName ) ) {
97
- await this . initialize ( ) ;
98
- }
99
-
100
- // Re-request telemetry so that users can see the dialog again.
101
- // Re-request if codeQL.canary is being set to `true` and telemetry
102
- // is not currently enabled.
103
- if (
104
- e . affectsConfiguration ( CANARY_FEATURES . qualifiedName ) &&
105
- CANARY_FEATURES . getValue ( ) &&
106
- ! ENABLE_TELEMETRY . getValue ( )
107
- ) {
108
- await this . setTelemetryRequested ( false ) ;
109
- await this . requestTelemetryPermission ( ) ;
110
- }
111
- }
112
-
113
- async initialize ( ) {
114
- await this . requestTelemetryPermission ( ) ;
115
-
116
- this . disposeReporter ( ) ;
117
-
118
- if ( ENABLE_TELEMETRY . getValue < boolean > ( ) ) {
119
- this . createReporter ( ) ;
120
- }
121
- }
122
-
123
- private createReporter ( ) {
51
+ constructor ( id : string , version : string , key : string ) {
52
+ // We can always initialize this and send events using it because the vscode-extension-telemetry will check
53
+ // whether the `telemetry.telemetryLevel` setting is enabled.
124
54
this . reporter = new TelemetryReporter (
125
- this . id ,
126
- this . version ,
127
- this . key ,
55
+ id ,
56
+ version ,
57
+ key ,
128
58
/* anonymize stack traces */ true ,
129
59
) ;
130
- this . push ( this . reporter ) ;
131
60
61
+ this . addTelemetryProcessor ( ) ;
62
+ }
63
+
64
+ private addTelemetryProcessor ( ) {
132
65
// The appInsightsClient field is private but we want to access it anyway
133
66
const client = this . reporter [ "appInsightsClient" ] as TelemetryClient ;
134
67
if ( client ) {
@@ -151,14 +84,10 @@ export class ExtensionTelemetryListener
151
84
}
152
85
153
86
dispose ( ) {
154
- super . dispose ( ) ;
155
- void this . reporter ?. dispose ( ) ;
87
+ void this . reporter . dispose ( ) ;
156
88
}
157
89
158
90
sendCommandUsage ( name : string , executionTime : number , error ?: Error ) : void {
159
- if ( ! this . reporter ) {
160
- return ;
161
- }
162
91
const status = ! error
163
92
? CommandCompletion . Success
164
93
: error instanceof UserCancellationException
@@ -178,10 +107,6 @@ export class ExtensionTelemetryListener
178
107
}
179
108
180
109
sendUIInteraction ( name : string ) : void {
181
- if ( ! this . reporter ) {
182
- return ;
183
- }
184
-
185
110
this . reporter . sendTelemetryEvent (
186
111
"ui-interaction" ,
187
112
{
@@ -197,10 +122,6 @@ export class ExtensionTelemetryListener
197
122
error : RedactableError ,
198
123
extraProperties ?: { [ key : string ] : string } ,
199
124
) : void {
200
- if ( ! this . reporter ) {
201
- return ;
202
- }
203
-
204
125
const properties : { [ key : string ] : string } = {
205
126
isCanary : isCanary ( ) . toString ( ) ,
206
127
cliVersion : this . cliVersionStr ,
@@ -215,10 +136,6 @@ export class ExtensionTelemetryListener
215
136
}
216
137
217
138
sendConfigInformation ( config : Record < string , string > ) : void {
218
- if ( ! this . reporter ) {
219
- return ;
220
- }
221
-
222
139
this . reporter . sendTelemetryEvent (
223
140
"config" ,
224
141
{
@@ -230,37 +147,6 @@ export class ExtensionTelemetryListener
230
147
) ;
231
148
}
232
149
233
- /**
234
- * Displays a popup asking the user if they want to enable telemetry
235
- * for this extension.
236
- */
237
- async requestTelemetryPermission ( ) {
238
- if ( ! this . wasTelemetryRequested ( ) ) {
239
- // if global telemetry is disabled, avoid showing the dialog or making any changes
240
- let result = undefined ;
241
- if (
242
- env . isTelemetryEnabled &&
243
- // Avoid showing the dialog if we are in integration test mode.
244
- ! isIntegrationTestMode ( )
245
- ) {
246
- // Extension won't start until this completes.
247
- result = await showBinaryChoiceWithUrlDialog (
248
- "Does the CodeQL Extension by GitHub have your permission to collect usage data and metrics to help us improve CodeQL for VSCode?" ,
249
- "https://codeql.github.com/docs/codeql-for-visual-studio-code/about-telemetry-in-codeql-for-visual-studio-code" ,
250
- ) ;
251
- }
252
- if ( result !== undefined ) {
253
- await Promise . all ( [
254
- this . setTelemetryRequested ( true ) ,
255
- ENABLE_TELEMETRY . updateValue < boolean > (
256
- result ,
257
- ConfigurationTarget . Global ,
258
- ) ,
259
- ] ) ;
260
- }
261
- }
262
- }
263
-
264
150
/**
265
151
* Exposed for testing
266
152
*/
@@ -271,21 +157,6 @@ export class ExtensionTelemetryListener
271
157
set cliVersion ( version : SemVer | undefined ) {
272
158
this . cliVersionStr = version ? version . toString ( ) : NOT_SET_CLI_VERSION ;
273
159
}
274
-
275
- private disposeReporter ( ) {
276
- if ( this . reporter ) {
277
- void this . reporter . dispose ( ) ;
278
- this . reporter = undefined ;
279
- }
280
- }
281
-
282
- private wasTelemetryRequested ( ) : boolean {
283
- return ! ! this . ctx . globalState . get < boolean > ( "telemetry-request-viewed" ) ;
284
- }
285
-
286
- private async setTelemetryRequested ( newValue : boolean ) : Promise < void > {
287
- await this . ctx . globalState . update ( "telemetry-request-viewed" , newValue ) ;
288
- }
289
160
}
290
161
291
162
/**
@@ -305,11 +176,7 @@ export async function initializeTelemetry(
305
176
extension . id ,
306
177
extension . packageJSON . version ,
307
178
key ,
308
- ctx ,
309
179
) ;
310
- // do not await initialization, since doing so will sometimes cause a modal popup.
311
- // this is a particular problem during integration tests, which will hang if a modal popup is displayed.
312
- void telemetryListener . initialize ( ) ;
313
180
ctx . subscriptions . push ( telemetryListener ) ;
314
181
return telemetryListener ;
315
182
}
0 commit comments