Fix Clearcut logging wire format (#1359)

Fix for Clearcut logging wire format based on validation thread with Clearcut / Concord eng
This commit is contained in:
owenofbrien 2025-06-23 19:47:37 -05:00 committed by GitHub
parent aca034fdfe
commit 37034045ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 121 additions and 104 deletions

View File

@ -66,7 +66,8 @@ export class ClearcutLogger {
createLogEvent(name: string, data: object): object { createLogEvent(name: string, data: object): object {
return { return {
Application: 'GEMINI_CLI', console_type: 'GEMINI_CLI',
application: 102,
event_name: name, event_name: name,
client_install_id: getPersistentUserId(), client_install_id: getPersistentUserId(),
event_metadata: [data] as object[], event_metadata: [data] as object[],
@ -97,7 +98,7 @@ export class ClearcutLogger {
}, },
]; ];
const body = JSON.stringify(request); const body = JSON.stringify(request);
if (this.config?.getDebugMode()) { if (this.config?.getDebugMode() ?? false) {
console.log('Clearcut POST request body:', body); console.log('Clearcut POST request body:', body);
} }
const options = { const options = {
@ -178,63 +179,62 @@ export class ClearcutLogger {
logStartSessionEvent(event: StartSessionEvent): void { logStartSessionEvent(event: StartSessionEvent): void {
const data = [ const data = [
{ {
EventMetadataKey: EventMetadataKey.GEMINI_CLI_START_SESSION_MODEL, gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_MODEL,
value: event.model, value: event.model,
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_EMBEDDING_MODEL, EventMetadataKey.GEMINI_CLI_START_SESSION_EMBEDDING_MODEL,
value: event.embedding_model, value: event.embedding_model,
}, },
{ {
EventMetadataKey: EventMetadataKey.GEMINI_CLI_START_SESSION_SANDBOX, gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_SANDBOX,
value: event.sandbox_enabled.toString(), value: event.sandbox_enabled.toString(),
}, },
{ {
EventMetadataKey: EventMetadataKey.GEMINI_CLI_START_SESSION_CORE_TOOLS, gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_CORE_TOOLS,
value: event.core_tools_enabled, value: event.core_tools_enabled,
}, },
{ {
EventMetadataKey: gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_APPROVAL_MODE,
EventMetadataKey.GEMINI_CLI_START_SESSION_APPROVAL_MODE,
value: event.approval_mode, value: event.approval_mode,
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_API_KEY_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_API_KEY_ENABLED,
value: event.api_key_enabled.toString(), value: event.api_key_enabled.toString(),
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED,
value: event.vertex_ai_enabled.toString(), value: event.vertex_ai_enabled.toString(),
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_DEBUG_MODE_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_DEBUG_MODE_ENABLED,
value: event.debug_enabled.toString(), value: event.debug_enabled.toString(),
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED,
value: event.vertex_ai_enabled.toString(), value: event.vertex_ai_enabled.toString(),
}, },
{ {
EventMetadataKey: EventMetadataKey.GEMINI_CLI_START_SESSION_MCP_SERVERS, gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_MCP_SERVERS,
value: event.mcp_servers, value: event.mcp_servers,
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED,
value: event.vertex_ai_enabled.toString(), value: event.vertex_ai_enabled.toString(),
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_TELEMETRY_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_TELEMETRY_ENABLED,
value: event.telemetry_enabled.toString(), value: event.telemetry_enabled.toString(),
}, },
{ {
EventMetadataKey: gemini_cli_key:
EventMetadataKey.GEMINI_CLI_START_SESSION_TELEMETRY_LOG_USER_PROMPTS_ENABLED, EventMetadataKey.GEMINI_CLI_START_SESSION_TELEMETRY_LOG_USER_PROMPTS_ENABLED,
value: event.telemetry_log_user_prompts_enabled.toString(), value: event.telemetry_log_user_prompts_enabled.toString(),
}, },
@ -245,124 +245,141 @@ export class ClearcutLogger {
} }
logNewPromptEvent(event: UserPromptEvent): void { logNewPromptEvent(event: UserPromptEvent): void {
const data: Map<EventMetadataKey, string> = new Map(); const data = [
{
data.set( gemini_cli_key: EventMetadataKey.GEMINI_CLI_USER_PROMPT_LENGTH,
EventMetadataKey.GEMINI_CLI_USER_PROMPT_LENGTH, value: JSON.stringify(event.prompt_length),
JSON.stringify(event.prompt_length), },
); ];
this.enqueueLogEvent(this.createLogEvent(new_prompt_event_name, data)); this.enqueueLogEvent(this.createLogEvent(new_prompt_event_name, data));
this.flushToClearcut(); this.flushToClearcut();
} }
logToolCallEvent(event: ToolCallEvent): void { logToolCallEvent(event: ToolCallEvent): void {
const data: Map<EventMetadataKey, string> = new Map(); const data = [
{
data.set(EventMetadataKey.GEMINI_CLI_TOOL_CALL_NAME, event.function_name); gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_NAME,
data.set( value: JSON.stringify(event.function_name),
EventMetadataKey.GEMINI_CLI_TOOL_CALL_DECISION, },
JSON.stringify(event.decision), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_DECISION,
data.set( value: JSON.stringify(event.decision),
EventMetadataKey.GEMINI_CLI_TOOL_CALL_SUCCESS, },
JSON.stringify(event.success), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_SUCCESS,
data.set( value: JSON.stringify(event.success),
EventMetadataKey.GEMINI_CLI_TOOL_CALL_DURATION_MS, },
JSON.stringify(event.duration_ms), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_DURATION_MS,
data.set( value: JSON.stringify(event.duration_ms),
EventMetadataKey.GEMINI_CLI_TOOL_ERROR_MESSAGE, },
JSON.stringify(event.error), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_ERROR_MESSAGE,
data.set( value: JSON.stringify(event.error),
EventMetadataKey.GEMINI_CLI_TOOL_CALL_ERROR_TYPE, },
JSON.stringify(event.error_type), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_ERROR_TYPE,
value: JSON.stringify(event.error_type),
},
];
this.enqueueLogEvent(this.createLogEvent(tool_call_event_name, data)); this.enqueueLogEvent(this.createLogEvent(tool_call_event_name, data));
this.flushToClearcut(); this.flushToClearcut();
} }
logApiRequestEvent(event: ApiRequestEvent): void { logApiRequestEvent(event: ApiRequestEvent): void {
const data: Map<EventMetadataKey, string> = new Map(); const data = [
{
data.set(EventMetadataKey.GEMINI_CLI_API_REQUEST_MODEL, event.model); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_REQUEST_MODEL,
value: JSON.stringify(event.model),
},
];
this.enqueueLogEvent(this.createLogEvent(api_request_event_name, data)); this.enqueueLogEvent(this.createLogEvent(api_request_event_name, data));
this.flushToClearcut(); this.flushToClearcut();
} }
logApiResponseEvent(event: ApiResponseEvent): void { logApiResponseEvent(event: ApiResponseEvent): void {
const data: Map<EventMetadataKey, string> = new Map(); const data = [
{
data.set(EventMetadataKey.GEMINI_CLI_API_RESPONSE_MODEL, event.model); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_MODEL,
data.set( value: JSON.stringify(event.model),
EventMetadataKey.GEMINI_CLI_API_RESPONSE_STATUS_CODE, },
JSON.stringify(event.status_code), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_STATUS_CODE,
data.set( value: JSON.stringify(event.status_code),
EventMetadataKey.GEMINI_CLI_API_RESPONSE_DURATION_MS, },
JSON.stringify(event.duration_ms), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_DURATION_MS,
data.set( value: JSON.stringify(event.duration_ms),
EventMetadataKey.GEMINI_CLI_API_ERROR_MESSAGE, },
JSON.stringify(event.error), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_MESSAGE,
data.set( value: JSON.stringify(event.error),
EventMetadataKey.GEMINI_CLI_API_RESPONSE_INPUT_TOKEN_COUNT, },
JSON.stringify(event.input_token_count), {
); gemini_cli_key:
data.set( EventMetadataKey.GEMINI_CLI_API_RESPONSE_INPUT_TOKEN_COUNT,
EventMetadataKey.GEMINI_CLI_API_RESPONSE_OUTPUT_TOKEN_COUNT, value: JSON.stringify(event.input_token_count),
JSON.stringify(event.output_token_count), },
); {
data.set( gemini_cli_key:
EventMetadataKey.GEMINI_CLI_API_RESPONSE_CACHED_TOKEN_COUNT, EventMetadataKey.GEMINI_CLI_API_RESPONSE_OUTPUT_TOKEN_COUNT,
JSON.stringify(event.cached_content_token_count), value: JSON.stringify(event.output_token_count),
); },
data.set( {
EventMetadataKey.GEMINI_CLI_API_RESPONSE_THINKING_TOKEN_COUNT, gemini_cli_key:
JSON.stringify(event.thoughts_token_count), EventMetadataKey.GEMINI_CLI_API_RESPONSE_CACHED_TOKEN_COUNT,
); value: JSON.stringify(event.cached_content_token_count),
data.set( },
EventMetadataKey.GEMINI_CLI_API_RESPONSE_TOOL_TOKEN_COUNT, {
JSON.stringify(event.tool_token_count), gemini_cli_key:
); EventMetadataKey.GEMINI_CLI_API_RESPONSE_THINKING_TOKEN_COUNT,
value: JSON.stringify(event.thoughts_token_count),
},
{
gemini_cli_key:
EventMetadataKey.GEMINI_CLI_API_RESPONSE_THINKING_TOKEN_COUNT,
value: JSON.stringify(event.tool_token_count),
},
];
this.enqueueLogEvent(this.createLogEvent(api_response_event_name, data)); this.enqueueLogEvent(this.createLogEvent(api_response_event_name, data));
this.flushToClearcut(); this.flushToClearcut();
} }
logApiErrorEvent(event: ApiErrorEvent): void { logApiErrorEvent(event: ApiErrorEvent): void {
const data: Map<EventMetadataKey, string> = new Map(); const data = [
{
data.set(EventMetadataKey.GEMINI_CLI_API_ERROR_MODEL, event.model); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_MODEL,
data.set( value: JSON.stringify(event.model),
EventMetadataKey.GEMINI_CLI_API_ERROR_TYPE, },
JSON.stringify(event.error_type), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_TYPE,
data.set( value: JSON.stringify(event.error_type),
EventMetadataKey.GEMINI_CLI_API_ERROR_STATUS_CODE, },
JSON.stringify(event.status_code), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_STATUS_CODE,
data.set( value: JSON.stringify(event.status_code),
EventMetadataKey.GEMINI_CLI_API_ERROR_DURATION_MS, },
JSON.stringify(event.duration_ms), {
); gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_DURATION_MS,
value: JSON.stringify(event.duration_ms),
},
];
this.enqueueLogEvent(this.createLogEvent(api_error_event_name, data)); this.enqueueLogEvent(this.createLogEvent(api_error_event_name, data));
this.flushToClearcut(); this.flushToClearcut();
} }
logEndSessionEvent(event: EndSessionEvent): void { logEndSessionEvent(event: EndSessionEvent): void {
const data: Map<EventMetadataKey, string> = new Map(); const data = [
{
data.set( gemini_cli_key: EventMetadataKey.GEMINI_CLI_END_SESSION_ID,
EventMetadataKey.GEMINI_CLI_END_SESSION_ID, value: event?.session_id?.toString() ?? '',
event?.session_id?.toString() ?? '', },
); ];
this.enqueueLogEvent(this.createLogEvent(end_session_event_name, data)); this.enqueueLogEvent(this.createLogEvent(end_session_event_name, data));
// Flush immediately on session end. // Flush immediately on session end.