mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
Add telemetry to rewind (#18122)
This commit is contained in:
@@ -41,6 +41,8 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|||||||
...actual.coreEvents,
|
...actual.coreEvents,
|
||||||
emitFeedback: vi.fn(),
|
emitFeedback: vi.fn(),
|
||||||
},
|
},
|
||||||
|
logRewind: vi.fn(),
|
||||||
|
RewindEvent: class {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import {
|
|||||||
checkExhaustive,
|
checkExhaustive,
|
||||||
coreEvents,
|
coreEvents,
|
||||||
debugLogger,
|
debugLogger,
|
||||||
|
logRewind,
|
||||||
|
RewindEvent,
|
||||||
type ChatRecordingService,
|
type ChatRecordingService,
|
||||||
type GeminiClient,
|
type GeminiClient,
|
||||||
} from '@google/gemini-cli-core';
|
} from '@google/gemini-cli-core';
|
||||||
@@ -144,6 +146,9 @@ export const rewindCommand: SlashCommand = {
|
|||||||
context.ui.removeComponent();
|
context.ui.removeComponent();
|
||||||
}}
|
}}
|
||||||
onRewind={async (messageId, newText, outcome) => {
|
onRewind={async (messageId, newText, outcome) => {
|
||||||
|
if (outcome !== RewindOutcome.Cancel) {
|
||||||
|
logRewind(config, new RewindEvent(outcome));
|
||||||
|
}
|
||||||
switch (outcome) {
|
switch (outcome) {
|
||||||
case RewindOutcome.Cancel:
|
case RewindOutcome.Cancel:
|
||||||
context.ui.removeComponent();
|
context.ui.removeComponent();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import type {
|
|||||||
LoopDetectedEvent,
|
LoopDetectedEvent,
|
||||||
NextSpeakerCheckEvent,
|
NextSpeakerCheckEvent,
|
||||||
SlashCommandEvent,
|
SlashCommandEvent,
|
||||||
|
RewindEvent,
|
||||||
MalformedJsonResponseEvent,
|
MalformedJsonResponseEvent,
|
||||||
IdeConnectionEvent,
|
IdeConnectionEvent,
|
||||||
ConversationFinishedEvent,
|
ConversationFinishedEvent,
|
||||||
@@ -78,6 +79,7 @@ export enum EventNames {
|
|||||||
LOOP_DETECTION_DISABLED = 'loop_detection_disabled',
|
LOOP_DETECTION_DISABLED = 'loop_detection_disabled',
|
||||||
NEXT_SPEAKER_CHECK = 'next_speaker_check',
|
NEXT_SPEAKER_CHECK = 'next_speaker_check',
|
||||||
SLASH_COMMAND = 'slash_command',
|
SLASH_COMMAND = 'slash_command',
|
||||||
|
REWIND = 'rewind',
|
||||||
MALFORMED_JSON_RESPONSE = 'malformed_json_response',
|
MALFORMED_JSON_RESPONSE = 'malformed_json_response',
|
||||||
IDE_CONNECTION = 'ide_connection',
|
IDE_CONNECTION = 'ide_connection',
|
||||||
KITTY_SEQUENCE_OVERFLOW = 'kitty_sequence_overflow',
|
KITTY_SEQUENCE_OVERFLOW = 'kitty_sequence_overflow',
|
||||||
@@ -945,6 +947,18 @@ export class ClearcutLogger {
|
|||||||
this.flushIfNeeded();
|
this.flushIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logRewindEvent(event: RewindEvent): void {
|
||||||
|
const data: EventValue[] = [
|
||||||
|
{
|
||||||
|
gemini_cli_key: EventMetadataKey.GEMINI_CLI_REWIND_OUTCOME,
|
||||||
|
value: event.outcome,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
this.enqueueLogEvent(this.createLogEvent(EventNames.REWIND, data));
|
||||||
|
this.flushIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
logMalformedJsonResponseEvent(event: MalformedJsonResponseEvent): void {
|
logMalformedJsonResponseEvent(event: MalformedJsonResponseEvent): void {
|
||||||
const data: EventValue[] = [
|
const data: EventValue[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -544,6 +544,12 @@ export enum EventMetadataKey {
|
|||||||
GEMINI_CLI_APPROVAL_MODE_DURATION_MS = 143,
|
GEMINI_CLI_APPROVAL_MODE_DURATION_MS = 143,
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
// Rewind Event Keys
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
// Logs the outcome of a rewind operation.
|
||||||
|
GEMINI_CLI_REWIND_OUTCOME = 144,
|
||||||
|
|
||||||
// Model Routing Event Keys (Cont.)
|
// Model Routing Event Keys (Cont.)
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export {
|
|||||||
logExtensionUninstall,
|
logExtensionUninstall,
|
||||||
logExtensionUpdateEvent,
|
logExtensionUpdateEvent,
|
||||||
logWebFetchFallbackAttempt,
|
logWebFetchFallbackAttempt,
|
||||||
|
logRewind,
|
||||||
} from './loggers.js';
|
} from './loggers.js';
|
||||||
export type { SlashCommandEvent, ChatCompressionEvent } from './types.js';
|
export type { SlashCommandEvent, ChatCompressionEvent } from './types.js';
|
||||||
export {
|
export {
|
||||||
@@ -62,6 +63,7 @@ export {
|
|||||||
ToolOutputTruncatedEvent,
|
ToolOutputTruncatedEvent,
|
||||||
WebFetchFallbackAttemptEvent,
|
WebFetchFallbackAttemptEvent,
|
||||||
ToolCallDecision,
|
ToolCallDecision,
|
||||||
|
RewindEvent,
|
||||||
} from './types.js';
|
} from './types.js';
|
||||||
export { makeSlashCommandEvent, makeChatCompressionEvent } from './types.js';
|
export { makeSlashCommandEvent, makeChatCompressionEvent } from './types.js';
|
||||||
export type { TelemetryEvent } from './types.js';
|
export type { TelemetryEvent } from './types.js';
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
EVENT_API_ERROR,
|
EVENT_API_ERROR,
|
||||||
EVENT_API_RESPONSE,
|
EVENT_API_RESPONSE,
|
||||||
EVENT_TOOL_CALL,
|
EVENT_TOOL_CALL,
|
||||||
|
EVENT_REWIND,
|
||||||
} from './types.js';
|
} from './types.js';
|
||||||
import type {
|
import type {
|
||||||
ApiErrorEvent,
|
ApiErrorEvent,
|
||||||
@@ -27,6 +28,7 @@ import type {
|
|||||||
LoopDetectedEvent,
|
LoopDetectedEvent,
|
||||||
LoopDetectionDisabledEvent,
|
LoopDetectionDisabledEvent,
|
||||||
SlashCommandEvent,
|
SlashCommandEvent,
|
||||||
|
RewindEvent,
|
||||||
ConversationFinishedEvent,
|
ConversationFinishedEvent,
|
||||||
ChatCompressionEvent,
|
ChatCompressionEvent,
|
||||||
MalformedJsonResponseEvent,
|
MalformedJsonResponseEvent,
|
||||||
@@ -351,6 +353,24 @@ export function logSlashCommand(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function logRewind(config: Config, event: RewindEvent): void {
|
||||||
|
const uiEvent = {
|
||||||
|
...event,
|
||||||
|
'event.name': EVENT_REWIND,
|
||||||
|
'event.timestamp': new Date().toISOString(),
|
||||||
|
} as UiEvent;
|
||||||
|
uiTelemetryService.addEvent(uiEvent);
|
||||||
|
ClearcutLogger.getInstance(config)?.logRewindEvent(event);
|
||||||
|
bufferTelemetryEvent(() => {
|
||||||
|
const logger = logs.getLogger(SERVICE_NAME);
|
||||||
|
const logRecord: LogRecord = {
|
||||||
|
body: event.toLogBody(),
|
||||||
|
attributes: event.toOpenTelemetryAttributes(config),
|
||||||
|
};
|
||||||
|
logger.emit(logRecord);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function logIdeConnection(
|
export function logIdeConnection(
|
||||||
config: Config,
|
config: Config,
|
||||||
event: IdeConnectionEvent,
|
event: IdeConnectionEvent,
|
||||||
|
|||||||
@@ -889,6 +889,32 @@ export enum SlashCommandStatus {
|
|||||||
ERROR = 'error',
|
ERROR = 'error',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const EVENT_REWIND = 'gemini_cli.rewind';
|
||||||
|
export class RewindEvent implements BaseTelemetryEvent {
|
||||||
|
'event.name': 'rewind';
|
||||||
|
'event.timestamp': string;
|
||||||
|
outcome: string;
|
||||||
|
|
||||||
|
constructor(outcome: string) {
|
||||||
|
this['event.name'] = 'rewind';
|
||||||
|
this['event.timestamp'] = new Date().toISOString();
|
||||||
|
this.outcome = outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
toOpenTelemetryAttributes(config: Config): LogAttributes {
|
||||||
|
return {
|
||||||
|
...getCommonAttributes(config),
|
||||||
|
'event.name': EVENT_REWIND,
|
||||||
|
'event.timestamp': this['event.timestamp'],
|
||||||
|
outcome: this.outcome,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toLogBody(): string {
|
||||||
|
return `Rewind performed. Outcome: ${this.outcome}.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const EVENT_CHAT_COMPRESSION = 'gemini_cli.chat_compression';
|
export const EVENT_CHAT_COMPRESSION = 'gemini_cli.chat_compression';
|
||||||
export interface ChatCompressionEvent extends BaseTelemetryEvent {
|
export interface ChatCompressionEvent extends BaseTelemetryEvent {
|
||||||
'event.name': 'chat_compression';
|
'event.name': 'chat_compression';
|
||||||
@@ -1577,6 +1603,7 @@ export type TelemetryEvent =
|
|||||||
| StartupStatsEvent
|
| StartupStatsEvent
|
||||||
| WebFetchFallbackAttemptEvent
|
| WebFetchFallbackAttemptEvent
|
||||||
| EditStrategyEvent
|
| EditStrategyEvent
|
||||||
|
| RewindEvent
|
||||||
| EditCorrectionEvent;
|
| EditCorrectionEvent;
|
||||||
|
|
||||||
export const EVENT_EXTENSION_DISABLE = 'gemini_cli.extension_disable';
|
export const EVENT_EXTENSION_DISABLE = 'gemini_cli.extension_disable';
|
||||||
|
|||||||
Reference in New Issue
Block a user