Merge branch 'main' into chore/sync-gemini-cli-v0.3.4

This commit is contained in:
mingholy.lmh
2025-09-15 13:42:42 +08:00
123 changed files with 13595 additions and 1237 deletions

View File

@@ -24,6 +24,7 @@ export const EVENT_CONTENT_RETRY_FAILURE =
export const EVENT_CONVERSATION_FINISHED = 'qwen-code.conversation_finished';
export const EVENT_MALFORMED_JSON_RESPONSE =
'qwen-code.malformed_json_response';
export const EVENT_SUBAGENT_EXECUTION = 'qwen-code.subagent_execution';
export const METRIC_TOOL_CALL_COUNT = 'qwen-code.tool.call.count';
export const METRIC_TOOL_CALL_LATENCY = 'qwen-code.tool.call.latency';
@@ -36,3 +37,5 @@ export const METRIC_INVALID_CHUNK_COUNT = 'qwen-code.chat.invalid_chunk.count';
export const METRIC_CONTENT_RETRY_COUNT = 'qwen-code.chat.content_retry.count';
export const METRIC_CONTENT_RETRY_FAILURE_COUNT =
'qwen-code.chat.content_retry_failure.count';
export const METRIC_SUBAGENT_EXECUTION_COUNT =
'qwen-code.subagent.execution.count';

View File

@@ -24,6 +24,7 @@ import {
EVENT_INVALID_CHUNK,
EVENT_NEXT_SPEAKER_CHECK,
EVENT_SLASH_COMMAND,
EVENT_SUBAGENT_EXECUTION,
EVENT_TOOL_CALL,
EVENT_USER_PROMPT,
SERVICE_NAME,
@@ -36,6 +37,7 @@ import {
recordContentRetryFailure,
recordFileOperationMetric,
recordInvalidChunk,
recordSubagentExecutionMetrics,
recordTokenUsageMetrics,
recordToolCallMetrics,
} from './metrics.js';
@@ -58,11 +60,11 @@ import type {
NextSpeakerCheckEvent,
SlashCommandEvent,
StartSessionEvent,
SubagentExecutionEvent,
ToolCallEvent,
UserPromptEvent,
} from './types.js';
import type { UiEvent } from './uiTelemetry.js';
import { uiTelemetryService } from './uiTelemetry.js';
import { type UiEvent, uiTelemetryService } from './uiTelemetry.js';
const shouldLogUserPrompts = (config: Config): boolean =>
config.getTelemetryLogPromptsEnabled();
@@ -561,3 +563,31 @@ export function logContentRetryFailure(
logger.emit(logRecord);
recordContentRetryFailure(config);
}
export function logSubagentExecution(
config: Config,
event: SubagentExecutionEvent,
): void {
QwenLogger.getInstance(config)?.logSubagentExecutionEvent(event);
if (!isTelemetrySdkInitialized()) return;
const attributes: LogAttributes = {
...getCommonAttributes(config),
...event,
'event.name': EVENT_SUBAGENT_EXECUTION,
'event.timestamp': new Date().toISOString(),
};
const logger = logs.getLogger(SERVICE_NAME);
const logRecord: LogRecord = {
body: `Subagent execution: ${event.subagent_name}.`,
attributes,
};
logger.emit(logRecord);
recordSubagentExecutionMetrics(
config,
event.subagent_name,
event.status,
event.terminate_reason,
);
}

View File

@@ -19,6 +19,7 @@ import {
METRIC_INVALID_CHUNK_COUNT,
METRIC_CONTENT_RETRY_COUNT,
METRIC_CONTENT_RETRY_FAILURE_COUNT,
METRIC_SUBAGENT_EXECUTION_COUNT,
} from './constants.js';
import type { Config } from '../config/config.js';
import type { DiffStat } from '../tools/tools.js';
@@ -40,6 +41,7 @@ let chatCompressionCounter: Counter | undefined;
let invalidChunkCounter: Counter | undefined;
let contentRetryCounter: Counter | undefined;
let contentRetryFailureCounter: Counter | undefined;
let subagentExecutionCounter: Counter | undefined;
let isMetricsInitialized = false;
function getCommonAttributes(config: Config): Attributes {
@@ -111,6 +113,14 @@ export function initializeMetrics(config: Config): void {
valueType: ValueType.INT,
},
);
subagentExecutionCounter = meter.createCounter(
METRIC_SUBAGENT_EXECUTION_COUNT,
{
description:
'Counts subagent execution events, tagged by status and subagent name.',
valueType: ValueType.INT,
},
);
const sessionCounter = meter.createCounter(METRIC_SESSION_COUNT, {
description: 'Count of CLI sessions started.',
@@ -275,3 +285,27 @@ export function recordContentRetryFailure(config: Config): void {
if (!contentRetryFailureCounter || !isMetricsInitialized) return;
contentRetryFailureCounter.add(1, getCommonAttributes(config));
}
/**
* Records a metric for subagent execution events.
*/
export function recordSubagentExecutionMetrics(
config: Config,
subagentName: string,
status: 'started' | 'completed' | 'failed' | 'cancelled',
terminateReason?: string,
): void {
if (!subagentExecutionCounter || !isMetricsInitialized) return;
const attributes: Attributes = {
...getCommonAttributes(config),
subagent_name: subagentName,
status,
};
if (terminateReason) {
attributes['terminate_reason'] = terminateReason;
}
subagentExecutionCounter.add(1, attributes);
}

View File

@@ -28,6 +28,7 @@ import type {
ContentRetryEvent,
ContentRetryFailureEvent,
ConversationFinishedEvent,
SubagentExecutionEvent,
} from '../types.js';
import { EndSessionEvent } from '../types.js';
import type {
@@ -672,6 +673,20 @@ export class QwenLogger {
this.flushIfNeeded();
}
logSubagentExecutionEvent(event: SubagentExecutionEvent): void {
const rumEvent = this.createActionEvent('subagent', 'subagent_execution', {
snapshots: JSON.stringify({
subagent_name: event.subagent_name,
status: event.status,
terminate_reason: event.terminate_reason,
execution_summary: event.execution_summary,
}),
});
this.enqueueLogEvent(rumEvent);
this.flushIfNeeded();
}
logEndSessionEvent(_event: EndSessionEvent): void {
const applicationEvent = this.createViewEvent('session', 'session_end', {});

View File

@@ -507,6 +507,34 @@ export class ContentRetryFailureEvent implements BaseTelemetryEvent {
}
}
export class SubagentExecutionEvent implements BaseTelemetryEvent {
'event.name': 'subagent_execution';
'event.timestamp': string;
subagent_name: string;
status: 'started' | 'completed' | 'failed' | 'cancelled';
terminate_reason?: string;
result?: string;
execution_summary?: string;
constructor(
subagent_name: string,
status: 'started' | 'completed' | 'failed' | 'cancelled',
options?: {
terminate_reason?: string;
result?: string;
execution_summary?: string;
},
) {
this['event.name'] = 'subagent_execution';
this['event.timestamp'] = new Date().toISOString();
this.subagent_name = subagent_name;
this.status = status;
this.terminate_reason = options?.terminate_reason;
this.result = options?.result;
this.execution_summary = options?.execution_summary;
}
}
export type TelemetryEvent =
| StartSessionEvent
| EndSessionEvent
@@ -526,4 +554,5 @@ export type TelemetryEvent =
| FileOperationEvent
| InvalidChunkEvent
| ContentRetryEvent
| ContentRetryFailureEvent;
| ContentRetryFailureEvent
| SubagentExecutionEvent;