@@ -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,66 @@ 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+ amazonqUploadIntent = if (taskType == CodeWhispererConstants .UploadTaskType .SCAN_PROJECT ) {
104+ AmazonqUploadIntent .FULLPROJECTSECURITYSCAN
105+ } else {
106+ AmazonqUploadIntent .AUTOMATICFILESECURITYSCAN
107+ },
108+ result = result,
109+ reason = failureReason,
110+ reasonDesc = failureReasonDesc,
111+ duration = (System .currentTimeMillis() - startTime).toDouble(),
112+ credentialStartUrl = getStartUrl(project),
113+ requestId = requestId,
114+ requestServiceType = requestServiceType,
115+ httpStatusCode = httpStatusCode
116+ )
117+ }
118+ }
76119 }
77120
78121 @Throws(IOException ::class )
@@ -85,6 +128,7 @@ class CodeWhispererZipUploadManager(private val project: Project) {
85128 requestHeaders : Map <String , String >? ,
86129 featureUseCase : CodeWhispererConstants .FeatureName ,
87130 ) {
131+ var connection: HttpURLConnection ? = null
88132 RetryableOperation <Unit >().execute(
89133 operation = {
90134 val uploadIdJson = """ {"uploadId":"$uploadId "}"""
@@ -103,9 +147,9 @@ class CodeWhispererZipUploadManager(private val project: Project) {
103147 }
104148 }
105149 }.connect {
106- val connection = it.connection as HttpURLConnection
107- connection.setFixedLengthStreamingMode(fileToUpload.length())
108- IoUtils .copy(fileToUpload.inputStream(), connection.outputStream)
150+ connection = it.connection as HttpURLConnection
151+ connection? .setFixedLengthStreamingMode(fileToUpload.length())
152+ IoUtils .copy(fileToUpload.inputStream(), connection? .outputStream)
109153 }
110154 },
111155 isRetryable = { e ->
@@ -118,7 +162,12 @@ class CodeWhispererZipUploadManager(private val project: Project) {
118162 val errorMessage = getTelemetryErrorMessage(e, featureUseCase)
119163 when (featureUseCase) {
120164 CodeWhispererConstants .FeatureName .CODE_REVIEW ->
121- codeScanServerException(" CreateUploadUrlException: $errorMessage " )
165+ codeScanServerException(
166+ " CreateUploadUrlException: $errorMessage " ,
167+ connection?.getHeaderField(" x-amz-request-id" ),
168+ " s3" ,
169+ (e as ? HttpRequests .HttpStatusException )?.statusCode.toString()
170+ )
122171 CodeWhispererConstants .FeatureName .TEST_GENERATION ->
123172 throw CodeTestException (
124173 " UploadTestArtifactToS3Error: $errorMessage " ,
@@ -162,7 +211,11 @@ class CodeWhispererZipUploadManager(private val project: Project) {
162211 val errorMessage = getTelemetryErrorMessage(e, featureUseCase)
163212 when (featureUseCase) {
164213 CodeWhispererConstants .FeatureName .CODE_REVIEW ->
165- codeScanServerException(" CreateUploadUrlException after $attempts attempts: $errorMessage " )
214+ codeScanServerException(
215+ " CreateUploadUrlException after $attempts attempts: $errorMessage " ,
216+ requestId = (e as ? AwsServiceException )?.requestId(),
217+ httpStatusCode = (e as ? AwsServiceException )?.statusCode().toString()
218+ )
166219
167220 CodeWhispererConstants .FeatureName .TEST_GENERATION ->
168221 throw CodeTestException (
0 commit comments