diff --git a/packages/core/src/codewhisperer/models/model.ts b/packages/core/src/codewhisperer/models/model.ts index 257ffedb403..117c0934091 100644 --- a/packages/core/src/codewhisperer/models/model.ts +++ b/packages/core/src/codewhisperer/models/model.ts @@ -413,6 +413,8 @@ export class TransformByQState { private metadataPathSQL: string = '' + private linesOfCodeSubmitted: number | undefined = undefined + private planFilePath: string = '' private summaryFilePath: string = '' private preBuildLogFilePath: string = '' @@ -485,6 +487,10 @@ export class TransformByQState { return this.customBuildCommand } + public getLinesOfCodeSubmitted() { + return this.linesOfCodeSubmitted + } + public getPreBuildLogFilePath() { return this.preBuildLogFilePath } @@ -645,6 +651,10 @@ export class TransformByQState { this.customBuildCommand = command } + public setLinesOfCodeSubmitted(lines: number) { + this.linesOfCodeSubmitted = lines + } + public setStartTime(time: string) { this.startTime = time } diff --git a/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts b/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts index 55cd7797e5e..745f0942e45 100644 --- a/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts +++ b/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts @@ -573,6 +573,7 @@ export async function getTransformationPlan(jobId: string) { const linesOfCode = Number( jobStatistics.find((stat: { name: string; value: string }) => stat.name === 'linesOfCode').value ) + transformByQState.setLinesOfCodeSubmitted(linesOfCode) if (authType === 'iamIdentityCenter' && linesOfCode > CodeWhispererConstants.codeTransformLocThreshold) { plan += CodeWhispererConstants.codeTransformBillingText(linesOfCode) } diff --git a/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts b/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts index 2f75795c251..eab339df718 100644 --- a/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts +++ b/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts @@ -10,7 +10,7 @@ import { parsePatch, applyPatches, ParsedDiff } from 'diff' import path from 'path' import vscode from 'vscode' import { ExportIntent } from '@amzn/codewhisperer-streaming' -import { TransformByQReviewStatus, transformByQState } from '../../models/model' +import { TransformationType, TransformByQReviewStatus, transformByQState } from '../../models/model' import { ExportResultArchiveStructure, downloadExportResultArchive } from '../../../shared/utilities/download' import { getLogger } from '../../../shared/logger' import { telemetry } from '../../../shared/telemetry/telemetry' @@ -20,6 +20,7 @@ import * as CodeWhispererConstants from '../../models/constants' import { createCodeWhispererChatStreamingClient } from '../../../shared/clients/codewhispererChatClient' import { ChatSessionManager } from '../../../amazonqGumby/chat/storages/chatSession' import { setContext } from '../../../shared/vscode/setContext' +import * as codeWhisperer from '../../client/codewhisperer' export abstract class ProposedChangeNode { abstract readonly resourcePath: string @@ -402,6 +403,33 @@ export class ProposedTransformationExplorer { `${CodeWhispererConstants.errorDeserializingDiffNotification} ${deserializeErrorMessage}` ) } + + try { + const metricsPath = path.join(pathContainingArchive, ExportResultArchiveStructure.PathToMetrics) + const metricsData = JSON.parse(fs.readFileSync(metricsPath, 'utf8')) + + await codeWhisperer.codeWhispererClient.sendTelemetryEvent({ + telemetryEvent: { + transformEvent: { + jobId: transformByQState.getJobId(), + timestamp: new Date(), + ideCategory: 'VSCODE', + programmingLanguage: { + languageName: + transformByQState.getTransformationType() === TransformationType.LANGUAGE_UPGRADE + ? 'JAVA' + : 'SQL', + }, + linesOfCodeChanged: metricsData.linesOfCodeChanged, + charsOfCodeChanged: metricsData.charactersOfCodeChanged, + linesOfCodeSubmitted: transformByQState.getLinesOfCodeSubmitted(), // currently unavailable for SQL conversions + }, + }, + }) + } catch (err: any) { + // log error, but continue to show user diff.patch with results + getLogger().error(`CodeTransformation: SendTelemetryEvent error = ${err.message}`) + } }) vscode.commands.registerCommand('aws.amazonq.transformationHub.reviewChanges.acceptChanges', async () => { diff --git a/packages/core/src/shared/utilities/download.ts b/packages/core/src/shared/utilities/download.ts index 8c9f5479ac0..dfb4c551427 100644 --- a/packages/core/src/shared/utilities/download.ts +++ b/packages/core/src/shared/utilities/download.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import path from 'path' import { CodeWhispererStreaming, ExportResultArchiveCommandInput } from '@amzn/codewhisperer-streaming' import { ToolkitError } from '../errors' import fs from '../fs/fs' @@ -12,8 +11,9 @@ import fs from '../fs/fs' * This class represents the structure of the archive returned by the ExportResultArchive endpoint */ export class ExportResultArchiveStructure { - static readonly PathToSummary = path.join('summary', 'summary.md') - static readonly PathToDiffPatch = path.join('patch', 'diff.patch') + static readonly PathToSummary = 'summary/summary.md' + static readonly PathToDiffPatch = 'patch/diff.patch' + static readonly PathToMetrics = 'metrics/metrics.json' static readonly PathToManifest = 'manifest.json' }