Skip to content

Commit 29d6cc8

Browse files
authored
CodeWhisperer: Add telemetry optout status to SendTelemetryEventRequest (#3887)
Updated the API and put the field in SendTelemetryEvent API requests.
1 parent 13c2111 commit 29d6cc8

File tree

5 files changed

+358
-221
lines changed

5 files changed

+358
-221
lines changed

jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUr
2121
import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUrlResponse
2222
import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsRequest
2323
import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsResponse
24+
import software.amazon.awssdk.services.codewhispererruntime.model.OptOutPreference
2425
import software.amazon.awssdk.services.codewhispererruntime.model.SendTelemetryEventResponse
2526
import software.amazon.awssdk.services.codewhispererruntime.model.SuggestionState
2627
import software.aws.toolkits.core.utils.getLogger
@@ -39,6 +40,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.service.RequestCon
3940
import software.aws.toolkits.jetbrains.services.codewhisperer.service.ResponseContext
4041
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
4142
import software.aws.toolkits.jetbrains.services.codewhisperer.util.transform
43+
import software.aws.toolkits.jetbrains.settings.AwsSettings
4244
import software.aws.toolkits.telemetry.CodewhispererCompletionType
4345
import software.aws.toolkits.telemetry.CodewhispererSuggestionState
4446
import java.time.Instant
@@ -211,6 +213,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
211213
it.generatedLine(lineCount)
212214
}
213215
}
216+
requestBuilder.optOutPreference(getTelemetryOptoutPreference())
214217
}
215218
}
216219

@@ -227,6 +230,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
227230
it.timestamp(Instant.now())
228231
}
229232
}
233+
requestBuilder.optOutPreference(getTelemetryOptoutPreference())
230234
}
231235

232236
override fun sendUserModificationTelemetry(
@@ -246,6 +250,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
246250
it.timestamp(Instant.now())
247251
}
248252
}
253+
requestBuilder.optOutPreference(getTelemetryOptoutPreference())
249254
}
250255

251256
override fun sendCodeScanTelemetry(
@@ -261,8 +266,16 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
261266
it.timestamp(Instant.now())
262267
}
263268
}
269+
requestBuilder.optOutPreference(getTelemetryOptoutPreference())
264270
}
265271

272+
private fun getTelemetryOptoutPreference() =
273+
if (AwsSettings.getInstance().isTelemetryEnabled) {
274+
OptOutPreference.OPTIN
275+
} else {
276+
OptOutPreference.OPTOUT
277+
}
278+
266279
override fun dispose() {
267280
if (this::mySigv4Client.isLazyInitialized) {
268281
mySigv4Client.close()

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import com.intellij.testFramework.ProjectRule
88
import com.intellij.testFramework.RuleChain
99
import com.intellij.testFramework.replaceService
1010
import org.assertj.core.api.Assertions.assertThat
11+
import org.junit.After
1112
import org.junit.Before
1213
import org.junit.Rule
1314
import org.junit.Test
1415
import org.mockito.kotlin.any
16+
import org.mockito.kotlin.argThat
1517
import org.mockito.kotlin.argumentCaptor
1618
import org.mockito.kotlin.doReturn
1719
import org.mockito.kotlin.doReturnConsecutively
@@ -42,6 +44,9 @@ import software.amazon.awssdk.services.codewhispererruntime.model.GetCodeAnalysi
4244
import software.amazon.awssdk.services.codewhispererruntime.model.GetCodeAnalysisResponse
4345
import software.amazon.awssdk.services.codewhispererruntime.model.ListCodeAnalysisFindingsRequest
4446
import software.amazon.awssdk.services.codewhispererruntime.model.ListCodeAnalysisFindingsResponse
47+
import software.amazon.awssdk.services.codewhispererruntime.model.OptOutPreference
48+
import software.amazon.awssdk.services.codewhispererruntime.model.SendTelemetryEventRequest
49+
import software.amazon.awssdk.services.codewhispererruntime.model.SendTelemetryEventResponse
4550
import software.amazon.awssdk.services.codewhispererruntime.model.StartCodeAnalysisRequest
4651
import software.amazon.awssdk.services.codewhispererruntime.model.StartCodeAnalysisResponse
4752
import software.amazon.awssdk.services.codewhispererruntime.paginators.GenerateCompletionsIterable
@@ -62,6 +67,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestU
6267
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.sdkHttpResponse
6368
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
6469
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptorImpl
70+
import software.aws.toolkits.jetbrains.settings.AwsSettings
6571

6672
class CodeWhispererClientAdaptorTest {
6773
val projectRule = ProjectRule()
@@ -80,6 +86,7 @@ class CodeWhispererClientAdaptorTest {
8086

8187
private lateinit var sut: CodeWhispererClientAdaptor
8288
private lateinit var connectionManager: ToolkitConnectionManager
89+
private var isTelemetryEnabledDefault: Boolean = false
8390

8491
@Before
8592
fun setup() {
@@ -99,6 +106,7 @@ class CodeWhispererClientAdaptorTest {
99106
on { startCodeAnalysis(any<StartCodeAnalysisRequest>()) } doReturn startCodeAnalysisResponse
100107
on { getCodeAnalysis(any<GetCodeAnalysisRequest>()) } doReturn getCodeAnalysisResponse
101108
on { listCodeAnalysisFindings(any<ListCodeAnalysisFindingsRequest>()) } doReturn listCodeAnalysisFindingsResponse
109+
on { sendTelemetryEvent(any<SendTelemetryEventRequest>()) } doReturn sendtelemetryEventResponse
102110
}
103111

104112
val mockConnection = mock<BearerSsoConnection>()
@@ -110,6 +118,13 @@ class CodeWhispererClientAdaptorTest {
110118
} doReturn authManagerRule.createConnection(ManagedSsoProfile("us-east-1", aString(), emptyList())) as AwsBearerTokenConnection
111119
}
112120
projectRule.project.replaceService(ToolkitConnectionManager::class.java, connectionManager, disposableRule.disposable)
121+
122+
isTelemetryEnabledDefault = AwsSettings.getInstance().isTelemetryEnabled
123+
}
124+
125+
@After
126+
fun tearDown() {
127+
AwsSettings.getInstance().isTelemetryEnabled = isTelemetryEnabledDefault
113128
}
114129

115130
@Test
@@ -239,6 +254,55 @@ class CodeWhispererClientAdaptorTest {
239254
}
240255
}
241256

257+
@Test
258+
fun `sendTelemetryEvent for userTriggerDecision respects telemetry optin status`() {
259+
sendTelemetryEventOptOutCheckHelper {
260+
sut.putUserTriggerDecisionTelemetry(
261+
aRequestContext(projectRule.project),
262+
aResponseContext(),
263+
aCompletionType(),
264+
aSuggestionState(),
265+
0,
266+
1
267+
)
268+
}
269+
}
270+
271+
@Test
272+
fun `sendTelemetryEvent for codePercentage respects telemetry optin status`() {
273+
sendTelemetryEventOptOutCheckHelper {
274+
sut.putCodePercentageTelemetry(aProgrammingLanguage(), 0, 1)
275+
}
276+
}
277+
278+
@Test
279+
fun `sendTelemetryEvent for codeScan respects telemetry optin status`() {
280+
sendTelemetryEventOptOutCheckHelper {
281+
sut.sendCodeScanTelemetry(aProgrammingLanguage(), null)
282+
}
283+
}
284+
285+
@Test
286+
fun `sendTelemetryEvent for userModification respects telemetry optin status`() {
287+
sendTelemetryEventOptOutCheckHelper {
288+
sut.sendUserModificationTelemetry(aString(), aString(), aProgrammingLanguage(), 0.0)
289+
}
290+
}
291+
292+
private fun sendTelemetryEventOptOutCheckHelper(mockApiCall: () -> Unit) {
293+
AwsSettings.getInstance().isTelemetryEnabled = true
294+
mockApiCall()
295+
verify(bearerClient).sendTelemetryEvent(
296+
argThat<SendTelemetryEventRequest> { optOutPreference() == OptOutPreference.OPTIN }
297+
)
298+
299+
AwsSettings.getInstance().isTelemetryEnabled = false
300+
mockApiCall()
301+
verify(bearerClient).sendTelemetryEvent(
302+
argThat<SendTelemetryEventRequest> { optOutPreference() == OptOutPreference.OPTOUT }
303+
)
304+
}
305+
242306
private companion object {
243307
val createCodeScanRequest = CreateCodeScanRequest.builder()
244308
.artifacts(mapOf(ArtifactType.SOURCE_CODE to "foo"))
@@ -294,6 +358,8 @@ class CodeWhispererClientAdaptorTest {
294358
.sdkHttpResponse(sdkHttpResponse)
295359
.build() as ListCodeAnalysisFindingsResponse
296360

361+
val sendtelemetryEventResponse = SendTelemetryEventResponse.builder().build()
362+
297363
private val generateCompletionsPaginatorResponse: GenerateCompletionsIterable = mock()
298364

299365
private val createCodeScanUploadUrlResponse: CreateCodeScanUploadUrlResponse = mock()

0 commit comments

Comments
 (0)