Skip to content

Commit 8364ae2

Browse files
authored
feat(amazonq): Add telemetry for auth through LSP (#7224)
## Problem The new auth util on Flare LSP is not yet supporting telemetry events ## Solution * Migrate `getTelemetryMetadata` and `getAuthFormIds` to the new AuthUtil * Restore commented-out references **Note: CI is exepected to fail, unti tests not yet addressed and rebase with mainline is needed** --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 5c7b029 commit 8364ae2

File tree

4 files changed

+101
-45
lines changed

4 files changed

+101
-45
lines changed

packages/amazonq/src/extensionNode.ts

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ import * as vscode from 'vscode'
77
import { activateAmazonQCommon, amazonQContextPrefix, deactivateCommon } from './extension'
88
import { DefaultAmazonQAppInitContext } from 'aws-core-vscode/amazonq'
99
import { activate as activateQGumby } from 'aws-core-vscode/amazonqGumby'
10-
import { ExtContext, globals, CrashMonitoring /* getLogger, isSageMaker,*/, Experiments } from 'aws-core-vscode/shared'
10+
import { ExtContext, globals, CrashMonitoring, getLogger, isSageMaker, Experiments } from 'aws-core-vscode/shared'
1111
import { filetypes, SchemaService } from 'aws-core-vscode/sharedNode'
1212
import { updateDevMode } from 'aws-core-vscode/dev'
1313
import { CommonAuthViewProvider } from 'aws-core-vscode/login'
1414
import { isExtensionActive, VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
1515
import { registerSubmitFeedback } from 'aws-core-vscode/feedback'
1616
import { DevOptions } from 'aws-core-vscode/dev'
17-
import { Auth /* , AuthUtils, getTelemetryMetadataForConn, isAnySsoConnection*/ } from 'aws-core-vscode/auth'
17+
import { Auth, authUtils } from 'aws-core-vscode/auth'
1818
import api from './api'
1919
import { activate as activateCWChat } from './app/chat/activation'
2020
import { activate as activateInlineChat } from './inlineChat/activation'
2121
import { beta } from 'aws-core-vscode/dev'
2222
import * as amazonq from 'aws-core-vscode/amazonq'
23-
import { /* activate as activateNotifications,*/ NotificationsController } from 'aws-core-vscode/notifications'
24-
// import { AuthState, AuthUtil } from 'aws-core-vscode/codewhisperer'
25-
// import { telemetry, AuthUserState } from 'aws-core-vscode/telemetry'
23+
import { activate as activateNotifications, NotificationsController } from 'aws-core-vscode/notifications'
24+
import { AuthUtil } from 'aws-core-vscode/codewhisperer'
25+
import { telemetry, AuthUserState, AuthStatus } from 'aws-core-vscode/telemetry'
2626

2727
export async function activate(context: vscode.ExtensionContext) {
2828
// IMPORTANT: No other code should be added to this function. Place it in one of the following 2 functions where appropriate.
@@ -73,34 +73,32 @@ async function activateAmazonQNode(context: vscode.ExtensionContext) {
7373
await setupDevMode(context)
7474
await beta.activate(context)
7575

76-
// TODO: @opieter Fix telemetry
77-
// Will the web metric look the same?
78-
// telemetry.auth_userState.emit({
79-
// passive: true,
80-
// result: 'Succeeded',
81-
// source: AuthUtils.ExtensionUse.instance.sourceForTelemetry(),
82-
// ...(await getAuthState()),
83-
// })
76+
await getAuthState()
77+
telemetry.auth_userState.emit({
78+
passive: true,
79+
result: 'Succeeded',
80+
source: authUtils.ExtensionUse.instance.sourceForTelemetry(),
81+
authStatus: AuthUtil.instance.getAuthState(),
82+
authEnabledConnections: (await AuthUtil.instance.getAuthFormIds()).join(','),
83+
})
8484

85-
// void activateNotifications(context, getAuthState)
85+
void activateNotifications(context, getAuthState)
8686
}
8787

88-
// async function getAuthState(): Promise<Omit<auth2.AuthState, 'source'>> {
89-
// let authState: AuthState = 'disconnected'
90-
// authState = AuthUtil.instance.getAuthState()
91-
92-
// if (AuthUtil.instance.isConnected() && !(AuthUtil.instance.isSsoSession() || isSageMaker())) {
93-
// getLogger().error('Current Amazon Q connection is not SSO')
94-
// }
95-
96-
// return {
97-
// authStatus:
98-
// authState === 'connected' || authState === 'expired'
99-
// ? authState
100-
// : 'notConnected',
101-
// ...(await getTelemetryMetadataForConn(currConn)),
102-
// }
103-
// }
88+
async function getAuthState(): Promise<Omit<AuthUserState, 'source'>> {
89+
const state = AuthUtil.instance.getAuthState()
90+
91+
if (AuthUtil.instance.isConnected() && !(AuthUtil.instance.isSsoSession() || isSageMaker())) {
92+
getLogger().error('Current Amazon Q connection is not SSO')
93+
}
94+
95+
return {
96+
// @ts-ignore
97+
authStatus: (state ?? 'notConnected') as AuthStatus,
98+
authEnabledConnections: (await AuthUtil.instance.getAuthFormIds()).join(','),
99+
...AuthUtil.instance.getTelemetryMetadata(),
100+
}
101+
}
104102

105103
/**
106104
* Some parts of this do not work in Web mode so we need to set Dev Mode up here.

packages/core/src/codewhisperer/util/authUtil.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ import * as localizedText from '../../shared/localizedText'
88
import * as nls from 'vscode-nls'
99
import { ToolkitError } from '../../shared/errors'
1010
import { AmazonQPromptSettings } from '../../shared/settings'
11-
import { scopesCodeWhispererCore, scopesCodeWhispererChat, scopesFeatureDev, scopesGumby } from '../../auth/connection'
11+
import {
12+
scopesCodeWhispererCore,
13+
scopesCodeWhispererChat,
14+
scopesFeatureDev,
15+
scopesGumby,
16+
TelemetryMetadata,
17+
scopesSsoAccountAccess,
18+
hasScopes,
19+
} from '../../auth/connection'
1220
import { getLogger } from '../../shared/logger/logger'
1321
import { Commands } from '../../shared/vscode/commands2'
1422
import { vsCodeState } from '../models/model'
@@ -21,6 +29,7 @@ import { AuthStateEvent, LanguageClientAuth, LoginTypes, SsoLogin } from '../../
2129
import { builderIdStartUrl } from '../../auth/sso/constants'
2230
import { VSCODE_EXTENSION_ID } from '../../shared/extensions'
2331
import { RegionProfileManager } from '../region/regionProfileManager'
32+
import { AuthFormId } from '../../login/webview/vue/types'
2433

2534
const localize = nls.loadMessageBundle()
2635

@@ -260,4 +269,55 @@ export class AuthUtil implements IAuthProvider {
260269
void vscode.commands.executeCommand('aws.amazonq.notifyNewCustomizations')
261270
}
262271
}
272+
273+
async getTelemetryMetadata(): Promise<TelemetryMetadata> {
274+
if (!this.isConnected()) {
275+
return {
276+
id: 'undefined',
277+
}
278+
}
279+
280+
if (this.isSsoSession()) {
281+
const ssoSessionDetails = (await this.session.getProfile()).ssoSession?.settings
282+
return {
283+
authScopes: ssoSessionDetails?.sso_registration_scopes?.join(','),
284+
credentialSourceId: AuthUtil.instance.isBuilderIdConnection() ? 'awsId' : 'iamIdentityCenter',
285+
credentialStartUrl: AuthUtil.instance.connection?.startUrl,
286+
awsRegion: AuthUtil.instance.connection?.region,
287+
}
288+
} else if (!AuthUtil.instance.isSsoSession) {
289+
return {
290+
credentialSourceId: 'sharedCredentials',
291+
}
292+
}
293+
294+
throw new Error('getTelemetryMetadataForConn() called with unknown connection type')
295+
}
296+
297+
async getAuthFormIds(): Promise<AuthFormId[]> {
298+
if (!this.isConnected()) {
299+
return []
300+
}
301+
302+
const authIds: AuthFormId[] = []
303+
let connType: 'builderId' | 'identityCenter'
304+
305+
// TODO: update when there is IAM support
306+
if (!this.isSsoSession()) {
307+
return ['credentials']
308+
} else if (this.isBuilderIdConnection()) {
309+
connType = 'builderId'
310+
} else if (this.isIdcConnection()) {
311+
connType = 'identityCenter'
312+
const ssoSessionDetails = (await this.session.getProfile()).ssoSession?.settings
313+
if (hasScopes(ssoSessionDetails?.sso_registration_scopes ?? [], scopesSsoAccountAccess)) {
314+
authIds.push('identityCenterExplorer')
315+
}
316+
} else {
317+
return ['unknown']
318+
}
319+
authIds.push(`${connType}CodeWhisperer`)
320+
321+
return authIds
322+
}
263323
}

packages/core/src/login/webview/commonAuthViewProvider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { telemetry } from '../../shared/telemetry/telemetry'
4545
import { AuthSources } from './util'
4646
import { AuthFlowStates } from './vue/types'
4747
import { ExtensionUse } from '../../auth/utils'
48+
import { AuthUtil } from '../../codewhisperer/util/authUtil'
4849

4950
export class CommonAuthViewProvider implements WebviewViewProvider {
5051
public readonly viewType: string
@@ -107,7 +108,7 @@ export class CommonAuthViewProvider implements WebviewViewProvider {
107108
if (authState === AuthFlowStates.REAUTHNEEDED || authState === AuthFlowStates.REAUTHENTICATING) {
108109
this.webView!.server.storeMetricMetadata({
109110
isReAuth: true,
110-
// ...(await getTelemetryMetadataForConn(AuthUtil.instance.conn)), // TODO: @opieter Re-add telemetry
111+
...(await AuthUtil.instance.getTelemetryMetadata()),
111112
})
112113
} else {
113114
this.webView!.server.storeMetricMetadata({ isReAuth: false })

packages/core/src/login/webview/vue/amazonq/backend_amazonq.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ export class AmazonQLoginWebview extends CommonAuthWebview {
6565
isReAuth: false,
6666
})
6767
await awsIdSignIn()
68-
// this.storeMetricMetadata(await getTelemetryMetadataForConn(conn))
69-
// TODO: @opieter re-add metrics
68+
this.storeMetricMetadata(await AuthUtil.instance.getTelemetryMetadata())
7069

7170
void vscode.window.showInformationMessage('AmazonQ: Successfully connected to AWS Builder ID')
7271
})
@@ -83,8 +82,7 @@ export class AmazonQLoginWebview extends CommonAuthWebview {
8382
})
8483

8584
await connectToEnterpriseSso(startUrl, region)
86-
// this.storeMetricMetadata(await getTelemetryMetadataForConn(conn))
87-
// TODO: @opieter re-add metrics
85+
this.storeMetricMetadata(await AuthUtil.instance.getTelemetryMetadata())
8886

8987
void vscode.window.showInformationMessage('AmazonQ: Successfully connected to AWS IAM Identity Center')
9088
})
@@ -110,16 +108,15 @@ export class AmazonQLoginWebview extends CommonAuthWebview {
110108
* causes the reauth page to refresh before the user is actually done the whole reauth flow.
111109
*/
112110
this.reauthError = await this.ssoSetup('reauthenticateAmazonQ', async () => {
113-
// TODO: @ opieter Re-add metrics
114-
// this.storeMetricMetadata({
115-
// authEnabledFeatures: this.getAuthEnabledFeatures(conn),
116-
// isReAuth: true,
117-
// ...(await getTelemetryMetadataForConn(conn)),
118-
// })
111+
this.storeMetricMetadata({
112+
authEnabledFeatures: 'codewhisperer',
113+
isReAuth: true,
114+
...(await AuthUtil.instance.getTelemetryMetadata()),
115+
})
119116
await AuthUtil.instance.reauthenticate()
120-
// this.storeMetricMetadata({
121-
// ...(await getTelemetryMetadataForConn(conn)),
122-
// })
117+
this.storeMetricMetadata({
118+
...(await AuthUtil.instance.getTelemetryMetadata()),
119+
})
123120
})
124121
} finally {
125122
this.isReauthenticating = false

0 commit comments

Comments
 (0)