@quantumai/quantum-cli-core
Version:
Quantum CLI Core - Multi-LLM Collaboration System
187 lines • 7.22 kB
JavaScript
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { logs } from '@opentelemetry/api-logs';
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
import { EVENT_API_ERROR, EVENT_API_REQUEST, EVENT_API_RESPONSE, EVENT_CLI_CONFIG, EVENT_TOOL_CALL, EVENT_USER_PROMPT, SERVICE_NAME, } from './constants.js';
import { recordApiErrorMetrics, recordTokenUsageMetrics, recordApiResponseMetrics, recordToolCallMetrics, } from './metrics.js';
import { isTelemetrySdkInitialized } from './sdk.js';
import { uiTelemetryService } from './uiTelemetry.js';
import { ClearcutLogger } from './clearcut-logger/clearcut-logger.js';
const shouldLogUserPrompts = (config) => config.getTelemetryLogPromptsEnabled();
function getCommonAttributes(config) {
return {
'session.id': config.getSessionId(),
};
}
export function logCliConfiguration(config, event) {
ClearcutLogger.getInstance(config)?.logStartSessionEvent(event);
if (!isTelemetrySdkInitialized())
return;
const attributes = {
...getCommonAttributes(config),
'event.name': EVENT_CLI_CONFIG,
'event.timestamp': new Date().toISOString(),
model: event.model,
embedding_model: event.embedding_model,
sandbox_enabled: event.sandbox_enabled,
core_tools_enabled: event.core_tools_enabled,
approval_mode: event.approval_mode,
api_key_enabled: event.api_key_enabled,
vertex_ai_enabled: event.vertex_ai_enabled,
log_user_prompts_enabled: event.telemetry_log_user_prompts_enabled,
file_filtering_respect_git_ignore: event.file_filtering_respect_git_ignore,
debug_mode: event.debug_enabled,
mcp_servers: event.mcp_servers,
};
const logger = logs.getLogger(SERVICE_NAME);
const logRecord = {
body: 'CLI configuration loaded.',
attributes,
};
logger.emit(logRecord);
}
export function logUserPrompt(config, event) {
ClearcutLogger.getInstance(config)?.logNewPromptEvent(event);
if (!isTelemetrySdkInitialized())
return;
const attributes = {
...getCommonAttributes(config),
'event.name': EVENT_USER_PROMPT,
'event.timestamp': new Date().toISOString(),
prompt_length: event.prompt_length,
};
if (shouldLogUserPrompts(config)) {
attributes.prompt = event.prompt;
}
const logger = logs.getLogger(SERVICE_NAME);
const logRecord = {
body: `User prompt. Length: ${event.prompt_length}.`,
attributes,
};
logger.emit(logRecord);
}
export function logToolCall(config, event) {
const uiEvent = {
...event,
'event.name': EVENT_TOOL_CALL,
'event.timestamp': new Date().toISOString(),
};
uiTelemetryService.addEvent(uiEvent);
ClearcutLogger.getInstance(config)?.logToolCallEvent(event);
if (!isTelemetrySdkInitialized())
return;
const attributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_TOOL_CALL,
'event.timestamp': new Date().toISOString(),
function_args: JSON.stringify(event.function_args, null, 2),
};
if (event.error) {
attributes['error.message'] = event.error;
if (event.error_type) {
attributes['error.type'] = event.error_type;
}
}
const logger = logs.getLogger(SERVICE_NAME);
const logRecord = {
body: `Tool call: ${event.function_name}${event.decision ? `. Decision: ${event.decision}` : ''}. Success: ${event.success}. Duration: ${event.duration_ms}ms.`,
attributes,
};
logger.emit(logRecord);
recordToolCallMetrics(config, event.function_name, event.duration_ms, event.success, event.decision);
}
export function logApiRequest(config, event) {
ClearcutLogger.getInstance(config)?.logApiRequestEvent(event);
if (!isTelemetrySdkInitialized())
return;
const attributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_API_REQUEST,
'event.timestamp': new Date().toISOString(),
};
const logger = logs.getLogger(SERVICE_NAME);
const logRecord = {
body: `API request to ${event.model}.`,
attributes,
};
logger.emit(logRecord);
}
export function logApiError(config, event) {
const uiEvent = {
...event,
'event.name': EVENT_API_ERROR,
'event.timestamp': new Date().toISOString(),
};
uiTelemetryService.addEvent(uiEvent);
ClearcutLogger.getInstance(config)?.logApiErrorEvent(event);
if (!isTelemetrySdkInitialized())
return;
const attributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_API_ERROR,
'event.timestamp': new Date().toISOString(),
['error.message']: event.error,
model_name: event.model,
duration: event.duration_ms,
};
if (event.error_type) {
attributes['error.type'] = event.error_type;
}
if (typeof event.status_code === 'number') {
attributes[SemanticAttributes.HTTP_STATUS_CODE] = event.status_code;
}
const logger = logs.getLogger(SERVICE_NAME);
const logRecord = {
body: `API error for ${event.model}. Error: ${event.error}. Duration: ${event.duration_ms}ms.`,
attributes,
};
logger.emit(logRecord);
recordApiErrorMetrics(config, event.model, event.duration_ms, event.status_code, event.error_type);
}
export function logApiResponse(config, event) {
const uiEvent = {
...event,
'event.name': EVENT_API_RESPONSE,
'event.timestamp': new Date().toISOString(),
};
uiTelemetryService.addEvent(uiEvent);
ClearcutLogger.getInstance(config)?.logApiResponseEvent(event);
if (!isTelemetrySdkInitialized())
return;
const attributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_API_RESPONSE,
'event.timestamp': new Date().toISOString(),
};
if (event.response_text) {
attributes.response_text = event.response_text;
}
if (event.error) {
attributes['error.message'] = event.error;
}
else if (event.status_code) {
if (typeof event.status_code === 'number') {
attributes[SemanticAttributes.HTTP_STATUS_CODE] = event.status_code;
}
}
const logger = logs.getLogger(SERVICE_NAME);
const logRecord = {
body: `API response from ${event.model}. Status: ${event.status_code || 'N/A'}. Duration: ${event.duration_ms}ms.`,
attributes,
};
logger.emit(logRecord);
recordApiResponseMetrics(config, event.model, event.duration_ms, event.status_code, event.error);
recordTokenUsageMetrics(config, event.model, event.input_token_count, 'input');
recordTokenUsageMetrics(config, event.model, event.output_token_count, 'output');
recordTokenUsageMetrics(config, event.model, event.cached_content_token_count, 'cache');
recordTokenUsageMetrics(config, event.model, event.thoughts_token_count, 'thought');
recordTokenUsageMetrics(config, event.model, event.tool_token_count, 'tool');
}
//# sourceMappingURL=loggers.js.map