mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
Merge branch 'main' into chore/sync-gemini-cli-v0.3.4
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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', {});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user