MCPcopy Create free account
hub / github.com/github/gh-aw / ExtractJSONTokenUsage

Function ExtractJSONTokenUsage

pkg/workflow/metrics.go:91–163  ·  view source on GitHub ↗

ExtractJSONTokenUsage extracts token usage from JSON data

(data map[string]any)

Source from the content-addressed store, hash-verified

89
90// ExtractJSONTokenUsage extracts token usage from JSON data
91func ExtractJSONTokenUsage(data map[string]any) int {
92 // Prefer explicit input+output sums at the top-level
93 inputTop := typeutil.ConvertToInt(data["input_tokens"])
94 outputTop := typeutil.ConvertToInt(data["output_tokens"])
95 if inputTop > 0 || outputTop > 0 {
96 totalTokens := inputTop + outputTop
97 if metricsLog.Enabled() {
98 metricsLog.Printf("Token usage extracted: input=%d, output=%d, total=%d", inputTop, outputTop, totalTokens)
99 }
100 return totalTokens
101 }
102
103 // Check top-level token fields that represent a single total value
104 tokenFields := []string{"tokens", "token_count", "total_tokens"}
105 for _, field := range tokenFields {
106 if val, exists := data[field]; exists {
107 if tokens := typeutil.ConvertToInt(val); tokens > 0 {
108 return tokens
109 }
110 }
111 }
112
113 // Check nested usage objects (Claude and OpenAI API formats)
114 if usage, exists := data["usage"]; exists {
115 if usageMap, ok := usage.(map[string]any); ok {
116 // Claude format: {"usage": {"input_tokens": 10, "output_tokens": 5, "cache_creation_input_tokens": 100, "cache_read_input_tokens": 200}}
117 inputTokens := typeutil.ConvertToInt(usageMap["input_tokens"])
118 outputTokens := typeutil.ConvertToInt(usageMap["output_tokens"])
119 cacheCreationTokens := typeutil.ConvertToInt(usageMap["cache_creation_input_tokens"])
120 cacheReadTokens := typeutil.ConvertToInt(usageMap["cache_read_input_tokens"])
121
122 // OpenAI format: {"usage": {"prompt_tokens": 100, "completion_tokens": 50}}
123 // If Claude fields are not present, try OpenAI fields
124 if inputTokens == 0 {
125 inputTokens = typeutil.ConvertToInt(usageMap["prompt_tokens"])
126 }
127 if outputTokens == 0 {
128 outputTokens = typeutil.ConvertToInt(usageMap["completion_tokens"])
129 }
130
131 totalTokens := inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens
132 if totalTokens > 0 {
133 return totalTokens
134 }
135
136 // Generic token count fields inside usage
137 for _, field := range tokenFields {
138 if val, exists := usageMap[field]; exists {
139 if tokens := typeutil.ConvertToInt(val); tokens > 0 {
140 return tokens
141 }
142 }
143 }
144 }
145 }
146
147 // Check for delta structures (streaming format)
148 if delta, exists := data["delta"]; exists {

Callers 2

ExtractJSONMetricsFunction · 0.85

Calls 3

ConvertToIntFunction · 0.92
EnabledMethod · 0.45
PrintfMethod · 0.45

Tested by 1