@@ -8,6 +8,7 @@ import com.intellij.openapi.components.service
88import com.intellij.openapi.project.Project
99import com.intellij.util.io.HttpRequests
1010import org.apache.commons.codec.digest.DigestUtils
11+ import software.amazon.awssdk.awscore.exception.AwsServiceException
1112import software.amazon.awssdk.services.codewhispererruntime.model.CodeAnalysisUploadContext
1213import software.amazon.awssdk.services.codewhispererruntime.model.CodeFixUploadContext
1314import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUrlRequest
@@ -21,6 +22,7 @@ import software.aws.toolkits.core.utils.debug
2122import software.aws.toolkits.core.utils.getLogger
2223import software.aws.toolkits.jetbrains.core.AwsClientManager
2324import software.aws.toolkits.jetbrains.services.amazonq.RetryableOperation
25+ import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanServerException
2426import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanSession.Companion.APPLICATION_ZIP
2527import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanSession.Companion.AWS_KMS
2628import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanSession.Companion.CONTENT_MD5
@@ -32,7 +34,11 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.codeScanS
3234import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.invalidSourceZipError
3335import software.aws.toolkits.jetbrains.services.codewhisperer.codetest.CodeTestException
3436import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
37+ import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl
3538import software.aws.toolkits.resources.message
39+ import software.aws.toolkits.telemetry.AmazonqTelemetry
40+ import software.aws.toolkits.telemetry.AmazonqUploadIntent
41+ import software.aws.toolkits.telemetry.MetricResult
3642import java.io.File
3743import java.io.FileInputStream
3844import java.io.IOException
@@ -50,29 +56,67 @@ class CodeWhispererZipUploadManager(private val project: Project) {
5056 taskName : String ,
5157 featureUseCase : CodeWhispererConstants .FeatureName ,
5258 ): CreateUploadUrlResponse {
53- // Throw error if zipFile is invalid.
54- if (! zipFile.exists()) {
55- when (featureUseCase) {
56- CodeWhispererConstants .FeatureName .CODE_REVIEW -> invalidSourceZipError()
57- CodeWhispererConstants .FeatureName .TEST_GENERATION -> testGenerationInvalidSourceZipError()
58- else -> throw IllegalArgumentException (" Unsupported feature case: $featureUseCase " ) // Adding else for safety check
59+ val startTime = System .currentTimeMillis()
60+ var result: MetricResult = MetricResult .Succeeded
61+ var failureReason: String? = null
62+ var failureReasonDesc: String? = null
63+ var requestId: String? = null
64+ var requestServiceType: String? = null
65+ var httpStatusCode: String? = null
66+ try {
67+ // Throw error if zipFile is invalid.
68+ if (! zipFile.exists()) {
69+ when (featureUseCase) {
70+ CodeWhispererConstants .FeatureName .CODE_REVIEW -> invalidSourceZipError()
71+ CodeWhispererConstants .FeatureName .TEST_GENERATION -> testGenerationInvalidSourceZipError()
72+ else -> throw IllegalArgumentException (" Unsupported feature case: $featureUseCase " ) // Adding else for safety check
73+ }
5974 }
60- }
61- val fileMd5: String = Base64 .getEncoder().encodeToString(DigestUtils .md5(FileInputStream (zipFile)))
62- val createUploadUrlResponse = createUploadUrl(fileMd5, artifactType, taskType, taskName, featureUseCase)
63- val url = createUploadUrlResponse.uploadUrl()
64- LOG .debug { " $featureUseCase : Uploading $artifactType using the presigned URL." }
75+ val fileMd5: String = Base64 .getEncoder().encodeToString(DigestUtils .md5(FileInputStream (zipFile)))
76+ val createUploadUrlResponse = createUploadUrl(fileMd5, artifactType, taskType, taskName, featureUseCase)
77+ val url = createUploadUrlResponse.uploadUrl()
78+ LOG .debug { " $featureUseCase : Uploading $artifactType using the presigned URL." }
6579
66- uploadArtifactToS3(
67- url,
68- createUploadUrlResponse.uploadId(),
69- zipFile,
70- fileMd5,
71- createUploadUrlResponse.kmsKeyArn(),
72- createUploadUrlResponse.requestHeaders(),
73- featureUseCase
74- )
75- return createUploadUrlResponse
80+ uploadArtifactToS3(
81+ url,
82+ createUploadUrlResponse.uploadId(),
83+ zipFile,
84+ fileMd5,
85+ createUploadUrlResponse.kmsKeyArn(),
86+ createUploadUrlResponse.requestHeaders(),
87+ featureUseCase
88+ )
89+ return createUploadUrlResponse
90+ } catch (e: Exception ) {
91+ result = MetricResult .Failed
92+ failureReason = e.javaClass.simpleName
93+ failureReasonDesc = e.message
94+ if (e is CodeWhispererCodeScanServerException ) {
95+ requestId = e.requestId
96+ requestServiceType = e.requestServiceType
97+ httpStatusCode = e.httpStatusCode
98+ }
99+ throw e
100+ } finally {
101+ if (featureUseCase == CodeWhispererConstants .FeatureName .CODE_REVIEW ) {
102+ AmazonqTelemetry .createUpload(
103+ amazonqConversationId = " " ,
104+ amazonqUploadIntent = if (taskType == CodeWhispererConstants .UploadTaskType .SCAN_PROJECT ) {
105+ AmazonqUploadIntent .FULLPROJECTSECURITYSCAN
106+ } else {
107+ AmazonqUploadIntent .AUTOMATICFILESECURITYSCAN
108+ },
109+ result = result,
110+ reason = failureReason,
111+ reasonDesc = failureReasonDesc,
112+ duration = (System .currentTimeMillis() - startTime).toDouble(),
113+ credentialStartUrl = getStartUrl(project),
114+ requestId = requestId,
115+ requestServiceType = requestServiceType,
116+ httpStatusCode = httpStatusCode
117+ )
118+ }
119+ }
76120 }
77121
78122 @Throws(IOException ::class )
@@ -85,6 +129,7 @@ class CodeWhispererZipUploadManager(private val project: Project) {
85129 requestHeaders : Map <String , String >? ,
86130 featureUseCase : CodeWhispererConstants .FeatureName ,
87131 ) {
132+ var connection: HttpURLConnection ? = null
88133 RetryableOperation <Unit >().execute(
89134 operation = {
90135 val uploadIdJson = """ {"uploadId":"$uploadId "}"""
@@ -103,9 +148,9 @@ class CodeWhispererZipUploadManager(private val project: Project) {
103148 }
104149 }
105150 }.connect {
106- val connection = it.connection as HttpURLConnection
107- connection.setFixedLengthStreamingMode(fileToUpload.length())
108- IoUtils .copy(fileToUpload.inputStream(), connection.outputStream)
151+ connection = it.connection as HttpURLConnection
152+ connection? .setFixedLengthStreamingMode(fileToUpload.length())
153+ IoUtils .copy(fileToUpload.inputStream(), connection? .outputStream)
109154 }
110155 },
111156 isRetryable = { e ->
@@ -118,7 +163,12 @@ class CodeWhispererZipUploadManager(private val project: Project) {
118163 val errorMessage = getTelemetryErrorMessage(e, featureUseCase)
119164 when (featureUseCase) {
120165 CodeWhispererConstants .FeatureName .CODE_REVIEW ->
121- codeScanServerException(" CreateUploadUrlException: $errorMessage " )
166+ codeScanServerException(
167+ " CreateUploadUrlException: $errorMessage " ,
168+ connection?.getHeaderField(" x-amz-request-id" ),
169+ " s3" ,
170+ (e as ? HttpRequests .HttpStatusException )?.statusCode.toString()
171+ )
122172 CodeWhispererConstants .FeatureName .TEST_GENERATION ->
123173 throw CodeTestException (
124174 " UploadTestArtifactToS3Error: $errorMessage " ,
@@ -162,7 +212,11 @@ class CodeWhispererZipUploadManager(private val project: Project) {
162212 val errorMessage = getTelemetryErrorMessage(e, featureUseCase)
163213 when (featureUseCase) {
164214 CodeWhispererConstants .FeatureName .CODE_REVIEW ->
165- codeScanServerException(" CreateUploadUrlException after $attempts attempts: $errorMessage " )
215+ codeScanServerException(
216+ " CreateUploadUrlException after $attempts attempts: $errorMessage " ,
217+ requestId = (e as ? AwsServiceException )?.requestId(),
218+ httpStatusCode = (e as ? AwsServiceException )?.statusCode().toString()
219+ )
166220
167221 CodeWhispererConstants .FeatureName .TEST_GENERATION ->
168222 throw CodeTestException (
0 commit comments