Skip to content

Commit 40f3237

Browse files
authored
feat(codewhisperer): telemetry for total project size #2847
Update security scan telemetry to track overall project size
1 parent a9801e8 commit 40f3237

File tree

7 files changed

+66
-10
lines changed

7 files changed

+66
-10
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3196,7 +3196,7 @@
31963196
"report": "nyc report --reporter=html --reporter=json"
31973197
},
31983198
"devDependencies": {
3199-
"@aws-toolkits/telemetry": "^1.0.64",
3199+
"@aws-toolkits/telemetry": "^1.0.67",
32003200
"@cspotcode/source-map-support": "^0.8.1",
32013201
"@sinonjs/fake-timers": "^8.1.0",
32023202
"@types/adm-zip": "^0.4.34",

src/codewhisperer/commands/startSecurityScan.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { codeScanState, CodeScanTelemetryEntry } from '../models/model'
2424
import { openSettings } from '../../shared/settings'
2525
import { ok, viewSettings } from '../../shared/localizedText'
2626
import { statSync } from 'fs'
27+
import { getFileExt } from '../util/commonUtil'
28+
import { getDirSize } from '../../shared/filesystemUtilities'
2729

2830
const performance = globalThis.performance ?? require('perf_hooks').performance
2931

@@ -168,10 +170,26 @@ export async function startSecurityScan(
168170
await vscode.commands.executeCommand('aws.codeWhisperer.refresh')
169171
codeScanTelemetryEntry.duration = performance.now() - codeScanStartTime
170172
codeScanTelemetryEntry.codeScanServiceInvocationsDuration = performance.now() - serviceInvocationStartTime
171-
telemetry.recordCodewhispererSecurityScan(codeScanTelemetryEntry)
173+
emitCodeScanTelemetry(editor, codeScanTelemetryEntry)
172174
}
173175
}
174176

177+
export async function emitCodeScanTelemetry(editor: vscode.TextEditor, codeScanTelemetryEntry: CodeScanTelemetryEntry) {
178+
const uri = editor.document.uri
179+
const workspaceFolder = vscode.workspace.getWorkspaceFolder(uri)
180+
const fileExt = getFileExt(editor.document.languageId)
181+
if (workspaceFolder !== undefined && fileExt !== undefined) {
182+
const projectSize = await getDirSize(
183+
workspaceFolder.uri.fsPath,
184+
performance.now(),
185+
CodeWhispererConstants.projectSizeCalculateTimeoutSeconds * 1000,
186+
fileExt
187+
)
188+
codeScanTelemetryEntry.codewhispererCodeScanProjectBytes = projectSize
189+
}
190+
telemetry.recordCodewhispererSecurityScan(codeScanTelemetryEntry)
191+
}
192+
175193
export function errorPromptHelper(error: Error) {
176194
if (error instanceof JavaDependencyGraphError) {
177195
vscode.window

src/codewhisperer/models/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export const CodeWhispererConstants = {
127127
codeScanZipExt: '.zip',
128128
contextTruncationTimeoutSeconds: 10,
129129
codeScanJobTimeoutSeconds: 50,
130+
projectSizeCalculateTimeoutSeconds: 10,
130131
codeScanJobPollingIntervalSeconds: 5,
131132
artifactTypeSource: 'SourceCode',
132133
artifactTypeBuild: 'BuiltJars',

src/codewhisperer/models/model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export const codeScanState: CodeScanState = {
8383
export interface CodeScanTelemetryEntry {
8484
codewhispererCodeScanJobId?: string
8585
codewhispererLanguage: telemetry.CodewhispererLanguage
86+
codewhispererCodeScanProjectBytes?: number
8687
codewhispererCodeScanSrcPayloadBytes: number
8788
codewhispererCodeScanBuildPayloadBytes?: number
8889
codewhispererCodeScanSrcZipFileBytes: number

src/codewhisperer/util/commonUtil.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5-
65
export function getLocalDatetime() {
76
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
87
return new Date().toLocaleString([], { timeZone: timezone })
@@ -27,3 +26,15 @@ export function isAwsError(error: any): boolean {
2726
error.time instanceof Date
2827
)
2928
}
29+
30+
export function getFileExt(languageId: string) {
31+
switch (languageId) {
32+
case 'java':
33+
return '.java'
34+
case 'python':
35+
return '.py'
36+
default:
37+
break
38+
}
39+
return undefined
40+
}

src/shared/filesystemUtilities.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { access, mkdtemp, mkdirp, readFile, remove, existsSync, readdir, stat } from 'fs-extra'
77
import * as crypto from 'crypto'
88
import * as fs from 'fs'
9+
import * as fsExtra from 'fs-extra'
910
import * as os from 'os'
1011
import * as path from 'path'
1112
import * as vscode from 'vscode'
@@ -20,6 +21,30 @@ export const tempDirPath = path.join(
2021
'aws-toolkit-vscode'
2122
)
2223

24+
export async function getDirSize(
25+
dirPath: string,
26+
startTime: number,
27+
duration: number,
28+
fileExt: string
29+
): Promise<number> {
30+
if (performance.now() - startTime > duration) {
31+
getLogger().warn('getDirSize: exceeds time limit')
32+
return 0
33+
}
34+
const files = await fsExtra.readdir(dirPath, { withFileTypes: true })
35+
const fileSizes = files.map(async file => {
36+
const filePath = path.join(dirPath, file.name)
37+
if (file.isSymbolicLink()) return 0
38+
if (file.isDirectory()) return getDirSize(filePath, startTime, duration, fileExt)
39+
if (file.isFile() && file.name.endsWith(fileExt)) {
40+
const { size } = await fsExtra.stat(filePath)
41+
return size
42+
}
43+
return 0
44+
})
45+
return (await Promise.all(fileSizes)).reduce((accumulator, size) => accumulator + size, 0)
46+
}
47+
2348
export function downloadsDir(): string {
2449
const downloadPath = path.join(os.homedir(), 'Downloads')
2550
if (existsSync(downloadPath)) {

0 commit comments

Comments
 (0)