Skip to content

Commit 6f6fedb

Browse files
refactor: sync isFirstUse w/ ClientId
Problem: We were seeing some cases where the ClientId was seen as new, but ifFirstUse was reporting as not new. Solution: Validate that if we have a new ClientId, that isFirstUse MUST be true. Otherwise we emit an error, that should help us debug certain cases. Signed-off-by: nkomonen-amazon <[email protected]>
1 parent a5ab6c3 commit 6f6fedb

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

packages/core/src/auth/utils.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import { EcsCredentialsProvider } from './providers/ecsCredentialsProvider'
5858
import { EnvVarsCredentialsProvider } from './providers/envVarsCredentialsProvider'
5959
import { showMessageWithUrl } from '../shared/utilities/messages'
6060
import { credentialHelpUrl } from '../shared/constants'
61-
import { ExtStartUpSources, ExtStartUpSource } from '../shared/telemetry/util'
61+
import { ExtStartUpSources, ExtStartUpSource, hadClientIdOnStartup } from '../shared/telemetry/util'
6262

6363
// iam-only excludes Builder ID and IAM Identity Center from the list of valid connections
6464
// TODO: Understand if "iam" should include these from the list at all
@@ -695,6 +695,18 @@ export class ExtensionUse {
695695
return this.isFirstUseCurrentSession
696696
}
697697

698+
/**
699+
* SANITY CHECK: If the clientId already existed on startup, then isFirstUse MUST be false. So
700+
* there is a bug in the state.
701+
*/
702+
if (hadClientIdOnStartup(globals.globalState)) {
703+
telemetry.function_call.emit({
704+
result: 'Failed',
705+
functionName: 'isFirstUse',
706+
reason: 'ClientIdAlreadyExisted',
707+
})
708+
}
709+
698710
if (isAmazonQ()) {
699711
this.isFirstUseCurrentSession = true
700712
} else {

packages/core/src/shared/telemetry/util.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { asStringifiedStack, FunctionEntry } from './spans'
3030
import { telemetry } from './telemetry'
3131
import { v5 as uuidV5 } from 'uuid'
3232
import { ToolkitError } from '../errors'
33+
import { GlobalState } from '../globalState'
3334

3435
const legacySettingsTelemetryValueDisable = 'Disable'
3536
const legacySettingsTelemetryValueEnable = 'Enable'
@@ -177,6 +178,8 @@ export const getClientId = memoize(
177178
const localClientId = globalState.tryGet('telemetryClientId', String) // local to extension, despite accessing "global" state
178179
let clientId: string
179180

181+
_hadClientIdOnStartup = !!globalClientId || !!localClientId
182+
180183
if (isWeb()) {
181184
const machineId = vscode.env.machineId
182185
clientId = localClientId ?? machineId
@@ -210,6 +213,17 @@ export const getClientId = memoize(
210213
}
211214
)
212215

216+
let _hadClientIdOnStartup = false
217+
/**
218+
* Returns true if the ClientID existed before this session started
219+
*/
220+
export const hadClientIdOnStartup = (globalState: GlobalState) => {
221+
// triggers the flow that will update the state, if not done already
222+
getClientId(globalState)
223+
224+
return _hadClientIdOnStartup
225+
}
226+
213227
export const platformPair = () => `${env.appName.replace(/\s/g, '-')}/${version}`
214228

215229
/**

packages/core/src/test/shared/telemetry/util.test.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
convertLegacy,
1111
getClientId,
1212
getUserAgent,
13+
hadClientIdOnStartup,
1314
platformPair,
1415
SessionId,
1516
telemetryClientIdEnvKey,
@@ -128,20 +129,24 @@ describe('getSessionId', function () {
128129

129130
describe('getClientId', function () {
130131
before(function () {
131-
delete process.env[telemetryClientIdEnvKey]
132+
setClientIdEnvVar(undefined)
132133
})
133134

134135
afterEach(function () {
135-
delete process.env[telemetryClientIdEnvKey]
136+
setClientIdEnvVar(undefined)
136137
})
137138

138139
function testGetClientId(globalState: GlobalState) {
139140
return getClientId(globalState, true, false, randomUUID())
140141
}
141142

143+
function setClientIdEnvVar(val: string | undefined) {
144+
process.env[telemetryClientIdEnvKey] = val
145+
}
146+
142147
it('generates a unique id if no other id is available', function () {
143148
const c1 = testGetClientId(new GlobalState(new FakeMemento()))
144-
delete process.env[telemetryClientIdEnvKey]
149+
setClientIdEnvVar(undefined)
145150
const c2 = testGetClientId(new GlobalState(new FakeMemento()))
146151
assert.notStrictEqual(c1, c2)
147152
})
@@ -160,7 +165,7 @@ describe('getClientId', function () {
160165

161166
const e = new GlobalState(new FakeMemento())
162167
await e.update('telemetryClientId', randomUUID())
163-
process.env[telemetryClientIdEnvKey] = expectedClientId
168+
setClientIdEnvVar(expectedClientId)
164169

165170
assert.strictEqual(testGetClientId(new GlobalState(new FakeMemento())), expectedClientId)
166171
})
@@ -218,6 +223,25 @@ describe('getClientId', function () {
218223
const clientId = getClientId(new GlobalState(new FakeMemento()), false, false)
219224
assert.strictEqual(clientId, '11111111-1111-1111-1111-111111111111')
220225
})
226+
227+
describe('hadClientIdOnStartup', async function () {
228+
it('returns false when no existing clientId', async function () {
229+
const globalState = new GlobalState(new FakeMemento())
230+
assert.strictEqual(hadClientIdOnStartup(globalState), false)
231+
})
232+
233+
it('returns true when existing env var clientId', async function () {
234+
const globalState = new GlobalState(new FakeMemento())
235+
setClientIdEnvVar('aaa-111')
236+
assert.strictEqual(hadClientIdOnStartup(globalState), true)
237+
})
238+
239+
it('returns true when existing state clientId', async function () {
240+
const globalState = new GlobalState(new FakeMemento())
241+
await globalState.update('telemetryClientId', 'bbb-222')
242+
assert.strictEqual(hadClientIdOnStartup(globalState), true)
243+
})
244+
})
221245
})
222246

223247
describe('getUserAgent', function () {

0 commit comments

Comments
 (0)