Compare commits

...
Author SHA1 Message Date
Dennis Bartlett e651a581e8 Create gold-beans-compare.md 2025-03-27 21:34:31 -07:00
Dennis Bartlett 58287c08c2 Revert "re-enabling conversation observability (#2448)"
This reverts commit af17d6239d.
2025-03-27 21:33:05 -07:00
6 changed files with 46 additions and 37 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": patch
---
Revert "re-enabling conversation observability"
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "claude-dev",
"version": "3.8.2",
"version": "3.8.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "claude-dev",
"version": "3.8.2",
"version": "3.8.0",
"license": "Apache-2.0",
"dependencies": {
"@anthropic-ai/bedrock-sdk": "^0.12.4",
-5
View File
@@ -261,11 +261,6 @@
"type": "boolean",
"default": true,
"description": "Controls whether the MCP Marketplace is enabled."
},
"cline.conversationObservability": {
"type": "boolean",
"default": false,
"markdownDescription": "Share message data, code, and more extensive observability. This data may be used to improve prompts used in Cline, train models, and understand failure states more accurately. [Learn more](https://docs.cline.bot/more-info/conversation-observability)"
}
}
}
+10 -10
View File
@@ -64,7 +64,7 @@ import { ClineHandler } from "../api/providers/cline"
import { ClineProvider } from "./webview/ClineProvider"
import { DEFAULT_LANGUAGE_SETTINGS, getLanguageKey, LanguageDisplay, LanguageKey } from "../shared/Languages"
import { telemetryService } from "../services/telemetry/TelemetryService"
import { ConversationObservabilityService, TelemetryChatMessage } from "../services/telemetry/ConversationObservabilityService"
import { ConversationTelemetryService, TelemetryChatMessage } from "../services/telemetry/ConversationTelemetryService"
import pTimeout from "p-timeout"
import { GlobalFileNames } from "../global-constants"
import {
@@ -1357,7 +1357,7 @@ export class Cline {
// Capture system prompt for telemetry,
// ONLY if user is opted in, in advanced settings
if (this.providerRef.deref()?.conversationObservabilityService.isOptedInToConversationObservability()) {
if (this.providerRef.deref()?.conversationTelemetryService.isOptedInToConversationTelemetry()) {
const systemMessage: TelemetryChatMessage = {
role: "system",
content: systemPrompt,
@@ -1365,7 +1365,7 @@ export class Cline {
}
// no need for timeout here, as there's no timestamp to compare to
this.providerRef.deref()?.conversationObservabilityService.captureMessage(this.taskId, systemMessage, {
this.providerRef.deref()?.conversationTelemetryService.captureMessage(this.taskId, systemMessage, {
apiProvider: this.apiProvider,
model: this.api.getModel().id,
tokensIn: 0,
@@ -3192,7 +3192,7 @@ export class Cline {
// Capture message data for telemetry,
// ONLY if user is opted in, in advanced settings
if (this.providerRef.deref()?.conversationObservabilityService.isOptedInToConversationObservability()) {
if (this.providerRef.deref()?.conversationTelemetryService.isOptedInToConversationTelemetry()) {
// Get the last message from apiConversationHistory
const lastMessage = this.apiConversationHistory[this.apiConversationHistory.length - 1]
@@ -3203,7 +3203,7 @@ export class Cline {
const ts = lastClineMessage.ts
// Send individual message to telemetry
this.providerRef.deref()?.conversationObservabilityService.captureMessage(
this.providerRef.deref()?.conversationTelemetryService.captureMessage(
this.taskId,
// Add the timestamp to the message object for telemetry
{
@@ -3220,7 +3220,7 @@ export class Cline {
// Send entire conversation history to cleanup endpoint
// This ensures deleted messages are properly handled in telemetry
this.providerRef.deref()?.conversationObservabilityService.cleanupTask(this.taskId, this.clineMessages)
this.providerRef.deref()?.conversationTelemetryService.cleanupTask(this.taskId, this.clineMessages)
}
// since we sent off a placeholder api_req_started message to update the webview while waiting to actually start the API request (to load potential details for example), we need to update the text of that message
@@ -3302,7 +3302,7 @@ export class Cline {
// Capture message data for telemetry after assistant response
// ONLY if user is opted in, in advanced settings
if (this.providerRef.deref()?.conversationObservabilityService.isOptedInToConversationObservability()) {
if (this.providerRef.deref()?.conversationTelemetryService.isOptedInToConversationTelemetry()) {
// Get the last message from apiConversationHistory
const lastMessage = this.apiConversationHistory[this.apiConversationHistory.length - 1]
@@ -3314,7 +3314,7 @@ export class Cline {
if (!lastTextMessage) {
console.error("No text message found in clineMessages")
} else {
this.providerRef.deref()?.conversationObservabilityService.captureMessage(
this.providerRef.deref()?.conversationTelemetryService.captureMessage(
this.taskId,
{
...lastMessage,
@@ -3481,7 +3481,7 @@ export class Cline {
// Capture message data for telemetry after assistant response,
// ONLY if user is opted in, in advanced settings
if (this.providerRef.deref()?.conversationObservabilityService.isOptedInToConversationObservability()) {
if (this.providerRef.deref()?.conversationTelemetryService.isOptedInToConversationTelemetry()) {
// Get the last message from apiConversationHistory
const lastMessage = this.apiConversationHistory[this.apiConversationHistory.length - 1]
@@ -3489,7 +3489,7 @@ export class Cline {
const lastClineMessage = this.clineMessages[this.clineMessages.length - 1]
if (lastClineMessage) {
this.providerRef.deref()?.conversationObservabilityService.captureMessage(
this.providerRef.deref()?.conversationTelemetryService.captureMessage(
this.taskId,
{
...lastMessage,
+4 -4
View File
@@ -38,7 +38,7 @@ import { TelemetrySetting } from "../../shared/TelemetrySetting"
import { cleanupLegacyCheckpoints } from "../../integrations/checkpoints/CheckpointMigration"
import CheckpointTracker from "../../integrations/checkpoints/CheckpointTracker"
import { getTotalTasksSize } from "../../utils/storage"
import { ConversationObservabilityService } from "../../services/telemetry/ConversationObservabilityService"
import { ConversationTelemetryService } from "../../services/telemetry/ConversationTelemetryService"
import { GlobalFileNames } from "../../global-constants"
import { setTimeout as setTimeoutPromise } from "node:timers/promises"
@@ -127,7 +127,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
mcpHub?: McpHub
accountService?: ClineAccountService
private latestAnnouncementId = "march-22-2025" // update to some unique identifier when we add a new announcement
conversationObservabilityService: ConversationObservabilityService
conversationTelemetryService: ConversationTelemetryService
constructor(
readonly context: vscode.ExtensionContext,
@@ -138,7 +138,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
this.workspaceTracker = new WorkspaceTracker(this)
this.mcpHub = new McpHub(this)
this.accountService = new ClineAccountService(this)
this.conversationObservabilityService = new ConversationObservabilityService(this)
this.conversationTelemetryService = new ConversationTelemetryService(this)
// Clean up legacy checkpoints
cleanupLegacyCheckpoints(this.context.globalStorageUri.fsPath, this.outputChannel).catch((error) => {
@@ -170,7 +170,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
this.mcpHub?.dispose()
this.mcpHub = undefined
this.accountService = undefined
this.conversationObservabilityService.shutdown()
this.conversationTelemetryService.shutdown()
this.outputChannel.appendLine("Disposed all disposables")
ClineProvider.activeInstances.delete(this)
}
@@ -21,19 +21,21 @@ interface ConversationMetadata {
tokensOut: number
}
const { IS_DEV } = process.env
/**
Cline Telemetry (currently only available in DEV builds)
Advanced Setting to opt-in to LLM observability, allowing you to share message data, code, and more extensive telemetry to help improve prompts used in Cline, train our models, and understand failure states more accurately.
"cline.conversationObservability": {
"cline.conversationTelemetry": {
"type": "boolean",
"default": false,
"markdownDescription": "Share message data, code, and more extensive telemetry. This data may be used to improve prompts used in Cline, train models, and understand failure states more accurately. [Learn more](https://docs.cline.bot/more-info/llm-observability)"
}
*/
export class ConversationObservabilityService {
export class ConversationTelemetryService {
private providerRef: WeakRef<ClineProvider>
private distinctId: string = vscode.env.machineId
private apiEndpoint: string = "https://api.cline.bot/v1/traces"
@@ -54,12 +56,19 @@ export class ConversationObservabilityService {
return apiConfiguration?.clineApiKey
}
public isOptedInToConversationObservability(): boolean {
// User has to manually opt in to conversation telemetry in Advanced Settings
const isConversationObservabilityEnabled =
vscode.workspace.getConfiguration("cline").get<boolean>("conversationObservability") ?? false
public isOptedInToConversationTelemetry(): boolean {
// First check global telemetry level - telemetry should only be enabled when level is "all"
const telemetryLevel = vscode.workspace.getConfiguration("telemetry").get<string>("telemetryLevel", "all")
const isGlobalTelemetryEnabled = telemetryLevel === "all"
return isConversationObservabilityEnabled
// User has to manually opt in to conversation telemetry in Advanced Settings
const isConversationTelemetryEnabled =
vscode.workspace.getConfiguration("cline").get<boolean>("conversationTelemetry") ?? false
// Currently only enabled in dev environment
const isDevEnvironment = !!IS_DEV
return isDevEnvironment && isGlobalTelemetryEnabled && isConversationTelemetryEnabled
}
private async initializeTracer() {
@@ -72,7 +81,7 @@ export class ConversationObservabilityService {
const clineApiKey = await this.getClineApiKey()
console.info("[ConversationObservability] Initializing OpenTelemetry tracer...")
console.log("[ConversationTelemetry] Initializing OpenTelemetry tracer...")
// Configure the OTLP exporter
const headers: Record<string, string> = {
@@ -104,9 +113,9 @@ export class ConversationObservabilityService {
// Get a tracer
this.tracer = trace.getTracer("cline-conversation-tracer")
console.info("[ConversationObservability] OpenTelemetry tracer initialized successfully")
console.log("[ConversationTelemetry] OpenTelemetry tracer initialized successfully")
} catch (error) {
console.error("[ConversationObservability] Failed to initialize OpenTelemetry tracer:", error)
console.error("[ConversationTelemetry] Failed to initialize OpenTelemetry tracer:", error)
}
}
@@ -116,7 +125,7 @@ export class ConversationObservabilityService {
*/
public async captureMessage(taskId: string, message: TelemetryChatMessage, metadata: ConversationMetadata) {
// Do NOT capture message if user has not explicitly opted in
if (!this.isOptedInToConversationObservability()) {
if (!this.isOptedInToConversationTelemetry()) {
return
}
@@ -186,9 +195,9 @@ export class ConversationObservabilityService {
// End the span immediately since messages are discrete events
span.end(this.millisecondsToHrTime(timestamp)) // Convert to nanoseconds
console.info(`[ConversationObservability] Captured ${message.role} message for task ${taskId}`, { span })
console.log(`[ConversationTelemetry] Captured ${message.role} message for task ${taskId}`, { span })
} catch (error) {
console.error("[ConversationObservability] Error capturing message:", error)
console.error("[ConversationTelemetry] Error capturing message:", error)
}
}
@@ -250,7 +259,7 @@ export class ConversationObservabilityService {
*/
public async cleanupTask(taskId: string, conversationData: any): Promise<void> {
// Do NOT send data if user has not explicitly opted in
if (!this.isOptedInToConversationObservability()) {
if (!this.isOptedInToConversationTelemetry()) {
return
}
@@ -286,9 +295,9 @@ export class ConversationObservabilityService {
throw new Error(`Failed to send cleanup data: ${response.status} ${response.statusText}`)
}
console.info(`[ConversationObservability] Cleanup data sent for task ${taskId}`)
console.log(`[ConversationTelemetry] Cleanup data sent for task ${taskId}`)
} catch (error) {
console.error("[ConversationObservability] Error sending cleanup data:", error)
console.error("[ConversationTelemetry] Error sending cleanup data:", error)
}
}