summaryrefslogtreecommitdiff
path: root/packages/core/src/telemetry
diff options
context:
space:
mode:
authorShreya Keshive <[email protected]>2025-08-05 18:52:58 -0400
committerGitHub <[email protected]>2025-08-05 22:52:58 +0000
commit268627469b384ba3fa8dfe2e05b5186248013070 (patch)
tree27d6421c6d7cc7986d284fa8f7bf0fece9c607e3 /packages/core/src/telemetry
parent6a72cd064bccb5fda4618671c2da63c4e22c1ef9 (diff)
Refactor IDE client state management, improve user-facing error messages, and add logging of connection events (#5591)
Co-authored-by: matt korwel <[email protected]>
Diffstat (limited to 'packages/core/src/telemetry')
-rw-r--r--packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts14
-rw-r--r--packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts7
-rw-r--r--packages/core/src/telemetry/constants.ts1
-rw-r--r--packages/core/src/telemetry/loggers.ts23
-rw-r--r--packages/core/src/telemetry/telemetry.test.ts2
-rw-r--r--packages/core/src/telemetry/types.ts20
6 files changed, 64 insertions, 3 deletions
diff --git a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
index 6b85a664..649d82b6 100644
--- a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
+++ b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
@@ -21,6 +21,7 @@ import {
NextSpeakerCheckEvent,
SlashCommandEvent,
MalformedJsonResponseEvent,
+ IdeConnectionEvent,
} from '../types.js';
import { EventMetadataKey } from './event-metadata-key.js';
import { Config } from '../../config/config.js';
@@ -44,6 +45,7 @@ const loop_detected_event_name = 'loop_detected';
const next_speaker_check_event_name = 'next_speaker_check';
const slash_command_event_name = 'slash_command';
const malformed_json_response_event_name = 'malformed_json_response';
+const ide_connection_event_name = 'ide_connection';
export interface LogResponse {
nextRequestWaitMs?: number;
@@ -578,6 +580,18 @@ export class ClearcutLogger {
this.flushIfNeeded();
}
+ logIdeConnectionEvent(event: IdeConnectionEvent): void {
+ const data = [
+ {
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_IDE_CONNECTION_TYPE,
+ value: JSON.stringify(event.connection_type),
+ },
+ ];
+
+ this.enqueueLogEvent(this.createLogEvent(ide_connection_event_name, data));
+ this.flushIfNeeded();
+ }
+
logEndSessionEvent(event: EndSessionEvent): void {
const data = [
{
diff --git a/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts b/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
index 0fc35894..54f570f1 100644
--- a/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
+++ b/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
@@ -190,6 +190,13 @@ export enum EventMetadataKey {
// Logs the model that produced the malformed JSON response.
GEMINI_CLI_MALFORMED_JSON_RESPONSE_MODEL = 45,
+
+ // ==========================================================================
+ // IDE Connection Event Keys
+ // ===========================================================================
+
+ // Logs the type of the IDE connection.
+ GEMINI_CLI_IDE_CONNECTION_TYPE = 46,
}
export function getEventMetadataKey(
diff --git a/packages/core/src/telemetry/constants.ts b/packages/core/src/telemetry/constants.ts
index 7dd5c8d1..7d840815 100644
--- a/packages/core/src/telemetry/constants.ts
+++ b/packages/core/src/telemetry/constants.ts
@@ -15,6 +15,7 @@ export const EVENT_CLI_CONFIG = 'gemini_cli.config';
export const EVENT_FLASH_FALLBACK = 'gemini_cli.flash_fallback';
export const EVENT_NEXT_SPEAKER_CHECK = 'gemini_cli.next_speaker_check';
export const EVENT_SLASH_COMMAND = 'gemini_cli.slash_command';
+export const EVENT_IDE_CONNECTION = 'gemini_cli.ide_connection';
export const METRIC_TOOL_CALL_COUNT = 'gemini_cli.tool.call.count';
export const METRIC_TOOL_CALL_LATENCY = 'gemini_cli.tool.call.latency';
diff --git a/packages/core/src/telemetry/loggers.ts b/packages/core/src/telemetry/loggers.ts
index 2aa0d86a..e3726ccb 100644
--- a/packages/core/src/telemetry/loggers.ts
+++ b/packages/core/src/telemetry/loggers.ts
@@ -12,6 +12,7 @@ import {
EVENT_API_REQUEST,
EVENT_API_RESPONSE,
EVENT_CLI_CONFIG,
+ EVENT_IDE_CONNECTION,
EVENT_TOOL_CALL,
EVENT_USER_PROMPT,
EVENT_FLASH_FALLBACK,
@@ -23,6 +24,7 @@ import {
ApiErrorEvent,
ApiRequestEvent,
ApiResponseEvent,
+ IdeConnectionEvent,
StartSessionEvent,
ToolCallEvent,
UserPromptEvent,
@@ -355,3 +357,24 @@ export function logSlashCommand(
};
logger.emit(logRecord);
}
+
+export function logIdeConnection(
+ config: Config,
+ event: IdeConnectionEvent,
+): void {
+ ClearcutLogger.getInstance(config)?.logIdeConnectionEvent(event);
+ if (!isTelemetrySdkInitialized()) return;
+
+ const attributes: LogAttributes = {
+ ...getCommonAttributes(config),
+ ...event,
+ 'event.name': EVENT_IDE_CONNECTION,
+ };
+
+ const logger = logs.getLogger(SERVICE_NAME);
+ const logRecord: LogRecord = {
+ body: `Ide connection. Type: ${event.connection_type}.`,
+ attributes,
+ };
+ logger.emit(logRecord);
+}
diff --git a/packages/core/src/telemetry/telemetry.test.ts b/packages/core/src/telemetry/telemetry.test.ts
index 8ebb3d9a..9734e382 100644
--- a/packages/core/src/telemetry/telemetry.test.ts
+++ b/packages/core/src/telemetry/telemetry.test.ts
@@ -12,7 +12,6 @@ import {
} from './sdk.js';
import { Config } from '../config/config.js';
import { NodeSDK } from '@opentelemetry/sdk-node';
-import { IdeClient } from '../ide/ide-client.js';
vi.mock('@opentelemetry/sdk-node');
vi.mock('../config/config.js');
@@ -30,7 +29,6 @@ describe('telemetry', () => {
targetDir: '/test/dir',
debugMode: false,
cwd: '/test/dir',
- ideClient: IdeClient.getInstance(false),
});
vi.spyOn(mockConfig, 'getTelemetryEnabled').mockReturnValue(true);
vi.spyOn(mockConfig, 'getTelemetryOtlpEndpoint').mockReturnValue(
diff --git a/packages/core/src/telemetry/types.ts b/packages/core/src/telemetry/types.ts
index 9d1fd77a..668421f0 100644
--- a/packages/core/src/telemetry/types.ts
+++ b/packages/core/src/telemetry/types.ts
@@ -308,6 +308,23 @@ export class MalformedJsonResponseEvent {
}
}
+export enum IdeConnectionType {
+ START = 'start',
+ SESSION = 'session',
+}
+
+export class IdeConnectionEvent {
+ 'event.name': 'ide_connection';
+ 'event.timestamp': string; // ISO 8601
+ connection_type: IdeConnectionType;
+
+ constructor(connection_type: IdeConnectionType) {
+ this['event.name'] = 'ide_connection';
+ this['event.timestamp'] = new Date().toISOString();
+ this.connection_type = connection_type;
+ }
+}
+
export type TelemetryEvent =
| StartSessionEvent
| EndSessionEvent
@@ -320,4 +337,5 @@ export type TelemetryEvent =
| LoopDetectedEvent
| NextSpeakerCheckEvent
| SlashCommandEvent
- | MalformedJsonResponseEvent;
+ | MalformedJsonResponseEvent
+ | IdeConnectionEvent;