Log Model Slash Commands (#9250)

This commit is contained in:
Victor May
2025-09-23 18:06:03 -04:00
committed by GitHub
parent 28c3901513
commit 4bd4cd697b
8 changed files with 128 additions and 31 deletions

View File

@@ -29,6 +29,7 @@ import type {
ExtensionUninstallEvent,
ModelRoutingEvent,
ExtensionEnableEvent,
ModelSlashCommandEvent,
ExtensionDisableEvent,
} from '../types.js';
import { EventMetadataKey } from './event-metadata-key.js';
@@ -69,6 +70,7 @@ export enum EventNames {
EXTENSION_UNINSTALL = 'extension_uninstall',
TOOL_OUTPUT_TRUNCATED = 'tool_output_truncated',
MODEL_ROUTING = 'model_routing',
MODEL_SLASH_COMMAND = 'model_slash_command',
}
export interface LogResponse {
@@ -994,6 +996,20 @@ export class ClearcutLogger {
this.flushIfNeeded();
}
logModelSlashCommandEvent(event: ModelSlashCommandEvent): void {
const data: EventValue[] = [
{
gemini_cli_key: EventMetadataKey.GEMINI_CLI_MODEL_SLASH_COMMAND,
value: event.model_name,
},
];
this.enqueueLogEvent(
this.createLogEvent(EventNames.MODEL_SLASH_COMMAND, data),
);
this.flushIfNeeded();
}
logExtensionDisableEvent(event: ExtensionDisableEvent): void {
const data: EventValue[] = [
{

View File

@@ -401,4 +401,7 @@ export enum EventMetadataKey {
// Logs the source of the decision.
GEMINI_CLI_ROUTING_DECISION_SOURCE = 101,
// Logs an event when the user uses the /model command.
GEMINI_CLI_MODEL_SLASH_COMMAND = 103,
}

View File

@@ -30,6 +30,7 @@ export const EVENT_CONTENT_RETRY = 'gemini_cli.chat.content_retry';
export const EVENT_CONTENT_RETRY_FAILURE =
'gemini_cli.chat.content_retry_failure';
export const EVENT_FILE_OPERATION = 'gemini_cli.file_operation';
export const EVENT_MODEL_SLASH_COMMAND = 'gemini_cli.slash_command.model';
export const METRIC_TOOL_CALL_COUNT = 'gemini_cli.tool.call.count';
export const METRIC_TOOL_CALL_LATENCY = 'gemini_cli.tool.call.latency';
export const METRIC_API_REQUEST_COUNT = 'gemini_cli.api.request.count';
@@ -45,3 +46,5 @@ export const EVENT_MODEL_ROUTING = 'gemini_cli.model_routing';
export const METRIC_MODEL_ROUTING_LATENCY = 'gemini_cli.model_routing.latency';
export const METRIC_MODEL_ROUTING_FAILURE_COUNT =
'gemini_cli.model_routing.failure.count';
export const METRIC_MODEL_SLASH_COMMAND_CALL_COUNT =
'gemini_cli.slash_command.model.call_count';

View File

@@ -32,6 +32,7 @@ import {
EVENT_RIPGREP_FALLBACK,
EVENT_MODEL_ROUTING,
EVENT_EXTENSION_INSTALL,
EVENT_MODEL_SLASH_COMMAND,
EVENT_EXTENSION_DISABLE,
} from './constants.js';
import type {
@@ -62,6 +63,7 @@ import type {
ExtensionEnableEvent,
ExtensionUninstallEvent,
ExtensionInstallEvent,
ModelSlashCommandEvent,
} from './types.js';
import {
recordApiErrorMetrics,
@@ -74,6 +76,7 @@ import {
recordContentRetry,
recordContentRetryFailure,
recordModelRoutingMetrics,
recordModelSlashCommand,
} from './metrics.js';
import { isTelemetrySdkInitialized } from './sdk.js';
import type { UiEvent } from './uiTelemetry.js';
@@ -700,6 +703,28 @@ export function logModelRouting(
recordModelRoutingMetrics(config, event);
}
export function logModelSlashCommand(
config: Config,
event: ModelSlashCommandEvent,
): void {
ClearcutLogger.getInstance(config)?.logModelSlashCommandEvent(event);
if (!isTelemetrySdkInitialized()) return;
const attributes: LogAttributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_MODEL_SLASH_COMMAND,
};
const logger = logs.getLogger(SERVICE_NAME);
const logRecord: LogRecord = {
body: `Model slash command. Model: ${event.model_name}`,
attributes,
};
logger.emit(logRecord);
recordModelSlashCommand(config, event);
}
export function logExtensionInstallEvent(
config: Config,
event: ExtensionInstallEvent,

View File

@@ -21,9 +21,10 @@ import {
METRIC_CONTENT_RETRY_FAILURE_COUNT,
METRIC_MODEL_ROUTING_LATENCY,
METRIC_MODEL_ROUTING_FAILURE_COUNT,
METRIC_MODEL_SLASH_COMMAND_CALL_COUNT,
} from './constants.js';
import type { Config } from '../config/config.js';
import type { ModelRoutingEvent } from './types.js';
import type { ModelRoutingEvent, ModelSlashCommandEvent } from './types.js';
export enum FileOperation {
CREATE = 'create',
@@ -44,6 +45,7 @@ let contentRetryCounter: Counter | undefined;
let contentRetryFailureCounter: Counter | undefined;
let modelRoutingLatencyHistogram: Histogram | undefined;
let modelRoutingFailureCounter: Counter | undefined;
let modelSlashCommandCallCounter: Counter | undefined;
let isMetricsInitialized = false;
function getCommonAttributes(config: Config): Attributes {
@@ -130,6 +132,13 @@ export function initializeMetrics(config: Config): void {
valueType: ValueType.INT,
},
);
modelSlashCommandCallCounter = meter.createCounter(
METRIC_MODEL_SLASH_COMMAND_CALL_COUNT,
{
description: 'Counts model slash command calls.',
valueType: ValueType.INT,
},
);
const sessionCounter = meter.createCounter(METRIC_SESSION_COUNT, {
description: 'Count of CLI sessions started.',
@@ -287,6 +296,17 @@ export function recordContentRetryFailure(config: Config): void {
contentRetryFailureCounter.add(1, getCommonAttributes(config));
}
export function recordModelSlashCommand(
config: Config,
event: ModelSlashCommandEvent,
): void {
if (!modelSlashCommandCallCounter || !isMetricsInitialized) return;
modelSlashCommandCallCounter.add(1, {
...getCommonAttributes(config),
'slash_command.model.model_name': event.model_name,
});
}
export function recordModelRoutingMetrics(
config: Config,
event: ModelRoutingEvent,

View File

@@ -567,33 +567,6 @@ export class ModelRoutingEvent implements BaseTelemetryEvent {
}
}
export type TelemetryEvent =
| StartSessionEvent
| EndSessionEvent
| UserPromptEvent
| ToolCallEvent
| ApiRequestEvent
| ApiErrorEvent
| ApiResponseEvent
| FlashFallbackEvent
| LoopDetectedEvent
| LoopDetectionDisabledEvent
| NextSpeakerCheckEvent
| KittySequenceOverflowEvent
| MalformedJsonResponseEvent
| IdeConnectionEvent
| ConversationFinishedEvent
| SlashCommandEvent
| FileOperationEvent
| InvalidChunkEvent
| ContentRetryEvent
| ContentRetryFailureEvent
| ExtensionEnableEvent
| ExtensionInstallEvent
| ExtensionUninstallEvent
| ModelRoutingEvent
| ToolOutputTruncatedEvent;
export class ExtensionInstallEvent implements BaseTelemetryEvent {
'event.name': 'extension_install';
'event.timestamp': string;
@@ -676,6 +649,46 @@ export class ExtensionEnableEvent implements BaseTelemetryEvent {
}
}
export class ModelSlashCommandEvent implements BaseTelemetryEvent {
'event.name': 'model_slash_command';
'event.timestamp': string;
model_name: string;
constructor(model_name: string) {
this['event.name'] = 'model_slash_command';
this['event.timestamp'] = new Date().toISOString();
this.model_name = model_name;
}
}
export type TelemetryEvent =
| StartSessionEvent
| EndSessionEvent
| UserPromptEvent
| ToolCallEvent
| ApiRequestEvent
| ApiErrorEvent
| ApiResponseEvent
| FlashFallbackEvent
| LoopDetectedEvent
| LoopDetectionDisabledEvent
| NextSpeakerCheckEvent
| KittySequenceOverflowEvent
| MalformedJsonResponseEvent
| IdeConnectionEvent
| ConversationFinishedEvent
| SlashCommandEvent
| FileOperationEvent
| InvalidChunkEvent
| ContentRetryEvent
| ContentRetryFailureEvent
| ExtensionEnableEvent
| ExtensionInstallEvent
| ExtensionUninstallEvent
| ModelRoutingEvent
| ToolOutputTruncatedEvent
| ModelSlashCommandEvent;
export class ExtensionDisableEvent implements BaseTelemetryEvent {
'event.name': 'extension_disable';
'event.timestamp': string;