feat: add cc.output_tokens trace-level aggregate for Sankey visualization#19
Merged
Conversation
…tion Adds extractOutputTokensSnapshot which aggregates attributed output tokens by category at the trace level, enabling the spend Sankey to use sum(metadata.cc.output_tokens.by_category.*) directly without requiring span-level aggregation. Categories: thinking, assistant_text, builtin_tool_use, mcp_tool_use, skill_invocations — classified by content type and tool name prefix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Details
Adds
cc.output_tokensto the trace-level metadata, enabling the spend Sankey diagram to usesum(metadata.cc.output_tokens.by_category.*)directly without span-level aggregation.Previously the output breakdown (thinking / assistant_text / builtin_tool_use / mcp_tool_use / skill_invocations) only existed on individual spans via
cc.llm_call.attributed_output_tokens+cc.llm_call.block_kind. This is fine for span queries but blocks trace-level aggregations.New field shape:
```json
"cc": {
"output_tokens": {
"summary": { "total_tokens": 1312 },
"by_category": {
"thinking": 364,
"assistant_text": 671,
"builtin_tool_use": 240,
"mcp_tool_use": 25,
"skill_invocations": 12
}
}
}
```
Classification rules:
thinking—ContentType == "thinking"assistant_text—ContentType == "text"mcp_tool_use—ContentType == "tool_use"+ name starts withmcp__skill_invocations—ContentType == "tool_use"+ name== "Skill"builtin_tool_use— all othertool_useblockstotal_tokensequalssum(by_category.*)and matches the LLM call's actualoutput_tokensvia the existing attribution logic (DeduplicateUsage).Change checklist
extractOutputTokensSnapshotadded toextractors.godomainSnapshotsFromEntriesinmain.go(reuses the already-computedparsedTurnslice, no double-parse)TestDryRunOnTestThreaddomain list updatedIssues
N/A
AI-WATERMARK
AI assisted
Testing
go test ./...passes.Documentation
N/A — internal metadata field; consumers are the Sankey FE component.