Skip to content

Commit 47cecd0

Browse files
authored
[Codewhisperer] add serviceInvocation count field in the %code tracker (#3305)
1 parent e870f53 commit 47cecd0

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.service
66
import com.intellij.codeInsight.CodeInsightSettings
77
import com.intellij.codeInsight.hint.HintManager
88
import com.intellij.openapi.application.ApplicationInfo
9+
import com.intellij.openapi.application.ApplicationManager
910
import com.intellij.openapi.application.runInEdt
1011
import com.intellij.openapi.components.service
1112
import com.intellij.openapi.editor.Editor
@@ -17,6 +18,7 @@ import com.intellij.openapi.util.Key
1718
import com.intellij.psi.PsiDocumentManager
1819
import com.intellij.psi.PsiFile
1920
import com.intellij.util.concurrency.annotations.RequiresEdt
21+
import com.intellij.util.messages.Topic
2022
import kotlinx.coroutines.delay
2123
import kotlinx.coroutines.isActive
2224
import kotlinx.coroutines.launch
@@ -142,6 +144,8 @@ class CodeWhispererService {
142144
val responseContext = ResponseContext(sessionId, completionType)
143145
logServiceInvocation(requestId, requestContext, responseContext, response.recommendations(), latency, null)
144146
lastRecommendationIndex += response.recommendations().size
147+
ApplicationManager.getApplication().messageBus.syncPublisher(CODEWHISPERER_CODE_COMPLETION_PERFORMED)
148+
.onSuccess(requestContext.fileContextInfo)
145149
CodeWhispererTelemetryService.getInstance().sendServiceInvocationEvent(
146150
requestId,
147151
requestContext,
@@ -564,6 +568,10 @@ class CodeWhispererService {
564568

565569
companion object {
566570
private val LOG = getLogger<CodeWhispererService>()
571+
val CODEWHISPERER_CODE_COMPLETION_PERFORMED: Topic<CodeWhispererCodeCompletionServiceListener> = Topic.create(
572+
"CodeWhisperer code completion service invoked",
573+
CodeWhispererCodeCompletionServiceListener::class.java
574+
)
567575
val KEY_CODEWHISPERER_METADATA: Key<CodeWhispererMetadata> = Key.create("codewhisperer.metadata")
568576
fun getInstance(): CodeWhispererService = service()
569577
const val KET_SESSION_ID = "x-amzn-SessionId"
@@ -601,3 +609,7 @@ data class ResponseContext(
601609
val sessionId: String,
602610
val completionType: CodewhispererCompletionType
603611
)
612+
613+
interface CodeWhispererCodeCompletionServiceListener {
614+
fun onSuccess(fileContextInfo: FileContextInfo) {}
615+
}

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ import org.jetbrains.annotations.TestOnly
1818
import software.aws.toolkits.core.utils.debug
1919
import software.aws.toolkits.core.utils.getLogger
2020
import software.aws.toolkits.jetbrains.services.codewhisperer.language.toCodeWhispererLanguage
21+
import software.aws.toolkits.jetbrains.services.codewhisperer.model.FileContextInfo
2122
import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext
2223
import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext
2324
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager
2425
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererUserActionListener
26+
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererCodeCompletionServiceListener
27+
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
2528
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.TOTAL_SECONDS_IN_MINUTE
2629
import software.aws.toolkits.telemetry.CodewhispererLanguage
2730
import software.aws.toolkits.telemetry.CodewhispererTelemetry
@@ -35,7 +38,8 @@ abstract class CodeWhispererCodeCoverageTracker(
3538
private val timeWindowInSec: Long,
3639
private val language: CodewhispererLanguage,
3740
private val rangeMarkers: MutableList<RangeMarker>,
38-
private val fileToTokens: MutableMap<Document, CodeCoverageTokens>
41+
private val fileToTokens: MutableMap<Document, CodeCoverageTokens>,
42+
private val myServiceInvocationCount: AtomicInteger
3943
) : Disposable {
4044
val percentage: Int?
4145
get() = if (totalTokensSize != 0) calculatePercentage(acceptedTokensSize, totalTokensSize) else null
@@ -53,6 +57,8 @@ abstract class CodeWhispererCodeCoverageTracker(
5357
}
5458
val acceptedRecommendationsCount: Int
5559
get() = rangeMarkers.size
60+
val serviceInvocationCount: Int
61+
get() = myServiceInvocationCount.get()
5662
private val isActive: AtomicBoolean = AtomicBoolean(false)
5763
private val alarm = AlarmFactory.getInstance().create(Alarm.ThreadToUse.POOLED_THREAD, this)
5864
private val isShuttingDown = AtomicBoolean(false)
@@ -77,6 +83,17 @@ abstract class CodeWhispererCodeCoverageTracker(
7783
}
7884
}
7985
)
86+
87+
conn.subscribe(
88+
CodeWhispererService.CODEWHISPERER_CODE_COMPLETION_PERFORMED,
89+
object : CodeWhispererCodeCompletionServiceListener {
90+
override fun onSuccess(fileContextInfo: FileContextInfo) {
91+
if (language == fileContextInfo.programmingLanguage.toCodeWhispererLanguage()) {
92+
myServiceInvocationCount.getAndIncrement()
93+
}
94+
}
95+
}
96+
)
8097
startTime = Instant.now()
8198
isActive.set(true)
8299
scheduleCodeWhispererCodeCoverageTracker()
@@ -156,6 +173,7 @@ abstract class CodeWhispererCodeCoverageTracker(
156173
startTime = Instant.now()
157174
rangeMarkers.clear()
158175
fileToTokens.clear()
176+
myServiceInvocationCount.set(0)
159177
}
160178

161179
internal fun emitCodeWhispererCodeContribution() {
@@ -186,7 +204,7 @@ abstract class CodeWhispererCodeCoverageTracker(
186204
language,
187205
percentage,
188206
totalTokensSize,
189-
successCount = 0
207+
successCount = myServiceInvocationCount.get()
190208
)
191209
}
192210
}
@@ -236,7 +254,8 @@ class DefaultCodeWhispererCodeCoverageTracker(language: CodewhispererLanguage) :
236254
5 * TOTAL_SECONDS_IN_MINUTE,
237255
language,
238256
mutableListOf(),
239-
mutableMapOf()
257+
mutableMapOf(),
258+
AtomicInteger(0)
240259
)
241260

242261
class CodeCoverageTokens(totalTokens: Int = 0, acceptedTokens: Int = 0) {

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.model.ProgrammingL
4848
import software.aws.toolkits.jetbrains.services.codewhisperer.model.RecommendationContext
4949
import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext
5050
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager.Companion.CODEWHISPERER_USER_ACTION_PERFORMED
51+
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
5152
import software.aws.toolkits.jetbrains.services.codewhisperer.service.RequestContext
5253
import software.aws.toolkits.jetbrains.services.codewhisperer.service.ResponseContext
5354
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeCoverageTokens
@@ -62,14 +63,15 @@ import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRul
6263
import software.aws.toolkits.jetbrains.utils.rules.PythonCodeInsightTestFixtureRule
6364
import software.aws.toolkits.telemetry.CodewhispererCompletionType
6465
import software.aws.toolkits.telemetry.CodewhispererLanguage
66+
import java.util.concurrent.atomic.AtomicInteger
6567

6668
internal abstract class CodeWhispererCodeCoverageTrackerTestBase(myProjectRule: CodeInsightTestFixtureRule) {
6769
protected class TestCodePercentageTracker(
6870
timeWindowInSec: Long,
6971
language: CodewhispererLanguage,
7072
rangeMarkers: MutableList<RangeMarker> = mutableListOf(),
7173
codeCoverageTokens: MutableMap<Document, CodeCoverageTokens> = mutableMapOf()
72-
) : CodeWhispererCodeCoverageTracker(timeWindowInSec, language, rangeMarkers, codeCoverageTokens)
74+
) : CodeWhispererCodeCoverageTracker(timeWindowInSec, language, rangeMarkers, codeCoverageTokens, AtomicInteger(0))
7375

7476
protected class TestTelemetryService(
7577
publisher: TelemetryPublisher = NoOpPublisher(),
@@ -178,6 +180,22 @@ internal class CodeWhispererCodeCoverageTrackerTestPython : CodeWhispererCodeCov
178180
assertThat(CodeWhispererCodeCoverageTracker.getInstancesMap()).hasSize(3)
179181
}
180182

183+
@Test
184+
fun `test tracker is listening to cwspr recommendation service invocation`() {
185+
val pythonTracker = TestCodePercentageTracker(TOTAL_SECONDS_IN_MINUTE, CodewhispererLanguage.Python)
186+
val jsxTracker = TestCodePercentageTracker(TOTAL_SECONDS_IN_MINUTE, CodewhispererLanguage.Jsx)
187+
CodeWhispererCodeCoverageTracker.getInstancesMap()[CodewhispererLanguage.Python] = pythonTracker
188+
CodeWhispererCodeCoverageTracker.getInstancesMap()[CodewhispererLanguage.Jsx] = jsxTracker
189+
pythonTracker.activateTrackerIfNotActive()
190+
assertThat(pythonTracker.serviceInvocationCount).isEqualTo(0)
191+
assertThat(jsxTracker.serviceInvocationCount).isEqualTo(0)
192+
193+
val fileContextInfo = mock<FileContextInfo> { on { programmingLanguage } doReturn ProgrammingLanguage(CodewhispererLanguage.Python) }
194+
ApplicationManager.getApplication().messageBus.syncPublisher(CodeWhispererService.CODEWHISPERER_CODE_COMPLETION_PERFORMED).onSuccess(fileContextInfo)
195+
assertThat(pythonTracker.serviceInvocationCount).isEqualTo(1)
196+
assertThat(jsxTracker.serviceInvocationCount).isEqualTo(0)
197+
}
198+
181199
@Test
182200
fun `test tracker is listening to document changes and increment totalTokens - add new code`() {
183201
val pythonTracker = spy(TestCodePercentageTracker(TOTAL_SECONDS_IN_MINUTE, CodewhispererLanguage.Python))

0 commit comments

Comments
 (0)