Skip to content

Commit d334cf8

Browse files
authored
Security Scans: Improving telemetry error messages (#4500)
* Updating telemetry error messages
1 parent 32721cf commit d334cf8

File tree

5 files changed

+48
-28
lines changed

5 files changed

+48
-28
lines changed

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanException.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import software.aws.toolkits.resources.message
77

88
open class CodeWhispererCodeScanException(override val message: String?) : RuntimeException()
99

10-
open class UploadCodeScanException(override val message: String?) : Exception()
10+
open class CodeWhispererCodeScanServerException(override val message: String?) : RuntimeException()
1111

1212
internal fun noFileOpenError(): Nothing =
1313
throw CodeWhispererCodeScanException(message("codewhisperer.codescan.no_file_open"))
@@ -27,8 +27,8 @@ internal fun fileFormatNotSupported(format: String): Nothing =
2727
internal fun fileTooLarge(): Nothing =
2828
throw CodeWhispererCodeScanException(message("codewhisperer.codescan.file_too_large"))
2929

30-
internal fun uploadArtifactFailedError(errorMessage: String): Nothing =
31-
throw UploadCodeScanException(errorMessage)
30+
internal fun codeScanServerException(errorMessage: String): Nothing =
31+
throw CodeWhispererCodeScanServerException(errorMessage)
3232

3333
internal fun invalidSourceZipError(): Nothing =
3434
throw CodeWhispererCodeScanException(message("codewhisperer.codescan.invalid_source_zip_telemetry"))

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanManager.kt

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,26 @@ class CodeWhispererCodeScanManager(val project: Project) {
323323
return errorMessage
324324
}
325325

326+
private fun getCodeScanExceptionMessage(e: CodeWhispererCodeScanException): String? {
327+
val message = e.message
328+
return when {
329+
message.isNullOrBlank() -> null
330+
message == message("codewhisperer.codescan.invalid_source_zip_telemetry") -> {
331+
message("codewhisperer.codescan.run_scan_error")
332+
}
333+
else -> message
334+
}
335+
}
336+
337+
private fun getCodeScanServerExceptionMessage(e: CodeWhispererCodeScanServerException): String? =
338+
e.message?.takeIf { it.startsWith("UploadArtifactToS3Exception:") }
339+
?.let { message("codewhisperer.codescan.upload_to_s3_failed") }
340+
326341
fun handleException(coroutineContext: CoroutineContext, e: Exception, scope: CodeWhispererConstants.CodeAnalysisScope): String {
327342
val errorMessage = when (e) {
328343
is CodeWhispererException -> e.awsErrorDetails().errorMessage() ?: message("codewhisperer.codescan.run_scan_error")
329-
is CodeWhispererCodeScanException -> when (e.message) {
330-
message("codewhisperer.codescan.invalid_source_zip_telemetry") -> message("codewhisperer.codescan.run_scan_error")
331-
else -> e.message
332-
}
333-
is UploadCodeScanException -> message("codewhisperer.codescan.upload_to_s3_failed")
344+
is CodeWhispererCodeScanException -> getCodeScanExceptionMessage(e)
345+
is CodeWhispererCodeScanServerException -> getCodeScanServerExceptionMessage(e)
334346
is WaiterTimeoutException, is TimeoutCancellationException -> message("codewhisperer.codescan.scan_timed_out")
335347
is CancellationException -> message("codewhisperer.codescan.cancelled_by_user_exception")
336348
else -> null
@@ -372,10 +384,17 @@ class CodeWhispererCodeScanManager(val project: Project) {
372384
message("codewhisperer.codescan.file_too_large") -> message("codewhisperer.codescan.file_too_large_telemetry")
373385
else -> e.message
374386
}
375-
is UploadCodeScanException -> e.message
387+
is CodeWhispererCodeScanServerException -> e.message
376388
is WaiterTimeoutException, is TimeoutCancellationException -> message("codewhisperer.codescan.scan_timed_out")
377389
is CancellationException -> message("codewhisperer.codescan.cancelled_by_user_exception")
378-
else -> e.message
390+
else -> when {
391+
/**
392+
* Error message has text with user details(like requestId) which is specific so sending a custom error message to calculate the occurence of this event.
393+
*/
394+
e.message?.startsWith("Too many requests, please wait before trying again.") == true ->
395+
"Too many requests, please wait before trying again."
396+
else -> e.message
397+
}
379398
} ?: message("codewhisperer.codescan.run_scan_error_telemetry")
380399

381400
return telemetryErrorMessage

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanSession.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,8 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
285285
.build()
286286
)
287287
} catch (e: Exception) {
288-
throw e
288+
LOG.debug { "Create Upload URL failed: ${e.message}" }
289+
throw codeScanServerException("CreateUploadUrlException: " + e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry"))
289290
}
290291

291292
private fun getUploadIntent(scope: CodeWhispererConstants.CodeAnalysisScope): UploadIntent = when (scope) {
@@ -317,8 +318,8 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
317318
IoUtils.copy(fileToUpload.inputStream(), connection.outputStream)
318319
}
319320
} catch (e: Exception) {
320-
val errorMessage = e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry")
321-
throw uploadArtifactFailedError(errorMessage)
321+
LOG.debug { "Artifact failed to upload in the S3 bucket: ${e.message}" }
322+
throw codeScanServerException("UploadArtifactToS3Exception: " + e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry"))
322323
}
323324
}
324325

@@ -340,7 +341,7 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
340341
)
341342
} catch (e: Exception) {
342343
LOG.debug { "Creating security scan failed: ${e.message}" }
343-
throw e
344+
throw codeScanServerException("CreateCodeScanException: " + e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry"))
344345
}
345346
}
346347

@@ -352,7 +353,7 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
352353
)
353354
} catch (e: Exception) {
354355
LOG.debug { "Getting security scan failed: ${e.message}" }
355-
throw e
356+
throw codeScanServerException("GetCodeScanException: " + e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry"))
356357
}
357358

358359
fun listCodeScanFindings(jobId: String, nextToken: String?): ListCodeScanFindingsResponse = try {
@@ -365,7 +366,7 @@ class CodeWhispererCodeScanSession(val sessionContext: CodeScanSessionContext) {
365366
)
366367
} catch (e: Exception) {
367368
LOG.debug { "Listing security scan failed: ${e.message}" }
368-
throw e
369+
throw codeScanServerException("ListCodeScanFindingsException: " + e.message?.let { it } ?: message("codewhisperer.codescan.run_scan_error_telemetry"))
369370
}
370371

371372
fun mapToCodeScanIssues(recommendations: List<String>): List<CodeWhispererCodeScanIssue> {

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeFileScanTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,14 @@ class CodeWhispererCodeFileScanTest : CodeWhispererCodeScanTestBase(PythonCodeIn
311311
@Test
312312
fun `test run() - createCodeScan error`() {
313313
mockClient.stub {
314-
onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanException::class.java)
314+
onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanServerException::class.java)
315315
}
316316

317317
runBlocking {
318318
val codeScanResponse = codeScanSessionSpy.run()
319319
assertThat(codeScanResponse).isInstanceOf<CodeScanResponse.Failure>()
320320
assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext)
321-
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanException>()
321+
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanServerException>()
322322
}
323323
}
324324

@@ -361,28 +361,28 @@ class CodeWhispererCodeFileScanTest : CodeWhispererCodeScanTestBase(PythonCodeIn
361361
@Test
362362
fun `test run() - getCodeScan error`() {
363363
mockClient.stub {
364-
onGeneric { getCodeScan(any(), any()) }.thenThrow(CodeWhispererException::class.java)
364+
onGeneric { getCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanServerException::class.java)
365365
}
366366

367367
runBlocking {
368368
val codeScanResponse = codeScanSessionSpy.run()
369369
assertThat(codeScanResponse).isInstanceOf<CodeScanResponse.Failure>()
370370
assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext)
371-
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererException>()
371+
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanServerException>()
372372
}
373373
}
374374

375375
@Test
376376
fun `test run() - listCodeScanFindings error`() {
377377
mockClient.stub {
378-
onGeneric { listCodeScanFindings(any(), any()) }.thenThrow(CodeWhispererException::class.java)
378+
onGeneric { listCodeScanFindings(any(), any()) }.thenThrow(CodeWhispererCodeScanServerException::class.java)
379379
}
380380

381381
runBlocking {
382382
val codeScanResponse = codeScanSessionSpy.run()
383383
assertThat(codeScanResponse).isInstanceOf<CodeScanResponse.Failure>()
384384
assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext)
385-
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererException>()
385+
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanServerException>()
386386
}
387387
}
388388

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codescan/CodeWhispererCodeScanTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,14 @@ class CodeWhispererCodeScanTest : CodeWhispererCodeScanTestBase(PythonCodeInsigh
222222
@Test
223223
fun `test run() - createCodeScan error`() {
224224
mockClient.stub {
225-
onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanException::class.java)
225+
onGeneric { createCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanServerException::class.java)
226226
}
227227

228228
runBlocking {
229229
val codeScanResponse = codeScanSessionSpy.run()
230230
assertThat(codeScanResponse).isInstanceOf<CodeScanResponse.Failure>()
231231
assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext)
232-
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanException>()
232+
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanServerException>()
233233
}
234234
}
235235

@@ -272,28 +272,28 @@ class CodeWhispererCodeScanTest : CodeWhispererCodeScanTestBase(PythonCodeInsigh
272272
@Test
273273
fun `test run() - getCodeScan error`() {
274274
mockClient.stub {
275-
onGeneric { getCodeScan(any(), any()) }.thenThrow(CodeWhispererException::class.java)
275+
onGeneric { getCodeScan(any(), any()) }.thenThrow(CodeWhispererCodeScanServerException::class.java)
276276
}
277277

278278
runBlocking {
279279
val codeScanResponse = codeScanSessionSpy.run()
280280
assertThat(codeScanResponse).isInstanceOf<CodeScanResponse.Failure>()
281281
assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext)
282-
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererException>()
282+
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanServerException>()
283283
}
284284
}
285285

286286
@Test
287287
fun `test run() - listCodeScanFindings error`() {
288288
mockClient.stub {
289-
onGeneric { listCodeScanFindings(any(), any()) }.thenThrow(CodeWhispererException::class.java)
289+
onGeneric { listCodeScanFindings(any(), any()) }.thenThrow(CodeWhispererCodeScanServerException::class.java)
290290
}
291291

292292
runBlocking {
293293
val codeScanResponse = codeScanSessionSpy.run()
294294
assertThat(codeScanResponse).isInstanceOf<CodeScanResponse.Failure>()
295295
assertThat(codeScanResponse.responseContext.payloadContext).isEqualTo(payloadContext)
296-
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererException>()
296+
assertThat((codeScanResponse as CodeScanResponse.Failure).failureReason).isInstanceOf<CodeWhispererCodeScanServerException>()
297297
}
298298
}
299299

0 commit comments

Comments
 (0)