diff --git a/packages/core/src/codewhisperer/service/securityScanHandler.ts b/packages/core/src/codewhisperer/service/securityScanHandler.ts index 23ee028d22f..0f2a964181d 100644 --- a/packages/core/src/codewhisperer/service/securityScanHandler.ts +++ b/packages/core/src/codewhisperer/service/securityScanHandler.ts @@ -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 { @@ -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, @@ -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 } } @@ -356,7 +363,8 @@ export async function uploadArtifactToS3( fileName: string, resp: CreateUploadUrlResponse, featureUseCase: FeatureUseCase, - scope?: CodeWhispererConstants.CodeAnalysisScope + scope?: CodeWhispererConstants.CodeAnalysisScope, + span?: Span ) { const logger = getLoggerForScope(scope) const encryptionContext = `{"uploadId":"${resp.uploadId}"}` @@ -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' diff --git a/packages/core/src/shared/telemetry/spans.ts b/packages/core/src/shared/telemetry/spans.ts index 08923703be5..4521a83a12a 100644 --- a/packages/core/src/shared/telemetry/spans.ts +++ b/packages/core/src/shared/telemetry/spans.ts @@ -219,8 +219,8 @@ export class TelemetrySpan implements Span 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) } : {}), } as Partial) } diff --git a/packages/core/src/shared/telemetry/vscodeTelemetry.json b/packages/core/src/shared/telemetry/vscodeTelemetry.json index 09339283bee..0450ca42607 100644 --- a/packages/core/src/shared/telemetry/vscodeTelemetry.json +++ b/packages/core/src/shared/telemetry/vscodeTelemetry.json @@ -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", + "TASK_ASSIST_PLANNING", + "AUTOMATIC_FILE_SECURITY_SCAN", + "FULL_PROJECT_SECURITY_SCAN" + ] } ], "metrics": [ @@ -1166,6 +1177,10 @@ "type": "amazonqRepositorySize", "required": false }, + { + "type": "amazonqUploadIntent", + "required": false + }, { "type": "credentialStartUrl", "required": false