@@ -264,6 +264,23 @@ def update_usage(self, usage: Usage) -> None:
264264 self .accumulated_usage ["outputTokens" ] += usage ["outputTokens" ]
265265 self .accumulated_usage ["totalTokens" ] += usage ["totalTokens" ]
266266
267+ # Handle optional cached token metrics
268+ if "cacheReadInputTokens" in usage and usage ["cacheReadInputTokens" ] is not None :
269+ cache_read_tokens = usage ["cacheReadInputTokens" ]
270+ self ._metrics_client .event_loop_cache_read_tokens .record (cache_read_tokens )
271+ if "cacheReadInputTokens" not in self .accumulated_usage :
272+ self .accumulated_usage ["cacheReadInputTokens" ] = 0
273+ current_cache_read = self .accumulated_usage .get ("cacheReadInputTokens" , 0 ) or 0
274+ self .accumulated_usage ["cacheReadInputTokens" ] = current_cache_read + cache_read_tokens
275+
276+ if "cacheWriteInputTokens" in usage and usage ["cacheWriteInputTokens" ] is not None :
277+ cache_write_tokens = usage ["cacheWriteInputTokens" ]
278+ self ._metrics_client .event_loop_cache_write_tokens .record (cache_write_tokens )
279+ if "cacheWriteInputTokens" not in self .accumulated_usage :
280+ self .accumulated_usage ["cacheWriteInputTokens" ] = 0
281+ current_cache_write = self .accumulated_usage .get ("cacheWriteInputTokens" , 0 ) or 0
282+ self .accumulated_usage ["cacheWriteInputTokens" ] = current_cache_write + cache_write_tokens
283+
267284 def update_metrics (self , metrics : Metrics ) -> None :
268285 """Update the accumulated performance metrics with new metrics data.
269286
@@ -325,11 +342,21 @@ def _metrics_summary_to_lines(event_loop_metrics: EventLoopMetrics, allowed_name
325342 f"├─ Cycles: total={ summary ['total_cycles' ]} , avg_time={ summary ['average_cycle_time' ]:.3f} s, "
326343 f"total_time={ summary ['total_duration' ]:.3f} s"
327344 )
328- yield (
329- f"├─ Tokens: in={ summary ['accumulated_usage' ]['inputTokens' ]} , "
330- f"out={ summary ['accumulated_usage' ]['outputTokens' ]} , "
331- f"total={ summary ['accumulated_usage' ]['totalTokens' ]} "
332- )
345+
346+ # Build token display with optional cached tokens
347+ token_parts = [
348+ f"in={ summary ['accumulated_usage' ]['inputTokens' ]} " ,
349+ f"out={ summary ['accumulated_usage' ]['outputTokens' ]} " ,
350+ f"total={ summary ['accumulated_usage' ]['totalTokens' ]} " ,
351+ ]
352+
353+ # Add cached token info if present
354+ if summary ["accumulated_usage" ].get ("cacheReadInputTokens" ):
355+ token_parts .append (f"cache_read={ summary ['accumulated_usage' ]['cacheReadInputTokens' ]} " )
356+ if summary ["accumulated_usage" ].get ("cacheWriteInputTokens" ):
357+ token_parts .append (f"cache_write={ summary ['accumulated_usage' ]['cacheWriteInputTokens' ]} " )
358+
359+ yield f"├─ Tokens: { ', ' .join (token_parts )} "
333360 yield f"├─ Bedrock Latency: { summary ['accumulated_metrics' ]['latencyMs' ]} ms"
334361
335362 yield "├─ Tool Usage:"
@@ -421,6 +448,8 @@ class MetricsClient:
421448 event_loop_latency : Histogram
422449 event_loop_input_tokens : Histogram
423450 event_loop_output_tokens : Histogram
451+ event_loop_cache_read_tokens : Histogram
452+ event_loop_cache_write_tokens : Histogram
424453
425454 tool_call_count : Counter
426455 tool_success_count : Counter
@@ -474,3 +503,9 @@ def create_instruments(self) -> None:
474503 self .event_loop_output_tokens = self .meter .create_histogram (
475504 name = constants .STRANDS_EVENT_LOOP_OUTPUT_TOKENS , unit = "token"
476505 )
506+ self .event_loop_cache_read_tokens = self .meter .create_histogram (
507+ name = constants .STRANDS_EVENT_LOOP_CACHE_READ_TOKENS , unit = "token"
508+ )
509+ self .event_loop_cache_write_tokens = self .meter .create_histogram (
510+ name = constants .STRANDS_EVENT_LOOP_CACHE_WRITE_TOKENS , unit = "token"
511+ )
0 commit comments