Skip to content

Commit 1c0f510

Browse files
fix: derive overall token totals from per-agent events instead of broken summary event
The LLM_Token_Usage_Summary event only captured MapHandler tokens because save_handler doesn't have visibility into Workflow service steps (Summarize, RAI, GapAnalysis). Fixed all queries that need total token counts to aggregate from LLM_Agent_Token_Usage events grouped by process_id. Queries fixed: - Overall Token Usage Summary - Token Usage Over Time - Estimated Daily Cost - Top 20 Token Consumers (join with Summary for file_name) - Token Usage by File Type (join with Summary for mime_type) - Token Usage Percentiles - Daily Processing Volume Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2aa4918 commit 1c0f510

3 files changed

Lines changed: 56 additions & 27 deletions

File tree

infra/dashboards/token-usage-queries.kql

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
// 1. Overall token usage summary (last 7 days)
88
customEvents
9-
| where name == 'LLM_Token_Usage_Summary'
9+
| where name == 'LLM_Agent_Token_Usage'
1010
| where timestamp > ago(7d)
11-
| extend input_tokens = toint(customDimensions['total_input_tokens'])
12-
| extend output_tokens = toint(customDimensions['total_output_tokens'])
11+
| extend process_id = tostring(customDimensions['process_id'])
12+
| extend input_tokens = toint(customDimensions['input_tokens'])
13+
| extend output_tokens = toint(customDimensions['output_tokens'])
1314
| extend total_tokens = toint(customDimensions['total_tokens'])
15+
| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), total_tokens=sum(total_tokens) by process_id
1416
| summarize
1517
TotalDocuments = count(),
1618
TotalInputTokens = sum(input_tokens),
@@ -36,10 +38,12 @@ customEvents
3638

3739
// 3. Token usage over time (hourly)
3840
customEvents
39-
| where name == 'LLM_Token_Usage_Summary'
41+
| where name == 'LLM_Agent_Token_Usage'
4042
| where timestamp > ago(7d)
41-
| extend input_tokens = toint(customDimensions['total_input_tokens'])
42-
| extend output_tokens = toint(customDimensions['total_output_tokens'])
43+
| extend process_id = tostring(customDimensions['process_id'])
44+
| extend input_tokens = toint(customDimensions['input_tokens'])
45+
| extend output_tokens = toint(customDimensions['output_tokens'])
46+
| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), timestamp=min(timestamp) by process_id
4347
| summarize InputTokens = sum(input_tokens), OutputTokens = sum(output_tokens) by bin(timestamp, 1h)
4448
| order by timestamp asc
4549
| render areachart
@@ -48,10 +52,12 @@ customEvents
4852
let input_price_per_million = 2.50;
4953
let output_price_per_million = 10.00;
5054
customEvents
51-
| where name == 'LLM_Token_Usage_Summary'
55+
| where name == 'LLM_Agent_Token_Usage'
5256
| where timestamp > ago(30d)
53-
| extend input_tokens = toint(customDimensions['total_input_tokens'])
54-
| extend output_tokens = toint(customDimensions['total_output_tokens'])
57+
| extend process_id = tostring(customDimensions['process_id'])
58+
| extend input_tokens = toint(customDimensions['input_tokens'])
59+
| extend output_tokens = toint(customDimensions['output_tokens'])
60+
| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), timestamp=min(timestamp) by process_id
5561
| summarize TotalInput = sum(input_tokens), TotalOutput = sum(output_tokens) by bin(timestamp, 1d)
5662
| extend InputCost = round(TotalInput * input_price_per_million / 1000000.0, 4)
5763
| extend OutputCost = round(TotalOutput * output_price_per_million / 1000000.0, 4)
@@ -61,12 +67,20 @@ customEvents
6167

6268
// 5. Top token consumers by document
6369
customEvents
64-
| where name == 'LLM_Token_Usage_Summary'
70+
| where name == 'LLM_Agent_Token_Usage'
6571
| where timestamp > ago(7d)
66-
| extend total_tokens = toint(customDimensions['total_tokens'])
6772
| extend process_id = tostring(customDimensions['process_id'])
68-
| extend file_name = tostring(customDimensions['file_name'])
69-
| summarize TotalTokens = sum(total_tokens) by process_id, file_name
73+
| extend total_tokens = toint(customDimensions['total_tokens'])
74+
| summarize TotalTokens = sum(total_tokens) by process_id
75+
| join kind=leftouter (
76+
customEvents
77+
| where name == 'LLM_Token_Usage_Summary'
78+
| where timestamp > ago(7d)
79+
| extend process_id = tostring(customDimensions['process_id'])
80+
| extend file_name = tostring(customDimensions['file_name'])
81+
| summarize file_name=take_any(file_name) by process_id
82+
) on process_id
83+
| project process_id, file_name, TotalTokens
7084
| order by TotalTokens desc
7185
| take 20
7286

@@ -81,9 +95,11 @@ customEvents
8195

8296
// 7. Token usage percentiles per document
8397
customEvents
84-
| where name == 'LLM_Token_Usage_Summary'
98+
| where name == 'LLM_Agent_Token_Usage'
8599
| where timestamp > ago(7d)
100+
| extend process_id = tostring(customDimensions['process_id'])
86101
| extend total_tokens = toint(customDimensions['total_tokens'])
102+
| summarize total_tokens=sum(total_tokens) by process_id
87103
| summarize
88104
p50 = percentile(total_tokens, 50),
89105
p90 = percentile(total_tokens, 90),
@@ -230,12 +246,21 @@ dependencies
230246

231247
// 16. Token usage by file type (PDF, DOCX, image, etc.)
232248
customEvents
233-
| where name == 'LLM_Token_Usage_Summary'
249+
| where name == 'LLM_Agent_Token_Usage'
234250
| where timestamp > ago(7d)
251+
| extend process_id = tostring(customDimensions['process_id'])
252+
| extend input_tokens = toint(customDimensions['input_tokens'])
253+
| extend output_tokens = toint(customDimensions['output_tokens'])
235254
| extend total_tokens = toint(customDimensions['total_tokens'])
236-
| extend input_tokens = toint(customDimensions['total_input_tokens'])
237-
| extend output_tokens = toint(customDimensions['total_output_tokens'])
238-
| extend mime_type = tostring(customDimensions['file_mime_type'])
255+
| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), total_tokens=sum(total_tokens) by process_id
256+
| join kind=leftouter (
257+
customEvents
258+
| where name == 'LLM_Token_Usage_Summary'
259+
| where timestamp > ago(7d)
260+
| extend process_id = tostring(customDimensions['process_id'])
261+
| extend mime_type = tostring(customDimensions['file_mime_type'])
262+
| summarize mime_type=take_any(mime_type) by process_id
263+
) on process_id
239264
| extend file_type = case(
240265
mime_type has "pdf", "PDF",
241266
mime_type has "image", "Image",
@@ -270,10 +295,11 @@ customEvents
270295

271296
// 18. Daily processing volume with token costs
272297
customEvents
273-
| where name == 'LLM_Token_Usage_Summary'
298+
| where name == 'LLM_Agent_Token_Usage'
274299
| where timestamp > ago(30d)
300+
| extend process_id = tostring(customDimensions['process_id'])
275301
| extend total_tokens = toint(customDimensions['total_tokens'])
276-
| extend file_name = tostring(customDimensions['file_name'])
302+
| summarize total_tokens=sum(total_tokens), timestamp=min(timestamp) by process_id
277303
| summarize
278304
DocumentsProcessed = count(),
279305
TotalTokens = sum(total_tokens),

infra/dashboards/token-usage-workbook.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"type": 3,
6060
"content": {
6161
"version": "KqlItem/1.0",
62-
"query": "customEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['total_input_tokens'])\r\n| extend output_tokens = toint(customDimensions['total_output_tokens'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize input_tokens=max(input_tokens), output_tokens=max(output_tokens), total_tokens=max(total_tokens) by process_id\r\n| summarize\r\n TotalDocuments = count(),\r\n TotalInputTokens = sum(input_tokens),\r\n TotalOutputTokens = sum(output_tokens),\r\n TotalTokens = sum(total_tokens),\r\n AvgTokensPerDocument = round(avg(total_tokens), 0)",
62+
"query": "customEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['input_tokens'])\r\n| extend output_tokens = toint(customDimensions['output_tokens'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), total_tokens=sum(total_tokens) by process_id\r\n| summarize\r\n TotalDocuments = count(),\r\n TotalInputTokens = sum(input_tokens),\r\n TotalOutputTokens = sum(output_tokens),\r\n TotalTokens = sum(total_tokens),\r\n AvgTokensPerDocument = round(avg(total_tokens), 0)",
6363
"size": 3,
6464
"title": "Overall Token Usage Summary",
6565
"timeContextFromParameter": "TimeRange",
@@ -95,7 +95,7 @@
9595
"type": 3,
9696
"content": {
9797
"version": "KqlItem/1.0",
98-
"query": "customEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['total_input_tokens'])\r\n| extend output_tokens = toint(customDimensions['total_output_tokens'])\r\n| summarize input_tokens=max(input_tokens), output_tokens=max(output_tokens), timestamp=min(timestamp) by process_id\r\n| summarize InputTokens = sum(input_tokens), OutputTokens = sum(output_tokens) by bin(timestamp, 1h)\r\n| order by timestamp asc",
98+
"query": "customEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['input_tokens'])\r\n| extend output_tokens = toint(customDimensions['output_tokens'])\r\n| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), timestamp=min(timestamp) by process_id\r\n| summarize InputTokens = sum(input_tokens), OutputTokens = sum(output_tokens) by bin(timestamp, 1h)\r\n| order by timestamp asc",
9999
"size": 0,
100100
"title": "Token Usage Over Time (Hourly)",
101101
"timeContextFromParameter": "TimeRange",
@@ -130,7 +130,7 @@
130130
"type": 3,
131131
"content": {
132132
"version": "KqlItem/1.0",
133-
"query": "let input_price_per_million = 2.50;\r\nlet output_price_per_million = 10.00;\r\ncustomEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['total_input_tokens'])\r\n| extend output_tokens = toint(customDimensions['total_output_tokens'])\r\n| summarize input_tokens=max(input_tokens), output_tokens=max(output_tokens), timestamp=min(timestamp) by process_id\r\n| summarize TotalInput = sum(input_tokens), TotalOutput = sum(output_tokens) by bin(timestamp, 1d)\r\n| extend InputCost = round(TotalInput * input_price_per_million / 1000000.0, 4)\r\n| extend OutputCost = round(TotalOutput * output_price_per_million / 1000000.0, 4)\r\n| extend TotalCost = InputCost + OutputCost\r\n| project Day = timestamp, TotalInput, TotalOutput, InputCost, OutputCost, TotalCost\r\n| order by Day desc",
133+
"query": "let input_price_per_million = 2.50;\r\nlet output_price_per_million = 10.00;\r\ncustomEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['input_tokens'])\r\n| extend output_tokens = toint(customDimensions['output_tokens'])\r\n| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), timestamp=min(timestamp) by process_id\r\n| summarize TotalInput = sum(input_tokens), TotalOutput = sum(output_tokens) by bin(timestamp, 1d)\r\n| extend InputCost = round(TotalInput * input_price_per_million / 1000000.0, 4)\r\n| extend OutputCost = round(TotalOutput * output_price_per_million / 1000000.0, 4)\r\n| extend TotalCost = InputCost + OutputCost\r\n| project Day = timestamp, TotalInput, TotalOutput, InputCost, OutputCost, TotalCost\r\n| order by Day desc",
134134
"size": 0,
135135
"title": "Estimated Daily Cost (GPT-4o Pricing: $2.50/1M input, $10.00/1M output)",
136136
"timeContextFromParameter": "TimeRange",
@@ -193,7 +193,7 @@
193193
"type": 3,
194194
"content": {
195195
"version": "KqlItem/1.0",
196-
"query": "customEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend file_name = tostring(customDimensions['file_name'])\r\n| summarize TotalTokens = max(total_tokens) by process_id, file_name\r\n| order by TotalTokens desc\r\n| take 20",
196+
"query": "customEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize TotalTokens = sum(total_tokens) by process_id\r\n| join kind=leftouter (\r\n customEvents\r\n | where name == 'LLM_Token_Usage_Summary'\r\n | where timestamp > ago(7d)\r\n | extend process_id = tostring(customDimensions['process_id'])\r\n | extend file_name = tostring(customDimensions['file_name'])\r\n | summarize file_name=take_any(file_name) by process_id\r\n) on process_id\r\n| project process_id, file_name, TotalTokens\r\n| order by TotalTokens desc\r\n| take 20",
197197
"size": 0,
198198
"title": "Top 20 Token Consumers by Document",
199199
"timeContextFromParameter": "TimeRange",
@@ -207,7 +207,7 @@
207207
"type": 3,
208208
"content": {
209209
"version": "KqlItem/1.0",
210-
"query": "customEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| extend input_tokens = toint(customDimensions['total_input_tokens'])\r\n| extend output_tokens = toint(customDimensions['total_output_tokens'])\r\n| extend mime_type = tostring(customDimensions['file_mime_type'])\r\n| extend file_type = case(\r\n mime_type has \"pdf\", \"PDF\",\r\n mime_type has \"image\", \"Image\",\r\n mime_type has \"word\" or mime_type has \"docx\", \"Word\",\r\n mime_type has \"excel\" or mime_type has \"xlsx\", \"Excel\",\r\n mime_type has \"text\", \"Text\",\r\n \"Other\")\r\n| summarize input_tokens=max(input_tokens), output_tokens=max(output_tokens), total_tokens=max(total_tokens), file_type=take_any(file_type) by process_id\r\n| summarize\r\n Documents = count(),\r\n TotalInputTokens = sum(input_tokens),\r\n TotalOutputTokens = sum(output_tokens),\r\n TotalTokens = sum(total_tokens),\r\n AvgTokensPerDoc = round(avg(total_tokens), 0)\r\n by FileType = file_type\r\n| order by TotalTokens desc",
210+
"query": "customEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend input_tokens = toint(customDimensions['input_tokens'])\r\n| extend output_tokens = toint(customDimensions['output_tokens'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize input_tokens=sum(input_tokens), output_tokens=sum(output_tokens), total_tokens=sum(total_tokens) by process_id\r\n| join kind=leftouter (\r\n customEvents\r\n | where name == 'LLM_Token_Usage_Summary'\r\n | where timestamp > ago(7d)\r\n | extend process_id = tostring(customDimensions['process_id'])\r\n | extend mime_type = tostring(customDimensions['file_mime_type'])\r\n | summarize mime_type=take_any(mime_type) by process_id\r\n) on process_id\r\n| extend file_type = case(\r\n mime_type has \"pdf\", \"PDF\",\r\n mime_type has \"image\", \"Image\",\r\n mime_type has \"word\" or mime_type has \"docx\", \"Word\",\r\n mime_type has \"excel\" or mime_type has \"xlsx\", \"Excel\",\r\n mime_type has \"text\", \"Text\",\r\n \"Other\")\r\n| summarize\r\n Documents = count(),\r\n TotalInputTokens = sum(input_tokens),\r\n TotalOutputTokens = sum(output_tokens),\r\n TotalTokens = sum(total_tokens),\r\n AvgTokensPerDoc = round(avg(total_tokens), 0)\r\n by FileType = file_type\r\n| order by TotalTokens desc",
211211
"size": 0,
212212
"title": "Token Usage by File Type",
213213
"timeContextFromParameter": "TimeRange",
@@ -228,7 +228,7 @@
228228
"type": 3,
229229
"content": {
230230
"version": "KqlItem/1.0",
231-
"query": "customEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize total_tokens=max(total_tokens) by process_id\r\n| summarize\r\n p50 = percentile(total_tokens, 50),\r\n p90 = percentile(total_tokens, 90),\r\n p95 = percentile(total_tokens, 95),\r\n p99 = percentile(total_tokens, 99),\r\n Max = max(total_tokens)",
231+
"query": "customEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize total_tokens=sum(total_tokens) by process_id\r\n| summarize\r\n p50 = percentile(total_tokens, 50),\r\n p90 = percentile(total_tokens, 90),\r\n p95 = percentile(total_tokens, 95),\r\n p99 = percentile(total_tokens, 99),\r\n Max = max(total_tokens)",
232232
"size": 3,
233233
"title": "Token Usage Percentiles Per Document",
234234
"timeContextFromParameter": "TimeRange",
@@ -250,7 +250,7 @@
250250
"type": 3,
251251
"content": {
252252
"version": "KqlItem/1.0",
253-
"query": "customEvents\r\n| where name == 'LLM_Token_Usage_Summary'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize total_tokens=max(total_tokens), timestamp=min(timestamp) by process_id\r\n| summarize\r\n DocumentsProcessed = count(),\r\n TotalTokens = sum(total_tokens),\r\n AvgTokensPerDoc = round(avg(total_tokens), 0),\r\n MaxTokensPerDoc = max(total_tokens)\r\n by Day = bin(timestamp, 1d)\r\n| order by Day desc",
253+
"query": "customEvents\r\n| where name == 'LLM_Agent_Token_Usage'\r\n| where timestamp > ago(7d)\r\n| extend process_id = tostring(customDimensions['process_id'])\r\n| extend total_tokens = toint(customDimensions['total_tokens'])\r\n| summarize total_tokens=sum(total_tokens), timestamp=min(timestamp) by process_id\r\n| summarize\r\n DocumentsProcessed = count(),\r\n TotalTokens = sum(total_tokens),\r\n AvgTokensPerDoc = round(avg(total_tokens), 0),\r\n MaxTokensPerDoc = max(total_tokens)\r\n by Day = bin(timestamp, 1d)\r\n| order by Day desc",
254254
"size": 0,
255255
"title": "Daily Processing Volume with Token Usage",
256256
"timeContextFromParameter": "TimeRange",

src/ContentProcessor/src/libs/pipeline/handlers/save_handler.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ def find_process_result(step_name: str):
170170
)
171171

172172
# Emit token usage summary and per-model events to Application Insights
173+
# NOTE: This summary only contains tokens from the evaluate/map step.
174+
# For true totals across all pipeline steps (Summarize, RAI, GapAnalysis),
175+
# aggregate from LLM_Agent_Token_Usage events grouped by process_id.
173176
emit_summary_token_event(
174177
total_input_tokens=evaluated_result.prompt_tokens,
175178
total_output_tokens=evaluated_result.completion_tokens,

0 commit comments

Comments
 (0)