Skip to content

Commit fee1fcb

Browse files
committed
merge in telemetry changes
2 parents 31fd2b9 + c0bc44e commit fee1fcb

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
"type": "int",
66
"description": "A generic size for when units are clear"
77
},
8+
{
9+
"name": "systemResource",
10+
"type": "string",
11+
"allowedValues": ["cpu", "memory"],
12+
"description": "The type of system resource being measured"
13+
},
814
{
915
"name": "amazonGenerateApproachLatency",
1016
"type": "double",
@@ -387,6 +393,16 @@
387393
}
388394
]
389395
},
396+
{
397+
"name": "ide_childProcessWarning",
398+
"description": "Child Process warning due to high system usage",
399+
"metadata": [
400+
{
401+
"type": "systemResource",
402+
"required": true
403+
}
404+
]
405+
},
390406
{
391407
"name": "vscode_executeCommand",
392408
"description": "Emitted whenever a registered Toolkit command is executed",

packages/core/src/shared/utilities/processUtils.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,19 +106,30 @@ export class ChildProcessTracker {
106106
}
107107
}
108108

109-
private async checkProcessUsage(pid: pid): Promise<void> {
109+
private async checkProcessUsage(pid: number): Promise<void> {
110+
const doesExceedThreshold = (resource: keyof ProcessStats, value: number) => {
111+
const threshold = ChildProcessTracker.thresholds[resource]
112+
return value > threshold
113+
}
114+
const warn = (resource: keyof ProcessStats, value: number) => {
115+
telemetry.ide_childProcessWarning.run((span) => {
116+
this.logger.warn(`Process ${pid} exceeded ${resource} threshold: ${value}`)
117+
span.record({ systemResource: resource })
118+
})
119+
}
120+
110121
if (!this.#pids.has(pid)) {
111122
this.logger.warn(`Missing process with id ${pid}`)
112123
return
113124
}
114125
const stats = await this.getUsage(pid)
115-
if (stats) {
116-
this.logger.debug(`Process ${pid} usage: %O`, stats)
117-
if (stats.memory > ChildProcessTracker.thresholds.memory) {
118-
this.logger.warn(`Process ${pid} exceeded memory threshold: ${stats.memory}`)
119-
}
120-
if (stats.cpu > ChildProcessTracker.thresholds.cpu) {
121-
this.logger.warn(`Process ${pid} exceeded cpu threshold: ${stats.cpu}`)
126+
if (!stats) {
127+
this.logger.warn(`Failed to get process stats for ${pid}`)
128+
return
129+
}
130+
for (const resource of Object.keys(ChildProcessTracker.thresholds) as (keyof ProcessStats)[]) {
131+
if (doesExceedThreshold(resource, stats[resource])) {
132+
warn(resource as keyof ProcessStats, stats[resource])
122133
}
123134
}
124135
}
@@ -162,7 +173,7 @@ export class ChildProcessTracker {
162173
}
163174

164175
public async logAllUsage(): Promise<void> {
165-
telemetry.ide_logActiveProcesses.run(async (span) => {
176+
await telemetry.ide_logActiveProcesses.run(async (span) => {
166177
span.record({ size: this.size })
167178
if (this.size === 0) {
168179
this.logger.info('No Active Subprocesses')

packages/core/src/test/shared/utilities/processUtils.test.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -459,27 +459,36 @@ describe('ChildProcessTracker', function () {
459459
assert.strictEqual(tracker.size, 0, 'expected tracker to be empty')
460460
})
461461

462-
it('logs a warning message when system usage exceeds threshold', async function () {
462+
it('logs a warning message and emits metric when cpu exceeds threshold', async function () {
463463
const runningProcess = startSleepProcess()
464464
tracker.add(runningProcess.childProcess)
465465

466466
const highCpu: ProcessStats = {
467467
cpu: ChildProcessTracker.thresholds.cpu + 1,
468468
memory: 0,
469469
}
470-
const highMemory: ProcessStats = {
471-
cpu: 0,
472-
memory: ChildProcessTracker.thresholds.memory + 1,
473-
}
474470

475471
usageMock.resolves(highCpu)
476472

477473
await clock.tickAsync(ChildProcessTracker.pollingInterval)
478474
assertLogsContain('exceeded cpu threshold', false, 'warn')
475+
assertTelemetry('ide_childProcessWarning', { systemResource: 'cpu' })
476+
477+
await stopAndWait(runningProcess)
478+
})
479+
480+
it('logs a warning message and emits metric when memory exceeds threshold', async function () {
481+
const runningProcess = startSleepProcess()
482+
tracker.add(runningProcess.childProcess)
483+
const highMemory: ProcessStats = {
484+
cpu: 0,
485+
memory: ChildProcessTracker.thresholds.memory + 1,
486+
}
479487

480488
usageMock.resolves(highMemory)
481489
await clock.tickAsync(ChildProcessTracker.pollingInterval)
482490
assertLogsContain('exceeded memory threshold', false, 'warn')
491+
assertTelemetry('ide_childProcessWarning', { systemResource: 'memory' })
483492

484493
await stopAndWait(runningProcess)
485494
})
@@ -510,12 +519,13 @@ describe('ChildProcessTracker', function () {
510519
await clock.tickAsync(ChildProcessTracker.pollingInterval)
511520

512521
assert.throws(() => assertLogsContain(runningProcess.childProcess.pid().toString(), false, 'warn'))
513-
522+
assert.throws(() => assertTelemetry('ide_childProcessWarning', {}))
514523
await stopAndWait(runningProcess)
515524
})
516525
})
517526

518527
it('logAllUsage includes only active processes', async function () {
528+
console.log('start')
519529
const runningProcess1 = startSleepProcess()
520530
const runningProcess2 = startSleepProcess()
521531

@@ -528,9 +538,10 @@ describe('ChildProcessTracker', function () {
528538
await stopAndWait(runningProcess1)
529539

530540
await tracker.logAllUsage()
531-
541+
console.log('logAllUsage called')
532542
assert.throws(() => assertLogsContain(runningProcess1.childProcess.pid().toString(), false, 'info'))
533543
assertLogsContain(runningProcess2.childProcess.pid().toString(), false, 'info')
544+
console.log('end')
534545
})
535546

536547
it('logAllUsage defaults to empty message when empty', async function () {

0 commit comments

Comments
 (0)