Skip to content

Commit d18218c

Browse files
authored
Update STE UserTriggerDecision and UserModification events (#4955)
1 parent a35a059 commit d18218c

File tree

12 files changed

+219
-214
lines changed

12 files changed

+219
-214
lines changed

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
5656
import software.aws.toolkits.telemetry.CodewhispererCompletionType
5757
import software.aws.toolkits.telemetry.CodewhispererSuggestionState
5858
import java.time.Instant
59-
import java.util.concurrent.TimeUnit
6059
import kotlin.reflect.KProperty0
6160
import kotlin.reflect.jvm.isAccessible
6261

@@ -114,7 +113,8 @@ interface CodeWhispererClientAdaptor : Disposable {
114113
requestId: String,
115114
language: CodeWhispererProgrammingLanguage,
116115
customizationArn: String,
117-
modificationPercentage: Double,
116+
acceptedCharacterCount: Int,
117+
unmodifiedAcceptedTokenCount: Int,
118118
): SendTelemetryEventResponse
119119

120120
fun sendCodeScanTelemetry(
@@ -305,13 +305,14 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
305305
val programmingLanguage = fileContext.programmingLanguage
306306
var e2eLatency = requestContext.latencyContext.getCodeWhispererEndToEndLatency()
307307

308-
// When we send a userTriggerDecision of Empty or Discard, we set the time users see the first
309-
// suggestion to be now.
310-
if (e2eLatency < 0) {
311-
e2eLatency = TimeUnit.NANOSECONDS.toMillis(
312-
System.nanoTime() - requestContext.latencyContext.codewhispererEndToEndStart
313-
).toDouble()
308+
// When we send a userTriggerDecision for neither Accept nor Reject, service side should not use this value
309+
// and client side will set this value to 0.0.
310+
if (suggestionState != CodewhispererSuggestionState.Accept &&
311+
suggestionState != CodewhispererSuggestionState.Reject
312+
) {
313+
e2eLatency = 0.0
314314
}
315+
315316
return bearerClient().sendTelemetryEvent { requestBuilder ->
316317
requestBuilder.telemetryEvent { telemetryEventBuilder ->
317318
telemetryEventBuilder.userTriggerDecisionEvent {
@@ -321,6 +322,9 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
321322
it.sessionId(responseContext.sessionId)
322323
it.recommendationLatencyMilliseconds(e2eLatency)
323324
it.triggerToResponseLatencyMilliseconds(requestContext.latencyContext.paginationFirstCompletionTime)
325+
it.perceivedLatencyMilliseconds(
326+
requestContext.latencyContext.getPerceivedLatency(requestContext.triggerTypeInfo.triggerType)
327+
)
324328
it.suggestionState(suggestionState.toCodeWhispererSdkType())
325329
it.timestamp(Instant.now())
326330
it.suggestionReferenceCount(suggestionReferenceCount)
@@ -360,7 +364,8 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
360364
requestId: String,
361365
language: CodeWhispererProgrammingLanguage,
362366
customizationArn: String,
363-
modificationPercentage: Double,
367+
acceptedCharacterCount: Int,
368+
unmodifiedAcceptedTokenCount: Int,
364369
): SendTelemetryEventResponse = bearerClient().sendTelemetryEvent { requestBuilder ->
365370
requestBuilder.telemetryEvent { telemetryEventBuilder ->
366371
telemetryEventBuilder.userModificationEvent {
@@ -370,8 +375,11 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
370375
languageBuilder.languageName(language.toCodeWhispererRuntimeLanguage().languageId)
371376
}
372377
it.customizationArn(customizationArn)
373-
it.modificationPercentage(modificationPercentage)
378+
// deprecated field, service side should not use this % anymore
379+
it.modificationPercentage(0.0)
374380
it.timestamp(Instant.now())
381+
it.acceptedCharacterCount(acceptedCharacterCount)
382+
it.unmodifiedAcceptedCharacterCount(unmodifiedAcceptedTokenCount)
375383
}
376384
}
377385
requestBuilder.optOutPreference(getTelemetryOptOutPreference())

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/model/CodeWhispererModel.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import software.amazon.awssdk.services.codewhispererruntime.model.GenerateComple
1313
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
1414
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.sessionconfig.PayloadContext
1515
import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
16+
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererAutoTriggerService
1617
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererAutomatedTriggerType
1718
import software.aws.toolkits.jetbrains.services.codewhisperer.service.RequestContext
1819
import software.aws.toolkits.jetbrains.services.codewhisperer.service.ResponseContext
@@ -198,6 +199,18 @@ data class LatencyContext(
198199
fun getCodeWhispererPreprocessingLatency() = TimeUnit.NANOSECONDS.toMillis(
199200
codewhispererPreprocessingEnd - codewhispererPreprocessingStart
200201
).toDouble()
202+
203+
// For auto-trigger it's from the time when last char typed
204+
// for manual-trigger it's from the time when last trigger action happened(alt + c)
205+
fun getPerceivedLatency(triggerType: CodewhispererTriggerType) =
206+
if (triggerType == CodewhispererTriggerType.OnDemand) {
207+
getCodeWhispererEndToEndLatency()
208+
} else {
209+
(
210+
TimeUnit.NANOSECONDS.toMillis(codewhispererEndToEndEnd) -
211+
CodeWhispererAutoTriggerService.getInstance().timeAtLastCharTyped.toEpochMilli()
212+
).toDouble()
213+
}
201214
}
202215

203216
data class TryExampleRowContext(

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererAutoTriggerService.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class CodeWhispererAutoTriggerService : CodeWhispererAutoTriggerHandler, Disposa
4242

4343
private var lastInvocationTime: Instant? = null
4444
private var lastInvocationLineNum: Int? = null
45+
var timeAtLastCharTyped: Instant = Instant.now()
46+
private set
4547

4648
init {
4749
scheduleReset()
@@ -54,6 +56,7 @@ class CodeWhispererAutoTriggerService : CodeWhispererAutoTriggerHandler, Disposa
5456
// a util wrapper
5557
fun tryInvokeAutoTrigger(editor: Editor, triggerType: CodeWhispererAutomatedTriggerType): Job? {
5658
// only needed for Classifier group, thus calculate it lazily
59+
timeAtLastCharTyped = Instant.now()
5760
val classifierResult: ClassifierResult by lazy { shouldTriggerClassifier(editor, triggerType.telemetryType) }
5861
val language = runReadAction {
5962
FileDocumentManager.getInstance().getFile(editor.document)?.programmingLanguage()

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererFeatureConfigService.kt

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ class CodeWhispererFeatureConfigService {
3232
featureConfigs[it.feature()] = FeatureContext(it.feature(), it.variation(), it.value())
3333
}
3434

35+
// Only apply new auto-trigger UX to BID users
36+
val isNewAutoTriggerUX = getNewAutoTriggerUX()
37+
if (isNewAutoTriggerUX) {
38+
calculateIfIamIdentityCenterConnection(project) {
39+
featureConfigs.remove(NEW_AUTO_TRIGGER_UX)
40+
}
41+
}
42+
3543
val customizationArnOverride = featureConfigs[CUSTOMIZATION_ARN_OVERRIDE_NAME]?.value?.stringValue()
3644
if (customizationArnOverride != null) {
3745
// Double check if server-side wrongly returns a customizationArn to BID users
@@ -84,20 +92,24 @@ class CodeWhispererFeatureConfigService {
8492

8593
fun getCustomizationArnOverride(): String = getFeatureValueForKey(CUSTOMIZATION_ARN_OVERRIDE_NAME).stringValue()
8694

95+
fun getNewAutoTriggerUX(): Boolean = getFeatureValueForKey(NEW_AUTO_TRIGGER_UX).boolValue()
96+
8797
// Get the feature value for the given key.
88-
// In case of a misconfiguration, it will return a default feature value of Boolean true.
98+
// In case of a misconfiguration, it will return a default feature value of Boolean false.
8999
private fun getFeatureValueForKey(name: String): FeatureValue =
90100
featureConfigs[name]?.value ?: FEATURE_DEFINITIONS[name]?.value
91-
?: FeatureValue.builder().boolValue(true).build()
101+
?: FeatureValue.builder().boolValue(false).build()
92102

93103
companion object {
94104
fun getInstance(): CodeWhispererFeatureConfigService = service()
95105
private const val TEST_FEATURE_NAME = "testFeature"
96106
private const val DATA_COLLECTION_FEATURE = "IDEProjectContextDataCollection"
97107
const val CUSTOMIZATION_ARN_OVERRIDE_NAME = "customizationArnOverride"
108+
private const val NEW_AUTO_TRIGGER_UX = "newAutoTriggerUX"
98109
private val LOG = getLogger<CodeWhispererFeatureConfigService>()
99110

100111
// TODO: add real feature later
112+
// Also serve as default values in case server-side config isn't there yet
101113
internal val FEATURE_DEFINITIONS = mapOf(
102114
TEST_FEATURE_NAME to FeatureContext(
103115
TEST_FEATURE_NAME,
@@ -109,7 +121,12 @@ class CodeWhispererFeatureConfigService {
109121
CUSTOMIZATION_ARN_OVERRIDE_NAME,
110122
"customizationARN",
111123
FeatureValue.builder().stringValue("").build()
112-
)
124+
),
125+
NEW_AUTO_TRIGGER_UX to FeatureContext(
126+
NEW_AUTO_TRIGGER_UX,
127+
"CONTROL",
128+
FeatureValue.builder().boolValue(false).build()
129+
),
113130
)
114131
}
115132
}

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
244244
val sessionId = response.sdkHttpResponse().headers().getOrDefault(KET_SESSION_ID, listOf(requestId))[0]
245245
if (requestCount == 1) {
246246
requestContext.latencyContext.codewhispererPostprocessingStart = System.nanoTime()
247-
requestContext.latencyContext.paginationFirstCompletionTime = latency
247+
requestContext.latencyContext.paginationFirstCompletionTime =
248+
(endTime - requestContext.latencyContext.codewhispererEndToEndStart).toDouble()
248249
requestContext.latencyContext.firstRequestId = requestId
249250
CodeWhispererInvocationStatus.getInstance().setInvocationSessionId(sessionId)
250251
}

0 commit comments

Comments
 (0)