@@ -17,16 +17,14 @@ import { Result } from './telemetry.gen'
17
17
import { MetricDatum } from './clienttelemetry'
18
18
import { isValidationExemptMetric } from './exemptMetrics'
19
19
import { isAmazonQ , isCloud9 , isSageMaker } from '../../shared/extensionUtilities'
20
- import { isExtensionInstalled , VSCODE_EXTENSION_ID } from '../utilities'
21
20
import { randomUUID } from '../crypto'
22
- import { activateExtension } from '../utilities/vsCodeUtils'
23
21
import { ClassToInterfaceType } from '../utilities/tsUtils'
24
22
25
23
const legacySettingsTelemetryValueDisable = 'Disable'
26
24
const legacySettingsTelemetryValueEnable = 'Enable'
27
25
28
26
const TelemetryFlag = addTypeName ( 'boolean' , convertLegacy )
29
- const telemetryClientIdEnvKey = '__TELEMETRY_CLIENT_ID'
27
+ export const telemetryClientIdEnvKey = '__TELEMETRY_CLIENT_ID'
30
28
31
29
export class TelemetryConfig {
32
30
private readonly _toolkitConfig
@@ -83,6 +81,19 @@ export function convertLegacy(value: unknown): boolean {
83
81
}
84
82
}
85
83
84
+ /**
85
+ * Calculates the clientId for the current profile. This calculation is performed once
86
+ * on first call and the result is stored for the remainder of the session.
87
+ *
88
+ * Web mode will always compute to whatever is stored in global state or vscode.machineId.
89
+ * For normal use, the clientId is fetched from the first providing source:
90
+ * 1. clientId stored in process.env
91
+ * 2. clientId stored in current extension's global state.
92
+ * 3. a random UUID
93
+ *
94
+ * The clientId in the current extension's global state AND the clientId stored in process.env
95
+ * is updated to the result of above to allow other extensions to converge to the same clientId.
96
+ */
86
97
export const getClientId = memoize (
87
98
/**
88
99
* @param nonce Dummy parameter to allow tests to defeat memoize().
@@ -100,11 +111,34 @@ export const getClientId = memoize(
100
111
return '11111111-1111-1111-1111-111111111111'
101
112
}
102
113
try {
103
- let clientId = globalState . tryGet ( 'telemetryClientId' , String )
104
- if ( ! clientId ) {
105
- clientId = randomUUID ( )
106
- globalState . tryUpdate ( 'telemetryClientId' , clientId )
114
+ const globalClientId = process . env [ telemetryClientIdEnvKey ] // truly global across all extensions
115
+ const localClientId = globalState . tryGet ( 'telemetryClientId' , String ) // local to extension, despite accessing "global" state
116
+ let clientId : string
117
+
118
+ if ( isWeb ( ) ) {
119
+ const machineId = vscode . env . machineId
120
+ clientId = localClientId ?? machineId
121
+ getLogger ( ) . debug (
122
+ 'getClientId: web mode determined clientId: %s, stored clientId was: %s, vscode.machineId was: %s' ,
123
+ clientId ,
124
+ localClientId ,
125
+ machineId
126
+ )
127
+ } else {
128
+ clientId = globalClientId ?? localClientId ?? randomUUID ( )
129
+ getLogger ( ) . debug (
130
+ 'getClientId: determined clientId as: %s, process.env clientId was: %s, stored clientId was: %s' ,
131
+ clientId ,
132
+ globalClientId ,
133
+ localClientId
134
+ )
135
+ if ( ! globalClientId ) {
136
+ getLogger ( ) . debug ( `getClientId: setting clientId in process.env to: %s` , clientId )
137
+ process . env [ telemetryClientIdEnvKey ] = clientId
138
+ }
107
139
}
140
+
141
+ globalState . tryUpdate ( 'telemetryClientId' , clientId )
108
142
return clientId
109
143
} catch ( e ) {
110
144
getLogger ( ) . error ( 'getClientId: failed to create client id: %O' , e )
@@ -205,53 +239,6 @@ export function validateMetricEvent(event: MetricDatum, fatal: boolean) {
205
239
}
206
240
}
207
241
208
- /**
209
- * Setup the telemetry client id at extension activation.
210
- * This function is designed to let AWS Toolkit and Amazon Q share
211
- * the same telemetry client id.
212
- */
213
- export async function setupTelemetryId ( extensionContext : vscode . ExtensionContext ) {
214
- try {
215
- if ( isWeb ( ) ) {
216
- await globals . globalState . update ( 'telemetryClientId' , vscode . env . machineId )
217
- } else {
218
- const currentClientId = globals . globalState . tryGet ( 'telemetryClientId' , String )
219
- const storedClientId = process . env [ telemetryClientIdEnvKey ]
220
- if ( currentClientId && storedClientId ) {
221
- if ( extensionContext . extension . id === VSCODE_EXTENSION_ID . awstoolkit ) {
222
- getLogger ( ) . debug ( `telemetry: Store telemetry client id to env ${ currentClientId } ` )
223
- process . env [ telemetryClientIdEnvKey ] = currentClientId
224
- // notify amazon q to use this stored client id
225
- // if amazon q activates first. Do not block on activate amazon q
226
- if ( isExtensionInstalled ( VSCODE_EXTENSION_ID . amazonq ) ) {
227
- void activateExtension ( VSCODE_EXTENSION_ID . amazonq ) . then ( async ( ) => {
228
- getLogger ( ) . debug ( `telemetry: notifying Amazon Q to adopt client id ${ currentClientId } ` )
229
- await vscode . commands . executeCommand ( 'aws.amazonq.setupTelemetryId' )
230
- } )
231
- }
232
- } else if ( isAmazonQ ( ) ) {
233
- getLogger ( ) . debug ( `telemetry: Set telemetry client id to ${ storedClientId } ` )
234
- await globals . globalState . update ( 'telemetryClientId' , storedClientId )
235
- } else {
236
- getLogger ( ) . error ( `Unexpected extension id ${ extensionContext . extension . id } ` )
237
- }
238
- } else if ( ! currentClientId && storedClientId ) {
239
- getLogger ( ) . debug ( `telemetry: Write telemetry client id to global state ${ storedClientId } ` )
240
- await globals . globalState . update ( 'telemetryClientId' , storedClientId )
241
- } else if ( currentClientId && ! storedClientId ) {
242
- getLogger ( ) . debug ( `telemetry: Write telemetry client id to env ${ currentClientId } ` )
243
- process . env [ telemetryClientIdEnvKey ] = currentClientId
244
- } else {
245
- const clientId = getClientId ( globals . globalState )
246
- getLogger ( ) . debug ( `telemetry: Setup telemetry client id ${ clientId } ` )
247
- process . env [ telemetryClientIdEnvKey ] = clientId
248
- }
249
- }
250
- } catch ( err ) {
251
- getLogger ( ) . error ( `Error while setting up telemetry id ${ err } ` )
252
- }
253
- }
254
-
255
242
/**
256
243
* Potentially helpful values for the 'source' field in telemetry.
257
244
*/
0 commit comments