Skip to content

Commit 0b84915

Browse files
author
David Hasani
committed
telemetry(amazonq): emit TransformEvent metric from download ZIP
1 parent 06181dd commit 0b84915

File tree

7 files changed

+2647
-717
lines changed

7 files changed

+2647
-717
lines changed

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ArtifactHandler.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class ArtifactHandler(private val project: Project, private val clientAdaptor: G
7070
is DownloadArtifactResult.Success -> {
7171
if (result.artifact !is CodeModernizerArtifact) return notifyUnableToApplyPatch("")
7272
displayDiffUsingPatch(result.artifact.patch, job, source)
73+
clientAdaptor.sendTransformTelemetryEvent(job, result.artifact.metrics)
7374
}
7475
is DownloadArtifactResult.ParseZipFailure -> notifyUnableToApplyPatch(result.failureReason.errorMessage)
7576
is DownloadArtifactResult.UnzipFailure -> notifyUnableToApplyPatch(result.failureReason.errorMessage)

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/client/GumbyClient.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import software.amazon.awssdk.services.codewhispererruntime.model.GetTransformat
1616
import software.amazon.awssdk.services.codewhispererruntime.model.GetTransformationPlanResponse
1717
import software.amazon.awssdk.services.codewhispererruntime.model.GetTransformationRequest
1818
import software.amazon.awssdk.services.codewhispererruntime.model.GetTransformationResponse
19+
import software.amazon.awssdk.services.codewhispererruntime.model.IdeCategory
1920
import software.amazon.awssdk.services.codewhispererruntime.model.ResumeTransformationRequest
2021
import software.amazon.awssdk.services.codewhispererruntime.model.ResumeTransformationResponse
2122
import software.amazon.awssdk.services.codewhispererruntime.model.StartTransformationRequest
@@ -46,8 +47,11 @@ import software.aws.toolkits.jetbrains.services.amazonq.CONTENT_SHA256
4647
import software.aws.toolkits.jetbrains.services.amazonq.SERVER_SIDE_ENCRYPTION
4748
import software.aws.toolkits.jetbrains.services.amazonq.SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID
4849
import software.aws.toolkits.jetbrains.services.amazonq.clients.AmazonQStreamingClient
50+
import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
51+
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerMetrics
4952
import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId
5053
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.calculateTotalLatency
54+
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.getTelemetryOptOutPreference
5155
import java.io.File
5256
import java.net.HttpURLConnection
5357
import java.time.Instant
@@ -210,6 +214,26 @@ class GumbyClient(private val project: Project) {
210214
}
211215
}
212216

217+
fun sendTransformTelemetryEvent(job: JobId, metrics: CodeModernizerMetrics) {
218+
bearerClient().sendTelemetryEvent { requestBuilder ->
219+
requestBuilder.telemetryEvent { telemetryEventBuilder ->
220+
telemetryEventBuilder.transformEvent {
221+
it.jobId(job.id)
222+
it.timestamp(Instant.now())
223+
it.ideCategory(IdeCategory.JETBRAINS)
224+
it.programmingLanguage { language ->
225+
language.languageName("JAVA") // TODO: figure out when/how to make this SQL
226+
}
227+
it.linesOfCodeChanged(metrics.linesOfCodeChanged)
228+
it.charsOfCodeChanged(metrics.charsOfCodeChanged)
229+
it.linesOfCodeSubmitted(0) // TODO: figure out how to get lines of code submitted from plan stage
230+
}
231+
}
232+
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
233+
requestBuilder.userContext(codeWhispererUserContext())
234+
}
235+
}
236+
213237
companion object {
214238
private val LOG = getLogger<GumbyClient>()
215239

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerArtifact.kt

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,17 @@ open class CodeModernizerArtifact(
2929
private val patches: List<VirtualFile>,
3030
val summary: TransformationSummary,
3131
val summaryMarkdownFile: File,
32+
val metrics: CodeModernizerMetrics,
3233
) : CodeTransformDownloadArtifact {
3334
val patch: VirtualFile
3435
get() = patches.first()
3536

3637
companion object {
37-
private const val maxSupportedVersion = 1.0
38+
private const val MAX_SUPPORTED_VERSION = 1.0
3839
private val tempDir = createTempDirectory("codeTransformArtifacts", null)
39-
private const val manifestPathInZip = "manifest.json"
40-
private const val summaryNameInZip = "summary.md"
40+
private const val MANIFEST_FILE_NAME = "manifest.json"
41+
private const val SUMMARY_FILE_NAME = "summary.md"
42+
private const val METRICS_FILE_NAME = "metrics.json"
4143
val LOG = getLogger<CodeModernizerArtifact>()
4244
private val MAPPER = jacksonObjectMapper()
4345

@@ -53,36 +55,37 @@ open class CodeModernizerArtifact(
5355
throw RuntimeException("Could not unzip artifact")
5456
}
5557
val manifest = loadManifest()
56-
if (manifest.version > maxSupportedVersion) {
58+
if (manifest.version > MAX_SUPPORTED_VERSION) {
5759
// If not supported we can still try to use it, i.e. the versions should largely be backwards compatible
5860
LOG.warn { "Unsupported version: ${manifest.version}" }
5961
}
6062
val patches = extractPatches(manifest)
6163
val summary = extractSummary(manifest)
6264
val summaryMarkdownFile = getSummaryFile(manifest)
65+
val metrics = loadMetrics()
6366
if (patches.size != 1) throw RuntimeException("Expected 1 patch, but found ${patches.size}")
64-
return CodeModernizerArtifact(zipPath, manifest, patches, summary, summaryMarkdownFile)
67+
return CodeModernizerArtifact(zipPath, manifest, patches, summary, summaryMarkdownFile, metrics)
6568
}
6669
throw RuntimeException("Could not find artifact")
6770
}
6871

6972
private fun extractSummary(manifest: CodeModernizerManifest): TransformationSummary {
70-
val summaryFile = tempDir.toPath().resolve(manifest.summaryRoot).resolve(summaryNameInZip).toFile()
73+
val summaryFile = tempDir.toPath().resolve(manifest.summaryRoot).resolve(SUMMARY_FILE_NAME).toFile()
7174
if (!summaryFile.exists() || summaryFile.isDirectory) {
7275
throw RuntimeException("The summary in the downloaded zip had an unknown format")
7376
}
7477
return TransformationSummary(summaryFile.readText())
7578
}
7679

77-
private fun getSummaryFile(manifest: CodeModernizerManifest) = tempDir.toPath().resolve(manifest.summaryRoot).resolve(summaryNameInZip).toFile()
80+
private fun getSummaryFile(manifest: CodeModernizerManifest) = tempDir.toPath().resolve(manifest.summaryRoot).resolve(SUMMARY_FILE_NAME).toFile()
7881

7982
/**
8083
* Attempts to load the manifest from the zip file. Throws an exception if the manifest is not found or cannot be serialized.
8184
*/
8285
private fun loadManifest(): CodeModernizerManifest {
8386
val manifestFile =
8487
tempDir.listFiles()
85-
?.firstOrNull { it.name.endsWith(manifestPathInZip) }
88+
?.firstOrNull { it.name.endsWith(MANIFEST_FILE_NAME) }
8689
?: throw RuntimeException("Could not find manifest")
8790
try {
8891
val manifest = MAPPER.readValue(manifestFile, CodeModernizerManifest::class.java)
@@ -97,6 +100,17 @@ open class CodeModernizerArtifact(
97100
}
98101
}
99102

103+
private fun loadMetrics(): CodeModernizerMetrics {
104+
try {
105+
val metricsFile =
106+
tempDir.listFiles()
107+
?.firstOrNull { it.name.endsWith(METRICS_FILE_NAME) }
108+
return MAPPER.readValue(metricsFile, CodeModernizerMetrics::class.java)
109+
} catch (exception: JsonProcessingException) {
110+
throw RuntimeException("Unable to deserialize the metrics.json file")
111+
}
112+
}
113+
100114
@OptIn(ExperimentalPathApi::class)
101115
private fun extractPatches(manifest: CodeModernizerManifest): List<VirtualFile> {
102116
val fileSystem = LocalFileSystem.getInstance()

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerManifest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ package software.aws.toolkits.jetbrains.services.codemodernizer.model
66
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
77

88
@JsonIgnoreProperties(ignoreUnknown = true)
9-
data class CodeModernizerManifest(val version: Float, val patchesRoot: String, val artifactsRoot: String, val summaryRoot: String)
9+
data class CodeModernizerManifest(val version: Float, val patchesRoot: String, val artifactsRoot: String, val summaryRoot: String, val metricsRoot: String)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.codemodernizer.model
5+
6+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
7+
8+
@JsonIgnoreProperties(ignoreUnknown = true)
9+
data class CodeModernizerMetrics(val linesOfCodeChanged: Int, val charsOfCodeChanged: Int)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,8 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
630630
it.numSuggestionAddLines(numSuggestionAddLines)
631631
it.numSuggestionDelChars(numSuggestionDelChars)
632632
it.numSuggestionDelLines(numSuggestionDelLines)
633-
if (programmingLanguage != null) it.programmingLanguage { langBuilder -> langBuilder.languageName(programmingLanguage) }
633+
// TODO: looks like programmingLanguage was removed from InlineChatEvent in service-2.json?
634+
// if (programmingLanguage != null) it.programmingLanguage { langBuilder -> langBuilder.languageName(programmingLanguage) }
634635
it.timestamp(Instant.now())
635636
}
636637
}

0 commit comments

Comments
 (0)