Skip to content

Commit 5d6bcc4

Browse files
authored
perf(webview): sample memory usage telemetry (#2194)
1 parent 1fd698a commit 5d6bcc4

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

webview-ui/src/services/MemoryService.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// kilocode_change - new file
22
import { telemetryClient } from "../utils/TelemetryClient"
33
import { TelemetryEventName } from "@roo-code/types"
4+
import { createSampledFunction } from "../utils/sampling"
45

56
interface PerformanceMemory {
67
usedJSHeapSize?: number
@@ -9,7 +10,11 @@ interface PerformanceMemory {
910

1011
export class MemoryService {
1112
private intervalId: number | null = null
12-
private readonly intervalMs: number = 60 * 1000 // 1 min
13+
private readonly intervalMs: number = 10 * 60 * 1000 // 10 min(s)
14+
private readonly sampledTelemetryCapture = createSampledFunction(
15+
telemetryClient.capture.bind(telemetryClient),
16+
0.01, // 1% sampling rate
17+
)
1318

1419
public start(): void {
1520
if (this.intervalId) {
@@ -35,7 +40,7 @@ export class MemoryService {
3540
heapUsedMb: this.bytesToMegabytes(memory?.usedJSHeapSize || 0),
3641
heapTotalMb: this.bytesToMegabytes(memory?.totalJSHeapSize || 0),
3742
}
38-
telemetryClient.capture(TelemetryEventName.WEBVIEW_MEMORY_USAGE, memoryInfo)
43+
this.sampledTelemetryCapture(TelemetryEventName.WEBVIEW_MEMORY_USAGE, memoryInfo)
3944
}
4045

4146
private bytesToMegabytes(bytes: number): number {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { createSampledFunction } from "../sampling"
2+
import { vi } from "vitest"
3+
4+
describe("createSampledFunction", () => {
5+
beforeEach(() => {
6+
vi.restoreAllMocks()
7+
})
8+
9+
it("should call the wrapped function when random value is less than sample rate", () => {
10+
vi.spyOn(Math, "random").mockReturnValue(0.005) // 0.5%
11+
const mockFn = vi.fn()
12+
const sampledFn = createSampledFunction(mockFn, 0.01) // 1%
13+
14+
sampledFn("test", 123)
15+
16+
expect(mockFn).toHaveBeenCalledWith("test", 123)
17+
})
18+
19+
it("should not call the wrapped function when random value is greater than sample rate", () => {
20+
vi.spyOn(Math, "random").mockReturnValue(0.015) // 1.5%
21+
const mockFn = vi.fn()
22+
const sampledFn = createSampledFunction(mockFn, 0.01) // 1%
23+
24+
sampledFn("test", 123)
25+
26+
expect(mockFn).not.toHaveBeenCalled()
27+
})
28+
})

webview-ui/src/utils/sampling.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Creates a sampled version of a function that only executes based on the provided sample rate.
3+
*
4+
* @param fn - The function to wrap with sampling
5+
* @param sampleRate - The sampling rate as a decimal (e.g., 0.01 for 1%, 0.1 for 10%)
6+
* @returns A new function that only executes the original function based on the sample rate
7+
*/
8+
export function createSampledFunction<T extends (...args: any[]) => any>(fn: T, sampleRate: number): T {
9+
const clampedRate = Math.max(0, Math.min(1, sampleRate))
10+
11+
return ((...args: Parameters<T>) => {
12+
if (Math.random() < clampedRate) {
13+
return fn(...args)
14+
}
15+
}) as T
16+
}

0 commit comments

Comments
 (0)