Skip to content

Commit 01b822e

Browse files
authored
Merge pull request RooCodeInc#1524 from RooVetGit/checkpoint_telemetry
Add telemetry for checkpoint save/restore/diff
2 parents 0b2abee + 732eedd commit 01b822e

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

src/core/Cline.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3798,6 +3798,8 @@ export class Cline {
37983798
return
37993799
}
38003800

3801+
telemetryService.captureCheckpointDiffed(this.taskId)
3802+
38013803
if (!previousCommitHash && mode === "checkpoint") {
38023804
const previousCheckpoint = this.clineMessages
38033805
.filter(({ say }) => say === "checkpoint_saved")
@@ -3849,6 +3851,8 @@ export class Cline {
38493851
return
38503852
}
38513853

3854+
telemetryService.captureCheckpointCreated(this.taskId)
3855+
38523856
// Start the checkpoint process in the background.
38533857
service.saveCheckpoint(`Task: ${this.taskId}, Time: ${Date.now()}`).catch((err) => {
38543858
console.error("[Cline#checkpointSave] caught unexpected error, disabling checkpoints", err)
@@ -3880,6 +3884,8 @@ export class Cline {
38803884
try {
38813885
await service.restoreCheckpoint(commitHash)
38823886

3887+
telemetryService.captureCheckpointRestored(this.taskId)
3888+
38833889
await this.providerRef.deref()?.postMessageToWebview({ type: "currentCheckpointUpdated", text: commitHash })
38843890

38853891
if (mode === "restore") {

src/core/webview/ClineProvider.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,6 +2567,15 @@ export class ClineProvider implements vscode.WebviewViewProvider {
25672567
properties.apiProvider = apiConfiguration.apiProvider
25682568
}
25692569

2570+
// Add model ID if available
2571+
const currentCline = this.getCurrentCline()
2572+
if (currentCline?.api) {
2573+
const { id: modelId } = currentCline.api.getModel()
2574+
if (modelId) {
2575+
properties.modelId = modelId
2576+
}
2577+
}
2578+
25702579
return properties
25712580
}
25722581
}

src/core/webview/__tests__/ClineProvider.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,3 +1652,62 @@ describe("ContextProxy integration", () => {
16521652
expect(mockContextProxy.setValues).toBeDefined()
16531653
})
16541654
})
1655+
1656+
describe("getTelemetryProperties", () => {
1657+
let provider: ClineProvider
1658+
let mockContext: vscode.ExtensionContext
1659+
let mockOutputChannel: vscode.OutputChannel
1660+
let mockCline: any
1661+
1662+
beforeEach(() => {
1663+
// Reset mocks
1664+
jest.clearAllMocks()
1665+
1666+
// Setup basic mocks
1667+
mockContext = {
1668+
globalState: {
1669+
get: jest.fn().mockImplementation((key: string) => {
1670+
if (key === "mode") return "code"
1671+
if (key === "apiProvider") return "anthropic"
1672+
return undefined
1673+
}),
1674+
update: jest.fn(),
1675+
keys: jest.fn().mockReturnValue([]),
1676+
},
1677+
secrets: { get: jest.fn(), store: jest.fn(), delete: jest.fn() },
1678+
extensionUri: {} as vscode.Uri,
1679+
globalStorageUri: { fsPath: "/test/path" },
1680+
extension: { packageJSON: { version: "1.0.0" } },
1681+
} as unknown as vscode.ExtensionContext
1682+
1683+
mockOutputChannel = { appendLine: jest.fn() } as unknown as vscode.OutputChannel
1684+
provider = new ClineProvider(mockContext, mockOutputChannel)
1685+
1686+
// Setup Cline instance with mocked getModel method
1687+
const { Cline } = require("../../Cline")
1688+
mockCline = new Cline()
1689+
mockCline.api = {
1690+
getModel: jest.fn().mockReturnValue({
1691+
id: "claude-3-7-sonnet-20250219",
1692+
info: { contextWindow: 200000 },
1693+
}),
1694+
}
1695+
})
1696+
1697+
test("includes basic properties in telemetry", async () => {
1698+
const properties = await provider.getTelemetryProperties()
1699+
1700+
expect(properties).toHaveProperty("vscodeVersion")
1701+
expect(properties).toHaveProperty("platform")
1702+
expect(properties).toHaveProperty("appVersion", "1.0.0")
1703+
})
1704+
1705+
test("includes model ID from current Cline instance if available", async () => {
1706+
// Add mock Cline to stack
1707+
await provider.addClineToStack(mockCline)
1708+
1709+
const properties = await provider.getTelemetryProperties()
1710+
1711+
expect(properties).toHaveProperty("modelId", "claude-3-7-sonnet-20250219")
1712+
})
1713+
})

src/services/telemetry/TelemetryService.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ class PostHogClient {
2222
CONVERSATION_MESSAGE: "Conversation Message",
2323
MODE_SWITCH: "Mode Switched",
2424
TOOL_USED: "Tool Used",
25+
CHECKPOINT_CREATED: "Checkpoint Created",
26+
CHECKPOINT_RESTORED: "Checkpoint Restored",
27+
CHECKPOINT_DIFFED: "Checkpoint Diffed",
2528
},
2629
}
2730

@@ -246,6 +249,18 @@ class TelemetryService {
246249
})
247250
}
248251

252+
public captureCheckpointCreated(taskId: string): void {
253+
this.captureEvent(PostHogClient.EVENTS.TASK.CHECKPOINT_CREATED, { taskId })
254+
}
255+
256+
public captureCheckpointDiffed(taskId: string): void {
257+
this.captureEvent(PostHogClient.EVENTS.TASK.CHECKPOINT_DIFFED, { taskId })
258+
}
259+
260+
public captureCheckpointRestored(taskId: string): void {
261+
this.captureEvent(PostHogClient.EVENTS.TASK.CHECKPOINT_RESTORED, { taskId })
262+
}
263+
249264
/**
250265
* Checks if telemetry is currently enabled
251266
* @returns Whether telemetry is enabled

0 commit comments

Comments
 (0)