Adds centralized support to log slash commands + sub commands (#5128)

This commit is contained in:
Shreya Keshive
2025-07-29 16:20:37 -04:00
committed by GitHub
parent 72d6ef2d3c
commit a2c3dbd189
9 changed files with 187 additions and 1 deletions

View File

@@ -19,6 +19,7 @@ import {
FlashFallbackEvent,
LoopDetectedEvent,
FlashDecidedToContinueEvent,
SlashCommandEvent,
} from '../types.js';
import { EventMetadataKey } from './event-metadata-key.js';
import { Config } from '../../config/config.js';
@@ -40,6 +41,7 @@ const end_session_event_name = 'end_session';
const flash_fallback_event_name = 'flash_fallback';
const loop_detected_event_name = 'loop_detected';
const flash_decided_to_continue_event_name = 'flash_decided_to_continue';
const slash_command_event_name = 'slash_command';
export interface LogResponse {
nextRequestWaitMs?: number;
@@ -528,6 +530,25 @@ export class ClearcutLogger {
this.flushIfNeeded();
}
logSlashCommandEvent(event: SlashCommandEvent): void {
const data = [
{
gemini_cli_key: EventMetadataKey.GEMINI_CLI_SLASH_COMMAND_NAME,
value: JSON.stringify(event.command),
},
];
if (event.subcommand) {
data.push({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_SLASH_COMMAND_SUBCOMMAND,
value: JSON.stringify(event.subcommand),
});
}
this.enqueueLogEvent(this.createLogEvent(slash_command_event_name, data));
this.flushIfNeeded();
}
logEndSessionEvent(event: EndSessionEvent): void {
const data = [
{

View File

@@ -163,6 +163,16 @@ export enum EventMetadataKey {
// Logs the type of loop detected.
GEMINI_CLI_LOOP_DETECTED_TYPE = 38,
// ==========================================================================
// Slash Command Event Keys
// ===========================================================================
// Logs the name of the slash command.
GEMINI_CLI_SLASH_COMMAND_NAME = 41,
// Logs the subcommand of the slash command.
GEMINI_CLI_SLASH_COMMAND_SUBCOMMAND = 42,
}
export function getEventMetadataKey(

View File

@@ -15,6 +15,7 @@ export const EVENT_CLI_CONFIG = 'gemini_cli.config';
export const EVENT_FLASH_FALLBACK = 'gemini_cli.flash_fallback';
export const EVENT_FLASH_DECIDED_TO_CONTINUE =
'gemini_cli.flash_decided_to_continue';
export const EVENT_SLASH_COMMAND = 'gemini_cli.slash_command';
export const METRIC_TOOL_CALL_COUNT = 'gemini_cli.tool.call.count';
export const METRIC_TOOL_CALL_LATENCY = 'gemini_cli.tool.call.latency';

View File

@@ -26,6 +26,7 @@ export {
logApiError,
logApiResponse,
logFlashFallback,
logSlashCommand,
} from './loggers.js';
export {
StartSessionEvent,
@@ -37,6 +38,7 @@ export {
ApiResponseEvent,
TelemetryEvent,
FlashFallbackEvent,
SlashCommandEvent,
} from './types.js';
export { SpanStatusCode, ValueType } from '@opentelemetry/api';
export { SemanticAttributes } from '@opentelemetry/semantic-conventions';

View File

@@ -17,6 +17,7 @@ import {
EVENT_FLASH_FALLBACK,
EVENT_FLASH_DECIDED_TO_CONTINUE,
SERVICE_NAME,
EVENT_SLASH_COMMAND,
} from './constants.js';
import {
ApiErrorEvent,
@@ -28,6 +29,7 @@ import {
FlashFallbackEvent,
FlashDecidedToContinueEvent,
LoopDetectedEvent,
SlashCommandEvent,
} from './types.js';
import {
recordApiErrorMetrics,
@@ -332,3 +334,24 @@ export function logFlashDecidedToContinue(
};
logger.emit(logRecord);
}
export function logSlashCommand(
config: Config,
event: SlashCommandEvent,
): void {
ClearcutLogger.getInstance(config)?.logSlashCommandEvent(event);
if (!isTelemetrySdkInitialized()) return;
const attributes: LogAttributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_SLASH_COMMAND,
};
const logger = logs.getLogger(SERVICE_NAME);
const logRecord: LogRecord = {
body: `Slash command: ${event.command}.`,
attributes,
};
logger.emit(logRecord);
}

View File

@@ -278,6 +278,20 @@ export class FlashDecidedToContinueEvent {
}
}
export class SlashCommandEvent {
'event.name': 'slash_command';
'event.timestamp': string; // ISO 8106
command: string;
subcommand?: string;
constructor(command: string, subcommand?: string) {
this['event.name'] = 'slash_command';
this['event.timestamp'] = new Date().toISOString();
this.command = command;
this.subcommand = subcommand;
}
}
export type TelemetryEvent =
| StartSessionEvent
| EndSessionEvent
@@ -288,4 +302,5 @@ export type TelemetryEvent =
| ApiResponseEvent
| FlashFallbackEvent
| LoopDetectedEvent
| FlashDecidedToContinueEvent;
| FlashDecidedToContinueEvent
| SlashCommandEvent;