Skip to content

Commit 6be4247

Browse files
committed
feat: add telemetry
1 parent 5369d57 commit 6be4247

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

packages/amazonq/src/inlineChat/provider/inlineChatProvider.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
ChatTriggerType,
1717
EditorContextExtractor,
1818
PromptMessage,
19+
TriggerEvent,
1920
TriggerEventsStorage,
2021
TriggerPayload,
2122
triggerPayloadToChatRequest,
@@ -30,6 +31,7 @@ import { extractAuthFollowUp } from 'aws-core-vscode/amazonq'
3031
import { InlineChatParams, InlineChatResult } from '@aws/language-server-runtimes-types'
3132
import { decryptResponse, encryptRequest } from '../../lsp/encryption'
3233
import { getCursorState } from '../../lsp/utils'
34+
import { CwsprChatTriggerInteraction, telemetry } from 'aws-core-vscode/telemetry'
3335

3436
export class InlineChatProvider {
3537
private readonly editorContextExtractor: EditorContextExtractor
@@ -68,7 +70,34 @@ export class InlineChatProvider {
6870
}
6971
}
7072

73+
private getTriggerInteractionFromTriggerEvent(triggerEvent: TriggerEvent | undefined): CwsprChatTriggerInteraction {
74+
switch (triggerEvent?.type) {
75+
case 'editor_context_command':
76+
return triggerEvent.command?.triggerType === 'keybinding' ? 'hotkeys' : 'contextMenu'
77+
case 'follow_up':
78+
case 'chat_message':
79+
default:
80+
return 'click'
81+
}
82+
}
83+
7184
public async processPromptMessageLSP(message: PromptMessage): Promise<InlineChatResult> {
85+
const triggerInteraction = this.getTriggerInteractionFromTriggerEvent(
86+
this.triggerEventsStorage.getLastTriggerEventByTabID(message.tabID)
87+
)
88+
if (!AuthUtil.instance.isSsoSession()) {
89+
telemetry.amazonq_messageResponseError.emit({
90+
result: 'Failed',
91+
cwsprChatConversationType: 'Chat',
92+
cwsprChatRequestLength: message.message?.length ?? 0,
93+
cwsprChatResponseCode: 401,
94+
cwsprChatTriggerInteraction: triggerInteraction,
95+
reason: 'AuthenticationError',
96+
reasonDesc: 'Inline chat requires SSO authentication, but current session is not',
97+
})
98+
throw new ToolkitError('Inline chat is only available with SSO authentication')
99+
}
100+
72101
// TODO: handle partial responses.
73102
getLogger().info('Making inline chat request with message %O', message)
74103
const params = this.getCurrentEditorParams(message.message ?? '')
@@ -83,6 +112,23 @@ export class InlineChatProvider {
83112

84113
// TODO: remove in favor of LSP implementation.
85114
public async processPromptMessage(message: PromptMessage) {
115+
const triggerInteraction = this.getTriggerInteractionFromTriggerEvent(
116+
this.triggerEventsStorage.getLastTriggerEventByTabID(message.tabID)
117+
)
118+
if (!AuthUtil.instance.isSsoSession()) {
119+
telemetry.amazonq_messageResponseError.emit({
120+
result: 'Failed',
121+
cwsprChatConversationType: 'Chat',
122+
cwsprChatRequestLength: message.message?.length ?? 0,
123+
cwsprChatResponseCode: 401,
124+
cwsprChatTriggerInteraction: triggerInteraction,
125+
reason: 'AuthenticationError',
126+
reasonDesc: 'Inline chat requires SSO authentication, but current session is not',
127+
credentialStartUrl: AuthUtil.instance.connection?.startUrl,
128+
})
129+
throw new ToolkitError('Inline chat is only available with SSO authentication')
130+
}
131+
86132
return this.editorContextExtractor
87133
.extractContextForTrigger('ChatMessage')
88134
.then((context) => {

packages/core/src/codewhispererChat/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ export { ChatTriggerType, PromptMessage, TriggerPayload } from './controllers/ch
1212
export { UserIntentRecognizer } from './controllers/chat/userIntent/userIntentRecognizer'
1313
export { EditorContextExtractor } from './editor/context/extractor'
1414
export { ChatSessionStorage } from './storages/chatSession'
15-
export { TriggerEventsStorage } from './storages/triggerEvents'
15+
export { TriggerEventsStorage, TriggerEvent } from './storages/triggerEvents'
1616
export { ReferenceLogController } from './view/messages/referenceLogController'
1717
export { extractLanguageNameFromFile } from './editor/context/file/languages'

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { builderIdStartUrl } from '../../../../auth/sso/constants'
2020
import { RegionProfile, vsCodeState } from '../../../../codewhisperer/models/model'
2121
import { randomUUID } from '../../../../shared/crypto'
2222
import globals from '../../../../shared/extensionGlobals'
23-
import { telemetry } from '../../../../shared/telemetry/telemetry'
23+
import { CredentialType, telemetry } from '../../../../shared/telemetry/telemetry'
2424
import { ProfileSwitchIntent } from '../../../../codewhisperer/region/regionProfileManager'
2525

2626
const className = 'AmazonQLoginWebview'
@@ -204,6 +204,15 @@ export class AmazonQLoginWebview extends CommonAuthWebview {
204204
// Defining separate auth function to emit telemetry before returning from this method
205205
await globals.globalState.update('recentIamKeys', { accessKey: accessKey })
206206
await globals.globalState.update('recentRoleArn', { roleArn: roleArn })
207+
let credentialsType: CredentialType | undefined
208+
if (!sessionToken && !roleArn) {
209+
credentialsType = 'staticProfile'
210+
} else if (roleArn) {
211+
credentialsType = 'assumeRoleProfile'
212+
} else {
213+
credentialsType = 'staticSessionProfile'
214+
}
215+
207216
const runAuth = async (): Promise<AuthError | undefined> => {
208217
try {
209218
await AuthUtil.instance.loginIam({ accessKey, secretKey, sessionToken, roleArn })
@@ -224,7 +233,10 @@ export class AmazonQLoginWebview extends CommonAuthWebview {
224233
const result = await runAuth()
225234
this.storeMetricMetadata({
226235
credentialSourceId: 'sharedCredentials',
227-
authEnabledFeatures: 'codewhisperer',
236+
featureId: 'codewhisperer',
237+
credentialType: credentialsType,
238+
isReAuth: false,
239+
isAggregated: false,
228240
...this.getResultForMetrics(result),
229241
})
230242
this.emitAuthMetric()

packages/core/src/login/webview/vue/login.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,9 @@ export default defineComponent({
500500
}
501501
}
502502
} else if (this.selectedLoginOption === LoginOption.IAM_CREDENTIAL) {
503+
// Emit telemetry when IAM Credentials option is selected and Continue is clicked
504+
void client.emitUiClick('auth_credentialsOption')
505+
503506
this.stage = 'AWS_PROFILE'
504507
this.$nextTick(() => document.getElementById('profileName')!.focus())
505508
}

0 commit comments

Comments
 (0)