From 31d65f40bd9d2c749037e40d87172957ba445f3b Mon Sep 17 00:00:00 2001 From: Yuna Seol Date: Thu, 5 Mar 2026 13:21:55 -0500 Subject: [PATCH] feat(telemetry): implement Clearcut logging for startup statistics (#21172) Co-authored-by: Yuna Seol --- .../clearcut-logger/clearcut-logger.ts | 26 +++++++++++++++++++ .../clearcut-logger/event-metadata-key.ts | 18 ++++++++++++- packages/core/src/telemetry/loggers.ts | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts index 8646a3f6d4..51c5ab382f 100644 --- a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts +++ b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts @@ -49,6 +49,7 @@ import type { ToolOutputMaskingEvent, KeychainAvailabilityEvent, TokenStorageInitializationEvent, + StartupStatsEvent, } from '../types.js'; import { EventMetadataKey } from './event-metadata-key.js'; import type { Config } from '../../config/config.js'; @@ -117,6 +118,7 @@ export enum EventNames { TOKEN_STORAGE_INITIALIZATION = 'token_storage_initialization', CONSECA_POLICY_GENERATION = 'conseca_policy_generation', CONSECA_VERDICT = 'conseca_verdict', + STARTUP_STATS = 'startup_stats', } export interface LogResponse { @@ -1691,6 +1693,30 @@ export class ClearcutLogger { this.flushIfNeeded(); } + logStartupStatsEvent(event: StartupStatsEvent): void { + const data: EventValue[] = [ + { + gemini_cli_key: EventMetadataKey.GEMINI_CLI_STARTUP_PHASES, + value: JSON.stringify(event.phases), + }, + { + gemini_cli_key: EventMetadataKey.GEMINI_CLI_STARTUP_OS_PLATFORM, + value: event.os_platform, + }, + { + gemini_cli_key: EventMetadataKey.GEMINI_CLI_STARTUP_OS_RELEASE, + value: event.os_release, + }, + { + gemini_cli_key: EventMetadataKey.GEMINI_CLI_STARTUP_IS_DOCKER, + value: JSON.stringify(event.is_docker), + }, + ]; + + this.enqueueLogEvent(this.createLogEvent(EventNames.STARTUP_STATS, data)); + this.flushIfNeeded(); + } + /** * Adds default fields to data, and returns a new data array. This fields * should exist on all log events. 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 d799ca1caf..43bfa3278d 100644 --- a/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts +++ b/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts @@ -7,7 +7,7 @@ // Defines valid event metadata keys for Clearcut logging. export enum EventMetadataKey { // Deleted enums: 24 - // Next ID: 172 + // Next ID: 176 GEMINI_CLI_KEY_UNKNOWN = 0, @@ -54,6 +54,22 @@ export enum EventMetadataKey { // Logs the output format of the session. GEMINI_CLI_START_SESSION_OUTPUT_FORMAT = 94, + // ========================================================================== + // Startup Stats Event Keys + // ========================================================================== + + // Logs the array of startup phases. + GEMINI_CLI_STARTUP_PHASES = 172, + + // Logs the OS platform for startup stats. + GEMINI_CLI_STARTUP_OS_PLATFORM = 173, + + // Logs the OS release for startup stats. + GEMINI_CLI_STARTUP_OS_RELEASE = 174, + + // Logs whether the CLI is running in docker for startup stats. + GEMINI_CLI_STARTUP_IS_DOCKER = 175, + // ========================================================================== // User Prompt Event Keys // =========================================================================== diff --git a/packages/core/src/telemetry/loggers.ts b/packages/core/src/telemetry/loggers.ts index 4c3ed55321..393519d3ec 100644 --- a/packages/core/src/telemetry/loggers.ts +++ b/packages/core/src/telemetry/loggers.ts @@ -791,6 +791,7 @@ export function logStartupStats( config: Config, event: StartupStatsEvent, ): void { + ClearcutLogger.getInstance(config)?.logStartupStatsEvent(event); bufferTelemetryEvent(() => { // Wait for experiments to load before emitting so we capture experimentIds void config