Skip to content

Commit e870f53

Browse files
authored
[codewhisperer]: emit telemetry for perceived latency (#3298)
1 parent e7d9e77 commit e870f53

File tree

6 files changed

+47
-15
lines changed

6 files changed

+47
-15
lines changed

jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.Co
6060
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererPrevButtonActionListener
6161
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererScrollListener
6262
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
63+
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
6364
import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager
6465
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererColorUtil.POPUP_DIM_HEX
6566
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.POPUP_INFO_TEXT_SIZE
@@ -198,10 +199,7 @@ class CodeWhispererPopupManager {
198199
val caretPoint = states.requestContext.editor.offsetToXY(states.requestContext.caretPosition.offset)
199200
sessionContext.seen.add(sessionContext.selectedIndex)
200201
showPopup(
201-
states.requestContext.editor,
202-
states.recommendationContext.details,
203-
states.recommendationContext.userInputOriginal,
204-
states.recommendationContext.userInputSinceInvocation,
202+
states,
205203
sessionContext,
206204
states.popup,
207205
caretPoint,
@@ -231,15 +229,16 @@ class CodeWhispererPopupManager {
231229
}
232230

233231
fun showPopup(
234-
editor: Editor,
235-
detailContexts: List<DetailContext>,
236-
userInputOriginal: String,
237-
userInput: String,
232+
states: InvocationContext,
238233
sessionContext: SessionContext,
239234
popup: JBPopup,
240235
p: Point,
241236
overlappingLinesCount: Int
242237
) {
238+
val editor = states.requestContext.editor
239+
val detailContexts = states.recommendationContext.details
240+
val userInputOriginal = states.recommendationContext.userInputOriginal
241+
val userInput = states.recommendationContext.userInputSinceInvocation
243242
val selectedIndex = sessionContext.selectedIndex
244243
val typeaheadOriginal = sessionContext.typeaheadOriginal
245244
val typeahead = sessionContext.typeahead
@@ -294,6 +293,13 @@ class CodeWhispererPopupManager {
294293
CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP = originalAutoPopupCompletionLookup
295294
}
296295
popup.show(relativePopupLocationToEditor)
296+
val perceivedLatency = CodeWhispererInvocationStatus.getInstance().getTimeSinceDocumentChanged()
297+
CodeWhispererTelemetryService.getInstance().sendPerceivedLatencyEvent(
298+
detailContexts[selectedIndex].requestId,
299+
states.requestContext,
300+
states.responseContext,
301+
perceivedLatency
302+
)
297303
}
298304
if (shouldHidePopup) {
299305
WindowManager.getInstance().setAlphaModeRatio(popup.popupWindow, 1f)

jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererInvocationStatus.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ class CodeWhispererInvocationStatus {
6666
timeAtLastDocumentChanged = Instant.now()
6767
}
6868

69+
fun getTimeSinceDocumentChanged(): Double {
70+
val timeSinceDocumentChanged = Duration.between(timeAtLastInvocationComplete, Instant.now())
71+
val timeInDouble = timeSinceDocumentChanged.toMillis().toDouble()
72+
return timeInDouble
73+
}
74+
6975
fun hasEnoughDelayToShowCodeWhisperer(): Boolean {
7076
val timeCanShowCodeWhisperer = timeAtLastDocumentChanged?.plusMillis(CodeWhispererConstants.POPUP_DELAY) ?: return true
7177
return timeCanShowCodeWhisperer.isBefore(Instant.now())

jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/telemetry/CodeWhispererTelemetryService.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,26 @@ class CodeWhispererTelemetryService {
194194
}
195195
}
196196

197+
fun sendPerceivedLatencyEvent(
198+
requestId: String,
199+
requestContext: RequestContext,
200+
responseContext: ResponseContext,
201+
latency: Double,
202+
) {
203+
val (project, _, triggerTypeInfo) = requestContext
204+
val codewhispererLanguage = requestContext.fileContextInfo.programmingLanguage.toCodeWhispererLanguage()
205+
CodewhispererTelemetry.perceivedLatency(
206+
project = project,
207+
codewhispererCompletionType = responseContext.completionType,
208+
codewhispererLanguage = codewhispererLanguage,
209+
codewhispererRequestId = requestId,
210+
codewhispererSessionId = responseContext.sessionId,
211+
codewhispererTriggerType = triggerTypeInfo.triggerType,
212+
duration = latency,
213+
passive = true
214+
)
215+
}
216+
197217
private fun recordSuggestionState(
198218
index: Int,
199219
selectedIndex: Int,

jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTelemetryTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() {
687687
}
688688
invokeCodeWhispererService()
689689

690-
verify(popupManagerSpy, never()).showPopup(any(), any(), any(), any(), any(), any(), any(), any())
690+
verify(popupManagerSpy, never()).showPopup(any(), any(), any(), any(), any())
691691
runInEdtAndWait {
692692
val metricCaptor = argumentCaptor<MetricEvent>()
693693
verify(batcher, atLeastOnce()).enqueue(metricCaptor.capture())
@@ -752,11 +752,11 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() {
752752

753753
val numOfEmptyRecommendations = response.recommendations().filter { it.content().isEmpty() }.size
754754
if (numOfEmptyRecommendations == response.recommendations().size) {
755-
verify(popupManagerSpy, never()).showPopup(any(), any(), any(), any(), any(), any(), any(), any())
755+
verify(popupManagerSpy, never()).showPopup(any(), any(), any(), any(), any())
756756
} else {
757757
val popupCaptor = argumentCaptor<JBPopup>()
758758
verify(popupManagerSpy, timeout(5000))
759-
.showPopup(any(), any(), any(), any(), any(), popupCaptor.capture(), any(), any())
759+
.showPopup(any(), any(), popupCaptor.capture(), any(), any())
760760
runInEdtAndWait {
761761
popupManagerSpy.closePopup(popupCaptor.lastValue)
762762
}

jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTestBase.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ open class CodeWhispererTestBase {
103103

104104
popupManagerSpy = spy(CodeWhispererPopupManager.getInstance())
105105
popupManagerSpy.reset()
106-
doNothing().`when`(popupManagerSpy).showPopup(any(), any(), any(), any(), any(), any(), any(), any())
106+
doNothing().`when`(popupManagerSpy).showPopup(any(), any(), any(), any(), any())
107107
ApplicationManager.getApplication().replaceService(CodeWhispererPopupManager::class.java, popupManagerSpy, disposableRule.disposable)
108108

109109
invocationStatusSpy = spy(CodeWhispererInvocationStatus.getInstance())
@@ -152,7 +152,7 @@ open class CodeWhispererTestBase {
152152
val popupCaptor = argumentCaptor<JBPopup>()
153153
invokeCodeWhispererService()
154154
verify(popupManagerSpy, timeout(5000).atLeastOnce())
155-
.showPopup(any(), any(), any(), any(), any(), popupCaptor.capture(), any(), any())
155+
.showPopup(any(), any(), popupCaptor.capture(), any(), any())
156156
val popup = popupCaptor.lastValue
157157

158158
try {

jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererUserActionsTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class CodeWhispererUserActionsTest : CodeWhispererTestBase() {
116116
assertThat(projectRule.fixture.editor.document.text).isEqualTo(expectedFileContext)
117117
val popupCaptor = argumentCaptor<JBPopup>()
118118
verify(popupManagerSpy, timeout(5000))
119-
.showPopup(any(), any(), any(), any(), any(), popupCaptor.capture(), any(), any())
119+
.showPopup(any(), any(), popupCaptor.capture(), any(), any())
120120
runInEdtAndWait {
121121
popupManagerSpy.closePopup(popupCaptor.lastValue)
122122
}
@@ -128,7 +128,7 @@ class CodeWhispererUserActionsTest : CodeWhispererTestBase() {
128128
projectRule.fixture.type('\n')
129129
val popupCaptor = argumentCaptor<JBPopup>()
130130
verify(popupManagerSpy, timeout(5000).atLeast(times))
131-
.showPopup(any(), any(), any(), any(), any(), popupCaptor.capture(), any(), any())
131+
.showPopup(any(), any(), popupCaptor.capture(), any(), any())
132132
runInEdtAndWait {
133133
popupManagerSpy.closePopup(popupCaptor.lastValue)
134134
}

0 commit comments

Comments
 (0)