feat(diagnostics-otel): add context assembly spans

This commit is contained in:
Vincent Koc
2026-04-25 11:03:46 -07:00
parent afd6b5d6fc
commit ff172f46a5
5 changed files with 146 additions and 6 deletions

View File

@@ -2427,12 +2427,37 @@ export async function runEmbeddedAttempt(
});
}
const msgCount = activeSession.messages.length;
const systemLen = systemPromptText?.length ?? 0;
const promptLen = effectivePrompt.length;
const sessionSummary = summarizeSessionContext(activeSession.messages);
const reserveTokens = settingsManager.getCompactionReserveTokens();
const contextTokenBudget = params.contextTokenBudget ?? DEFAULT_CONTEXT_TOKENS;
emitTrustedDiagnosticEvent({
type: "context.assembled",
runId: params.runId,
...(params.sessionKey && { sessionKey: params.sessionKey }),
...(params.sessionId && { sessionId: params.sessionId }),
provider: params.provider,
model: params.modelId,
...((params.messageChannel ?? params.messageProvider)
? { channel: params.messageChannel ?? params.messageProvider }
: {}),
trigger: params.trigger,
messageCount: msgCount,
historyTextChars: sessionSummary.totalTextChars,
historyImageBlocks: sessionSummary.totalImageBlocks,
maxMessageTextChars: sessionSummary.maxMessageTextChars,
systemPromptChars: systemLen,
promptChars: promptLen,
promptImages: imageResult.images.length,
contextTokenBudget,
reserveTokens,
trace: freezeDiagnosticTraceContext(createChildDiagnosticTraceContext(runTrace)),
});
// Diagnostic: log context sizes before prompt to help debug early overflow errors.
if (log.isEnabled("debug")) {
const msgCount = activeSession.messages.length;
const systemLen = systemPromptText?.length ?? 0;
const promptLen = effectivePrompt.length;
const sessionSummary = summarizeSessionContext(activeSession.messages);
log.debug(
`[context-diag] pre-prompt: sessionKey=${params.sessionKey ?? params.sessionId} ` +
`messages=${msgCount} roleCounts=${sessionSummary.roleCounts} ` +
@@ -2475,8 +2500,6 @@ export async function runEmbeddedAttempt(
});
}
const reserveTokens = settingsManager.getCompactionReserveTokens();
const contextTokenBudget = params.contextTokenBudget ?? DEFAULT_CONTEXT_TOKENS;
const preemptiveCompaction = shouldPreemptivelyCompactBeforePrompt({
messages: activeSession.messages,
unwindowedMessages: unwindowedContextEngineMessagesForPrecheck,

View File

@@ -280,6 +280,26 @@ export type DiagnosticModelCallErrorEvent = DiagnosticModelCallBaseEvent & {
errorCategory: string;
};
export type DiagnosticContextAssembledEvent = DiagnosticBaseEvent & {
type: "context.assembled";
runId: string;
sessionKey?: string;
sessionId?: string;
provider: string;
model: string;
channel?: string;
trigger?: string;
messageCount: number;
historyTextChars: number;
historyImageBlocks: number;
maxMessageTextChars: number;
systemPromptChars: number;
promptChars: number;
promptImages: number;
contextTokenBudget?: number;
reserveTokens?: number;
};
export type DiagnosticMemoryUsage = {
rssBytes: number;
heapTotalBytes: number;
@@ -355,6 +375,7 @@ export type DiagnosticEventPayload =
| DiagnosticModelCallStartedEvent
| DiagnosticModelCallCompletedEvent
| DiagnosticModelCallErrorEvent
| DiagnosticContextAssembledEvent
| DiagnosticMemorySampleEvent
| DiagnosticMemoryPressureEvent
| DiagnosticPayloadLargeEvent
@@ -401,6 +422,7 @@ const ASYNC_DIAGNOSTIC_EVENT_TYPES = new Set<DiagnosticEventPayload["type"]>([
"model.call.started",
"model.call.completed",
"model.call.error",
"context.assembled",
"log.record",
]);