mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
feat: subagent runtime & CLI display - wip
This commit is contained in:
@@ -21,6 +21,7 @@ export const EVENT_INVALID_CHUNK = 'qwen-code.chat.invalid_chunk';
|
||||
export const EVENT_CONTENT_RETRY = 'qwen-code.chat.content_retry';
|
||||
export const EVENT_CONTENT_RETRY_FAILURE =
|
||||
'qwen-code.chat.content_retry_failure';
|
||||
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';
|
||||
@@ -33,3 +34,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';
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
EVENT_INVALID_CHUNK,
|
||||
EVENT_CONTENT_RETRY,
|
||||
EVENT_CONTENT_RETRY_FAILURE,
|
||||
EVENT_SUBAGENT_EXECUTION,
|
||||
} from './constants.js';
|
||||
import {
|
||||
ApiErrorEvent,
|
||||
@@ -41,6 +42,7 @@ import {
|
||||
InvalidChunkEvent,
|
||||
ContentRetryEvent,
|
||||
ContentRetryFailureEvent,
|
||||
SubagentExecutionEvent,
|
||||
} from './types.js';
|
||||
import {
|
||||
recordApiErrorMetrics,
|
||||
@@ -51,6 +53,7 @@ import {
|
||||
recordInvalidChunk,
|
||||
recordContentRetry,
|
||||
recordContentRetryFailure,
|
||||
recordSubagentExecutionMetrics,
|
||||
} from './metrics.js';
|
||||
import { QwenLogger } from './qwen-logger/qwen-logger.js';
|
||||
import { isTelemetrySdkInitialized } from './sdk.js';
|
||||
@@ -504,3 +507,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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
METRIC_INVALID_CHUNK_COUNT,
|
||||
METRIC_CONTENT_RETRY_COUNT,
|
||||
METRIC_CONTENT_RETRY_FAILURE_COUNT,
|
||||
METRIC_SUBAGENT_EXECUTION_COUNT,
|
||||
} from './constants.js';
|
||||
import { Config } from '../config/config.js';
|
||||
import { DiffStat } from '../tools/tools.js';
|
||||
@@ -46,6 +47,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 {
|
||||
@@ -117,6 +119,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.',
|
||||
@@ -277,3 +287,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' | 'progress' | 'completed' | 'failed',
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
InvalidChunkEvent,
|
||||
ContentRetryEvent,
|
||||
ContentRetryFailureEvent,
|
||||
SubagentExecutionEvent,
|
||||
} from '../types.js';
|
||||
import {
|
||||
RumEvent,
|
||||
@@ -628,6 +629,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', {});
|
||||
|
||||
|
||||
@@ -444,6 +444,34 @@ export class ContentRetryFailureEvent implements BaseTelemetryEvent {
|
||||
}
|
||||
}
|
||||
|
||||
export class SubagentExecutionEvent implements BaseTelemetryEvent {
|
||||
'event.name': 'subagent_execution';
|
||||
'event.timestamp': string;
|
||||
subagent_name: string;
|
||||
status: 'started' | 'progress' | 'completed' | 'failed';
|
||||
terminate_reason?: string;
|
||||
result?: string;
|
||||
execution_summary?: string;
|
||||
|
||||
constructor(
|
||||
subagent_name: string,
|
||||
status: 'started' | 'progress' | 'completed' | 'failed',
|
||||
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
|
||||
@@ -461,4 +489,5 @@ export type TelemetryEvent =
|
||||
| SlashCommandEvent
|
||||
| InvalidChunkEvent
|
||||
| ContentRetryEvent
|
||||
| ContentRetryFailureEvent;
|
||||
| ContentRetryFailureEvent
|
||||
| SubagentExecutionEvent;
|
||||
|
||||
Reference in New Issue
Block a user