Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 54 additions & 38 deletions packages/core/src/codewhisperer/service/securityScanHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,9 @@ import { RawCodeScanIssue } from '../models/model'
import * as crypto from 'crypto'
import path = require('path')
import { pageableToCollection } from '../../shared/utilities/collectionUtils'
import {
ArtifactMap,
CreateUploadUrlRequest,
CreateUploadUrlResponse,
UploadIntent,
} from '../client/codewhispereruserclient'
import { ArtifactMap, CreateUploadUrlRequest, CreateUploadUrlResponse } from '../client/codewhispereruserclient'
import { TelemetryHelper } from '../util/telemetryHelper'
import request from '../../shared/request'
import request, { RequestError } from '../../shared/request'
import { ZipMetadata } from '../util/zipUtil'
import { getNullLogger } from '../../shared/logger/logger'
import {
Expand All @@ -49,6 +44,8 @@ import { ChatSessionManager } from '../../amazonqTest/chat/storages/chatSession'
import { getStringHash } from '../../shared/utilities/textUtilities'
import { getClientId } from '../../shared/telemetry/util'
import globals from '../../shared/extensionGlobals'
import { AmazonqCreateUpload, Span, telemetry } from '../../shared/telemetry/telemetry'
import { AuthUtil } from '../util/authUtil'

export async function listScanResults(
client: DefaultCodeWhispererClient,
Expand Down Expand Up @@ -276,45 +273,55 @@ export async function getPresignedUrlAndUpload(
scope: CodeWhispererConstants.CodeAnalysisScope,
scanName: string
) {
const logger = getLoggerForScope(scope)
if (zipMetadata.zipFilePath === '') {
getLogger().error('Failed to create valid source zip')
throw new InvalidSourceZipError()
}
const srcReq: CreateUploadUrlRequest = {
contentMd5: getMd5(zipMetadata.zipFilePath),
artifactType: 'SourceCode',
uploadIntent: getUploadIntent(scope),
uploadContext: {
codeAnalysisUploadContext: {
codeScanName: scanName,
const artifactMap = await telemetry.amazonq_createUpload.run(async (span) => {
const logger = getLoggerForScope(scope)
if (zipMetadata.zipFilePath === '') {
getLogger().error('Failed to create valid source zip')
throw new InvalidSourceZipError()
}
const uploadIntent = getUploadIntent(scope)
span.record({
amazonqUploadIntent: uploadIntent,
amazonqRepositorySize: zipMetadata.srcPayloadSizeInBytes,
credentialStartUrl: AuthUtil.instance.startUrl,
})
const srcReq: CreateUploadUrlRequest = {
contentMd5: getMd5(zipMetadata.zipFilePath),
artifactType: 'SourceCode',
uploadIntent: uploadIntent,
uploadContext: {
codeAnalysisUploadContext: {
codeScanName: scanName,
},
},
},
}
logger.verbose(`Prepare for uploading src context...`)
const srcResp = await client.createUploadUrl(srcReq).catch((err) => {
getLogger().error(`Failed getting presigned url for uploading src context. Request id: ${err.requestId}`)
throw new CreateUploadUrlError(err)
}
logger.verbose(`Prepare for uploading src context...`)
const srcResp = await client.createUploadUrl(srcReq).catch((err) => {
getLogger().error(`Failed getting presigned url for uploading src context. Request id: ${err.requestId}`)
span.record({ requestId: err.requestId })
throw new CreateUploadUrlError(err.message)
})
logger.verbose(`CreateUploadUrlRequest request id: ${srcResp.$response.requestId}`)
logger.verbose(`Complete Getting presigned Url for uploading src context.`)
logger.verbose(`Uploading src context...`)
await uploadArtifactToS3(zipMetadata.zipFilePath, srcResp, FeatureUseCase.CODE_SCAN, scope, span)
logger.verbose(`Complete uploading src context.`)
const artifactMap: ArtifactMap = {
SourceCode: srcResp.uploadId,
}
return artifactMap
})
logger.verbose(`CreateUploadUrlRequest request id: ${srcResp.$response.requestId}`)
logger.verbose(`Complete Getting presigned Url for uploading src context.`)
logger.verbose(`Uploading src context...`)
await uploadArtifactToS3(zipMetadata.zipFilePath, srcResp, FeatureUseCase.CODE_SCAN, scope)
logger.verbose(`Complete uploading src context.`)
const artifactMap: ArtifactMap = {
SourceCode: srcResp.uploadId,
}
return artifactMap
}

function getUploadIntent(scope: CodeWhispererConstants.CodeAnalysisScope): UploadIntent {
function getUploadIntent(scope: CodeWhispererConstants.CodeAnalysisScope) {
if (
scope === CodeWhispererConstants.CodeAnalysisScope.FILE_AUTO ||
scope === CodeWhispererConstants.CodeAnalysisScope.PROJECT ||
scope === CodeWhispererConstants.CodeAnalysisScope.FILE_ON_DEMAND
) {
return CodeWhispererConstants.fileScanUploadIntent
} else {
return CodeWhispererConstants.projectScanUploadIntent
} else {
return CodeWhispererConstants.fileScanUploadIntent
}
}

Expand Down Expand Up @@ -356,7 +363,8 @@ export async function uploadArtifactToS3(
fileName: string,
resp: CreateUploadUrlResponse,
featureUseCase: FeatureUseCase,
scope?: CodeWhispererConstants.CodeAnalysisScope
scope?: CodeWhispererConstants.CodeAnalysisScope,
span?: Span<AmazonqCreateUpload>
) {
const logger = getLoggerForScope(scope)
const encryptionContext = `{"uploadId":"${resp.uploadId}"}`
Expand All @@ -378,6 +386,14 @@ export async function uploadArtifactToS3(
}).response
logger.debug(`StatusCode: ${response.status}, Text: ${response.statusText}`)
} catch (error) {
if (span && error instanceof RequestError) {
const requestId = error.response.headers.get('x-amz-request-id') ?? undefined
span.record({
requestId: requestId,
requestServiceType: 's3',
httpStatusCode: error.code.toString(),
})
}
let errorMessage = ''
const isCodeScan = featureUseCase === FeatureUseCase.CODE_SCAN
const featureType = isCodeScan ? 'security scans' : 'unit test generation'
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/shared/telemetry/spans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ export class TelemetrySpan<T extends MetricBase = MetricBase> implements Span<T>
result: getTelemetryResult(err),
reason: getTelemetryReason(err),
reasonDesc: getTelemetryReasonDesc(err),
requestId: getRequestId(err),
httpStatusCode: getHttpStatusCode(err),
...(!this.state.requestId ? { requestId: getRequestId(err) } : {}),
...(!this.state.httpStatusCode ? { httpStatusCode: getHttpStatusCode(err) } : {}),
Comment on lines +222 to +223
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this change to allow requestId and httpStatusCode to be set explicitly before the stop method is invoked. Otherwise it will silently get removed if err is not the correct format.

} as Partial<T>)
}

Expand Down
35 changes: 35 additions & 0 deletions packages/core/src/shared/telemetry/vscodeTelemetry.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,17 @@
"name": "executedCount",
"type": "int",
"description": "The number of executed operations"
},
{
"name": "amazonqUploadIntent",
"type": "string",
"description": "The intent of the upload",
"allowedValues": [
"TRANSFORMATION",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can you add TEST_GENERATION as allowed value, if not I can add this as part of next PR's or while shipping this to common package.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NVM, I will make change for UTG.
Thanks @ctlai95

"TASK_ASSIST_PLANNING",
"AUTOMATIC_FILE_SECURITY_SCAN",
"FULL_PROJECT_SECURITY_SCAN"
]
}
],
"metrics": [
Expand Down Expand Up @@ -1166,9 +1177,33 @@
"type": "amazonqRepositorySize",
"required": false
},
{
"type": "amazonqUploadIntent",
"required": false
},
{
"type": "credentialStartUrl",
"required": false
},
{
"type": "duration",
"required": false
},
{
"type": "reason",
"required": false
},
{
"type": "requestId",
"required": false
},
{
"type": "requestServiceType",
"required": false
},
{
"type": "result",
"required": false
}
]
},
Expand Down
Loading