Skip to content

feat(chronicle): emit assistant.usage events for VS Code Chat sessions#317640

Closed
digitarald wants to merge 3 commits into
microsoft:mainfrom
digitarald:agents/https-github-com-microsoft-vscode-internalbacklo-b40e0a7c
Closed

feat(chronicle): emit assistant.usage events for VS Code Chat sessions#317640
digitarald wants to merge 3 commits into
microsoft:mainfrom
digitarald:agents/https-github-com-microsoft-vscode-internalbacklo-b40e0a7c

Conversation

@digitarald

@digitarald digitarald commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds assistant.usage event emission to the cloud session store so that token consumption from the native VS Code Chat harness (~85% of sessions) becomes visible for cost analysis.

Problem

VS Code Chat sessions have turns data in the cloud session store but zero assistant.usage events, making token consumption invisible to the cost-optimizer skill and any usage analysis queries.

Changes

eventTranslator.ts

  • translateSpan() now handles GenAiOperationName.CHAT spans, emitting assistant.usage events with:
    • P0 fields: model, inputTokens, outputTokens
    • Optional fields: cacheReadTokens, timeToFirstTokenMs, duration
    • Sub-agent attribution via agentId
  • translateDebugLogEntry() handles llm_request entries for the reindex/backfill path
    • Accepts both cachedTokens (production debug logger format) and cacheReadTokens field names
    • Maps ttft attribute to timeToFirstTokenMs

remoteSessionExporter.ts

  • Buffers pre-init CHAT spans (which complete before their parent invoke_agent span) and replays them after session initialization to avoid losing first-turn usage data
  • Preserves sub-agent attribution (subagentId) for buffered CHAT spans during replay
  • Cleanup in dispose and session disposal handlers

Tests

  • 6 new tests in eventTranslator.spec.ts covering: CHAT spans with/without usage tokens, model fallback, sub-agent attribution, debug log entry translation, and field name fallback
  • All 223 chronicle tests pass

Validation

  • npx tsc --noEmit — zero errors
  • npx vitest run src/extension/chronicle/ — 223 tests pass (11 files)

Fixes microsoft/vscode-internalbacklog#7766

Add assistant.usage event emission to the cloud session store so token
consumption from the native VS Code Chat harness is visible for cost
analysis.

Changes:
- translateSpan() now handles GenAiOperationName.CHAT spans, emitting
  assistant.usage events with model, inputTokens, outputTokens, and
  optional cacheReadTokens, timeToFirstTokenMs, duration fields
- translateDebugLogEntry() handles llm_request entries for the
  reindex/backfill path
- RemoteSessionExporter buffers pre-init CHAT spans (which complete
  before their parent invoke_agent) and replays them after session
  initialization to avoid losing first-turn usage data

Fixes microsoft/vscode-internalbacklog#7766

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds assistant.usage event emission to Chronicle’s cloud session export pipeline so VS Code Chat sessions contribute token-usage data for cost/usage analysis (including support for both live OTel spans and debug-log reindexing).

Changes:

  • Extend translateSpan() to translate GenAiOperationName.CHAT spans into assistant.usage events (tokens, model, optional TTFT/duration/cache).
  • Extend translateDebugLogEntry() to emit assistant.usage for llm_request entries during reindex/backfill.
  • Buffer pre-init CHAT spans in RemoteSessionExporter and replay them after session initialization to avoid losing first-turn usage.
Show a summary per file
File Description
extensions/copilot/src/extension/chronicle/vscode-node/remoteSessionExporter.ts Buffers CHAT spans that complete before invoke_agent initialization and replays them after init.
extensions/copilot/src/extension/chronicle/common/eventTranslator.ts Emits assistant.usage events from CHAT spans and llm_request debug log entries.
extensions/copilot/src/extension/chronicle/common/test/eventTranslator.spec.ts Adds tests for CHAT-span and llm_requestassistant.usage translation paths.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

Comment thread extensions/copilot/src/extension/chronicle/common/eventTranslator.ts Outdated
digitarald and others added 2 commits May 20, 2026 15:06
- Preserve sub-agent attribution when replaying buffered CHAT spans by
  storing { span, subagentId } in _pendingChatSpans instead of bare spans
- Accept both 'cachedTokens' (production debug logger format) and
  'cacheReadTokens' field names in llm_request backfill path
- Map 'ttft' attribute to timeToFirstTokenMs in backfilled events
- Update test fixtures to use production attribute names (cachedTokens, ttft)
- Add test for cacheReadTokens fallback field name

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Usage events are transient metrics that should not be persisted as
session content. Set ephemeral=true on both the span translation and
debug log backfill paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@digitarald

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

data.duration = span.endTime - span.startTime;
}

pushEvent(events, state, 'assistant.usage', data, /*ephemeral*/ false, subagentId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ephemeral/ flag needs to be true else server could reject this payload.

outputTokens,
};
const cacheReadTokens = entry.attrs.cacheReadTokens;
if (typeof cacheReadTokens === 'number') {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for reindex, we need to handle cachedTokens and ttf which is written by the chat debug logger.

if (pendingChats) {
this._pendingChatSpans.delete(sessionId);
for (const chatSpan of pendingChats) {
const chatEvents = translateSpan(chatSpan, state, context);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on the CCR feedback regarding subAgent

@vijayupadya

Copy link
Copy Markdown
Contributor

you can close this PR. these changes are merged from a different pr.

@digitarald digitarald closed this May 22, 2026
@digitarald digitarald deleted the agents/https-github-com-microsoft-vscode-internalbacklo-b40e0a7c branch May 22, 2026 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants