Skip to content

Commit a69638f

Browse files
authored
telemetry(amazonq): createUpload metric for scans (aws#6715)
## Problem Some users are reporting S3 upload failures but we don't have the requestIds to investigate further. ## Solution Emit `amazonq_createUpload` metric with requestIds --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 1a313e4 commit a69638f

File tree

3 files changed

+71
-40
lines changed

3 files changed

+71
-40
lines changed

packages/core/src/codewhisperer/service/securityScanHandler.ts

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,9 @@ import { RawCodeScanIssue } from '../models/model'
2222
import * as crypto from 'crypto'
2323
import path = require('path')
2424
import { pageableToCollection } from '../../shared/utilities/collectionUtils'
25-
import {
26-
ArtifactMap,
27-
CreateUploadUrlRequest,
28-
CreateUploadUrlResponse,
29-
UploadIntent,
30-
} from '../client/codewhispereruserclient'
25+
import { ArtifactMap, CreateUploadUrlRequest, CreateUploadUrlResponse } from '../client/codewhispereruserclient'
3126
import { TelemetryHelper } from '../util/telemetryHelper'
32-
import request from '../../shared/request'
27+
import request, { RequestError } from '../../shared/request'
3328
import { ZipMetadata } from '../util/zipUtil'
3429
import { getNullLogger } from '../../shared/logger/logger'
3530
import {
@@ -49,6 +44,8 @@ import { ChatSessionManager } from '../../amazonqTest/chat/storages/chatSession'
4944
import { getStringHash } from '../../shared/utilities/textUtilities'
5045
import { getClientId } from '../../shared/telemetry/util'
5146
import globals from '../../shared/extensionGlobals'
47+
import { AmazonqCreateUpload, Span, telemetry } from '../../shared/telemetry/telemetry'
48+
import { AuthUtil } from '../util/authUtil'
5249

5350
export async function listScanResults(
5451
client: DefaultCodeWhispererClient,
@@ -276,45 +273,55 @@ export async function getPresignedUrlAndUpload(
276273
scope: CodeWhispererConstants.CodeAnalysisScope,
277274
scanName: string
278275
) {
279-
const logger = getLoggerForScope(scope)
280-
if (zipMetadata.zipFilePath === '') {
281-
getLogger().error('Failed to create valid source zip')
282-
throw new InvalidSourceZipError()
283-
}
284-
const srcReq: CreateUploadUrlRequest = {
285-
contentMd5: getMd5(zipMetadata.zipFilePath),
286-
artifactType: 'SourceCode',
287-
uploadIntent: getUploadIntent(scope),
288-
uploadContext: {
289-
codeAnalysisUploadContext: {
290-
codeScanName: scanName,
276+
const artifactMap = await telemetry.amazonq_createUpload.run(async (span) => {
277+
const logger = getLoggerForScope(scope)
278+
if (zipMetadata.zipFilePath === '') {
279+
getLogger().error('Failed to create valid source zip')
280+
throw new InvalidSourceZipError()
281+
}
282+
const uploadIntent = getUploadIntent(scope)
283+
span.record({
284+
amazonqUploadIntent: uploadIntent,
285+
amazonqRepositorySize: zipMetadata.srcPayloadSizeInBytes,
286+
credentialStartUrl: AuthUtil.instance.startUrl,
287+
})
288+
const srcReq: CreateUploadUrlRequest = {
289+
contentMd5: getMd5(zipMetadata.zipFilePath),
290+
artifactType: 'SourceCode',
291+
uploadIntent: uploadIntent,
292+
uploadContext: {
293+
codeAnalysisUploadContext: {
294+
codeScanName: scanName,
295+
},
291296
},
292-
},
293-
}
294-
logger.verbose(`Prepare for uploading src context...`)
295-
const srcResp = await client.createUploadUrl(srcReq).catch((err) => {
296-
getLogger().error(`Failed getting presigned url for uploading src context. Request id: ${err.requestId}`)
297-
throw new CreateUploadUrlError(err)
297+
}
298+
logger.verbose(`Prepare for uploading src context...`)
299+
const srcResp = await client.createUploadUrl(srcReq).catch((err) => {
300+
getLogger().error(`Failed getting presigned url for uploading src context. Request id: ${err.requestId}`)
301+
span.record({ requestId: err.requestId })
302+
throw new CreateUploadUrlError(err.message)
303+
})
304+
logger.verbose(`CreateUploadUrlRequest request id: ${srcResp.$response.requestId}`)
305+
logger.verbose(`Complete Getting presigned Url for uploading src context.`)
306+
logger.verbose(`Uploading src context...`)
307+
await uploadArtifactToS3(zipMetadata.zipFilePath, srcResp, FeatureUseCase.CODE_SCAN, scope, span)
308+
logger.verbose(`Complete uploading src context.`)
309+
const artifactMap: ArtifactMap = {
310+
SourceCode: srcResp.uploadId,
311+
}
312+
return artifactMap
298313
})
299-
logger.verbose(`CreateUploadUrlRequest request id: ${srcResp.$response.requestId}`)
300-
logger.verbose(`Complete Getting presigned Url for uploading src context.`)
301-
logger.verbose(`Uploading src context...`)
302-
await uploadArtifactToS3(zipMetadata.zipFilePath, srcResp, FeatureUseCase.CODE_SCAN, scope)
303-
logger.verbose(`Complete uploading src context.`)
304-
const artifactMap: ArtifactMap = {
305-
SourceCode: srcResp.uploadId,
306-
}
307314
return artifactMap
308315
}
309316

310-
function getUploadIntent(scope: CodeWhispererConstants.CodeAnalysisScope): UploadIntent {
317+
function getUploadIntent(scope: CodeWhispererConstants.CodeAnalysisScope) {
311318
if (
312-
scope === CodeWhispererConstants.CodeAnalysisScope.FILE_AUTO ||
319+
scope === CodeWhispererConstants.CodeAnalysisScope.PROJECT ||
313320
scope === CodeWhispererConstants.CodeAnalysisScope.FILE_ON_DEMAND
314321
) {
315-
return CodeWhispererConstants.fileScanUploadIntent
316-
} else {
317322
return CodeWhispererConstants.projectScanUploadIntent
323+
} else {
324+
return CodeWhispererConstants.fileScanUploadIntent
318325
}
319326
}
320327

@@ -356,7 +363,8 @@ export async function uploadArtifactToS3(
356363
fileName: string,
357364
resp: CreateUploadUrlResponse,
358365
featureUseCase: FeatureUseCase,
359-
scope?: CodeWhispererConstants.CodeAnalysisScope
366+
scope?: CodeWhispererConstants.CodeAnalysisScope,
367+
span?: Span<AmazonqCreateUpload>
360368
) {
361369
const logger = getLoggerForScope(scope)
362370
const encryptionContext = `{"uploadId":"${resp.uploadId}"}`
@@ -378,6 +386,14 @@ export async function uploadArtifactToS3(
378386
}).response
379387
logger.debug(`StatusCode: ${response.status}, Text: ${response.statusText}`)
380388
} catch (error) {
389+
if (span && error instanceof RequestError) {
390+
const requestId = error.response.headers.get('x-amz-request-id') ?? undefined
391+
span.record({
392+
requestId: requestId,
393+
requestServiceType: 's3',
394+
httpStatusCode: error.code.toString(),
395+
})
396+
}
381397
let errorMessage = ''
382398
const isCodeScan = featureUseCase === FeatureUseCase.CODE_SCAN
383399
const featureType = isCodeScan ? 'security scans' : 'unit test generation'

packages/core/src/shared/telemetry/spans.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ export class TelemetrySpan<T extends MetricBase = MetricBase> implements Span<T>
219219
result: getTelemetryResult(err),
220220
reason: getTelemetryReason(err),
221221
reasonDesc: getTelemetryReasonDesc(err),
222-
requestId: getRequestId(err),
223-
httpStatusCode: getHttpStatusCode(err),
222+
...(!this.state.requestId ? { requestId: getRequestId(err) } : {}),
223+
...(!this.state.httpStatusCode ? { httpStatusCode: getHttpStatusCode(err) } : {}),
224224
} as Partial<T>)
225225
}
226226

packages/core/src/shared/telemetry/vscodeTelemetry.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,17 @@
415415
"name": "executedCount",
416416
"type": "int",
417417
"description": "The number of executed operations"
418+
},
419+
{
420+
"name": "amazonqUploadIntent",
421+
"type": "string",
422+
"description": "The intent of the upload",
423+
"allowedValues": [
424+
"TRANSFORMATION",
425+
"TASK_ASSIST_PLANNING",
426+
"AUTOMATIC_FILE_SECURITY_SCAN",
427+
"FULL_PROJECT_SECURITY_SCAN"
428+
]
418429
}
419430
],
420431
"metrics": [
@@ -1212,6 +1223,10 @@
12121223
"type": "amazonqRepositorySize",
12131224
"required": false
12141225
},
1226+
{
1227+
"type": "amazonqUploadIntent",
1228+
"required": false
1229+
},
12151230
{
12161231
"type": "credentialStartUrl",
12171232
"required": false

0 commit comments

Comments
 (0)