Skip to content

Commit cd82ada

Browse files
committed
telemetry(amazonq): implement codewhisperer_clientComponentLatency
1 parent 260fb37 commit cd82ada

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed

packages/amazonq/src/app/inline/completion.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
import { InlineGeneratingMessage } from './inlineGeneratingMessage'
3737
import { LineTracker } from './stateTracker/lineTracker'
3838
import { InlineTutorialAnnotation } from './tutorials/inlineTutorialAnnotation'
39+
import { TelemetryHelper } from './telemetryHelper'
3940

4041
export class InlineCompletionManager implements Disposable {
4142
private disposable: Disposable
@@ -212,6 +213,8 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
212213

213214
// tell the tutorial that completions has been triggered
214215
await this.inlineTutorialAnnotation.triggered(context.triggerKind)
216+
TelemetryHelper.instance.setInvokeSuggestionStartTime()
217+
TelemetryHelper.instance.setTriggerType(context.triggerKind)
215218

216219
// make service requests if it's a new session
217220
await this.recommendationService.getAllRecommendations(

packages/amazonq/src/app/inline/recommendationService.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { LanguageClient } from 'vscode-languageclient'
1313
import { SessionManager } from './sessionManager'
1414
import { InlineGeneratingMessage } from './inlineGeneratingMessage'
1515
import { CodeWhispererStatusBarManager } from 'aws-core-vscode/codewhisperer'
16+
import { TelemetryHelper } from './telemetryHelper'
1617

1718
export class RecommendationService {
1819
constructor(
@@ -36,6 +37,9 @@ export class RecommendationService {
3637
}
3738
const requestStartTime = Date.now()
3839
const statusBar = CodeWhispererStatusBarManager.instance
40+
TelemetryHelper.instance.setInvokeSuggestionStartTime()
41+
TelemetryHelper.instance.setPreprocessEndTime()
42+
TelemetryHelper.instance.setSdkApiCallStartTime()
3943

4044
try {
4145
// Show UI indicators that we are generating suggestions
@@ -49,6 +53,14 @@ export class RecommendationService {
4953
token
5054
)
5155

56+
// Set telemetry data for the first response
57+
TelemetryHelper.instance.setSdkApiCallEndTime()
58+
TelemetryHelper.instance.setSessionId(firstResult.sessionId)
59+
if (firstResult.items.length > 0) {
60+
TelemetryHelper.instance.setFirstResponseRequestId(firstResult.items[0].itemId)
61+
}
62+
TelemetryHelper.instance.setFirstSuggestionShowTime()
63+
5264
const firstCompletionDisplayLatency = Date.now() - requestStartTime
5365
this.sessionManager.startSession(
5466
firstResult.sessionId,
@@ -64,6 +76,10 @@ export class RecommendationService {
6476
})
6577
} else {
6678
this.sessionManager.closeSession()
79+
80+
// No more results to fetch, mark pagination as complete
81+
TelemetryHelper.instance.setAllPaginationEndTime()
82+
TelemetryHelper.instance.tryRecordClientComponentLatency()
6783
}
6884
} finally {
6985
// Remove all UI indicators of message generation since we are done
@@ -89,6 +105,11 @@ export class RecommendationService {
89105
this.sessionManager.updateSessionSuggestions(result.items)
90106
nextToken = result.partialResultToken
91107
}
108+
92109
this.sessionManager.closeSession()
110+
111+
// All pagination requests completed
112+
TelemetryHelper.instance.setAllPaginationEndTime()
113+
TelemetryHelper.instance.tryRecordClientComponentLatency()
93114
}
94115
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { AuthUtil, getSelectedCustomization } from 'aws-core-vscode/codewhisperer'
7+
import { CodewhispererLanguage } from 'aws-core-vscode/shared'
8+
import { CodewhispererTriggerType, telemetry } from 'aws-core-vscode/telemetry'
9+
import { InlineCompletionTriggerKind } from 'vscode'
10+
11+
export class TelemetryHelper {
12+
// Variables needed for client component latency
13+
private _invokeSuggestionStartTime = 0
14+
private _preprocessEndTime = 0
15+
private _sdkApiCallStartTime = 0
16+
private _sdkApiCallEndTime = 0
17+
private _allPaginationEndTime = 0
18+
private _firstSuggestionShowTime = 0
19+
private _firstResponseRequestId = ''
20+
private _sessionId = ''
21+
private _language: CodewhispererLanguage = 'java'
22+
private _triggerType: CodewhispererTriggerType = 'OnDemand'
23+
24+
constructor() {}
25+
26+
static #instance: TelemetryHelper
27+
28+
public static get instance() {
29+
return (this.#instance ??= new this())
30+
}
31+
32+
public resetClientComponentLatencyTime() {
33+
this._invokeSuggestionStartTime = 0
34+
this._preprocessEndTime = 0
35+
this._sdkApiCallStartTime = 0
36+
this._sdkApiCallEndTime = 0
37+
this._firstSuggestionShowTime = 0
38+
this._allPaginationEndTime = 0
39+
this._firstResponseRequestId = ''
40+
}
41+
42+
public setInvokeSuggestionStartTime() {
43+
this.resetClientComponentLatencyTime()
44+
this._invokeSuggestionStartTime = performance.now()
45+
}
46+
47+
get invokeSuggestionStartTime(): number {
48+
return this._invokeSuggestionStartTime
49+
}
50+
51+
public setPreprocessEndTime() {
52+
this._preprocessEndTime = performance.now()
53+
}
54+
55+
get preprocessEndTime(): number {
56+
return this._preprocessEndTime
57+
}
58+
59+
public setSdkApiCallStartTime() {
60+
if (this._sdkApiCallStartTime === 0) {
61+
this._sdkApiCallStartTime = performance.now()
62+
}
63+
}
64+
65+
get sdkApiCallStartTime(): number {
66+
return this._sdkApiCallStartTime
67+
}
68+
69+
public setSdkApiCallEndTime() {
70+
if (this._sdkApiCallEndTime === 0 && this._sdkApiCallStartTime !== 0) {
71+
this._sdkApiCallEndTime = performance.now()
72+
}
73+
}
74+
75+
get sdkApiCallEndTime(): number {
76+
return this._sdkApiCallEndTime
77+
}
78+
79+
public setAllPaginationEndTime() {
80+
if (this._allPaginationEndTime === 0 && this._sdkApiCallEndTime !== 0) {
81+
this._allPaginationEndTime = performance.now()
82+
}
83+
}
84+
85+
get allPaginationEndTime(): number {
86+
return this._allPaginationEndTime
87+
}
88+
89+
public setFirstSuggestionShowTime() {
90+
if (this._firstSuggestionShowTime === 0 && this._sdkApiCallEndTime !== 0) {
91+
this._firstSuggestionShowTime = performance.now()
92+
}
93+
}
94+
95+
get firstSuggestionShowTime(): number {
96+
return this._firstSuggestionShowTime
97+
}
98+
99+
public setFirstResponseRequestId(requestId: string) {
100+
if (this._firstResponseRequestId === '') {
101+
this._firstResponseRequestId = requestId
102+
}
103+
}
104+
105+
get firstResponseRequestId(): string {
106+
return this._firstResponseRequestId
107+
}
108+
109+
public setSessionId(sessionId: string) {
110+
if (this._sessionId === '') {
111+
this._sessionId = sessionId
112+
}
113+
}
114+
115+
get sessionId(): string {
116+
return this._sessionId
117+
}
118+
119+
public setLanguage(language: CodewhispererLanguage) {
120+
this._language = language
121+
}
122+
123+
get language(): CodewhispererLanguage {
124+
return this._language
125+
}
126+
127+
public setTriggerType(triggerType: InlineCompletionTriggerKind) {
128+
if (triggerType === InlineCompletionTriggerKind.Invoke) {
129+
this._triggerType = 'OnDemand'
130+
} else if (triggerType === InlineCompletionTriggerKind.Automatic) {
131+
this._triggerType = 'AutoTrigger'
132+
}
133+
}
134+
135+
get triggerType(): string {
136+
return this._triggerType
137+
}
138+
139+
// report client component latency after all pagination call finish
140+
// and at least one suggestion is shown to the user
141+
public tryRecordClientComponentLatency() {
142+
if (this._firstSuggestionShowTime === 0 || this._allPaginationEndTime === 0) {
143+
return
144+
}
145+
telemetry.codewhisperer_clientComponentLatency.emit({
146+
codewhispererAllCompletionsLatency: this._allPaginationEndTime - this._sdkApiCallStartTime,
147+
codewhispererCompletionType: 'Line',
148+
codewhispererCredentialFetchingLatency: 0, // no longer relevant, because we don't re-build the sdk. Flare already has that set
149+
codewhispererCustomizationArn: getSelectedCustomization().arn,
150+
codewhispererEndToEndLatency: this._firstSuggestionShowTime - this._invokeSuggestionStartTime,
151+
codewhispererFirstCompletionLatency: this._sdkApiCallEndTime - this._sdkApiCallStartTime,
152+
codewhispererLanguage: this._language,
153+
codewhispererPostprocessingLatency: this._firstSuggestionShowTime - this._sdkApiCallEndTime,
154+
codewhispererPreprocessingLatency: this._preprocessEndTime - this._invokeSuggestionStartTime,
155+
codewhispererRequestId: this._firstResponseRequestId,
156+
codewhispererSessionId: this._sessionId,
157+
codewhispererTriggerType: this._triggerType,
158+
credentialStartUrl: AuthUtil.instance.startUrl,
159+
result: 'Succeeded',
160+
})
161+
}
162+
}

0 commit comments

Comments
 (0)