rhythmic-breakfast-40081
04/30/2026, 8:00 PMtall-airline-16756
04/30/2026, 8:00 PMtall-airline-16756
04/30/2026, 8:01 PMself._call_idx in dump_llm_request() so each LLM request gets a unique call index.
◦ AgentSession emits a metrics_collected event with an LLMMetrics instance; _on_metrics() reads prompt_tokens, prompt_cached_tokens, and completion_tokens and logs them with self._call_idx.
◦ That produces per-call lines like:
[LLM #n] prompt=X (cached=Y, fresh=X-Y) completion=Z
• Quick checks if you don’t see logs
◦ Ensure the logger level allows info/debug: logger.setLevel(logging.INFO) or DEBUG.
◦ Make sure register() is called so the event handler is attached.
◦ Confirm dump_llm_request() is called before the LLM call so the index matches the metrics event timing.
• Optional improvements
◦ If metrics events can arrive out of order, attach an identifier to the request payload and include it in both the dumped file and the metrics event (if the metrics event carries a request id) to reliably correlate.
◦ Write per-call metrics to a file (e.g., append JSON lines) if you want structured post-analysis:
out = self.dump_dir / "llm_token_log.jsonl"
out.write_text(json.dumps({
"call_idx": self._call_idx,
"prompt": prompt,
"prompt_cached": cached,
"completion": completion,
"timestamp": datetime.utcnow().isoformat()
}) + "\n", append=True)
(Adjust to your file-append method.)
If you want, tell me whether metrics sometimes arrive out of order or if you want a sample code snippet to append structured per-call logs to disk.
Sources: Understand and Improve Agent Latency | LiveKit | Understand and Improve Agent Latency | LiveKit | Build Your First AI Voice Agent in Python: Complete Tutorial | LiveKit, with interactive elementsrhythmic-breakfast-40081
04/30/2026, 8:08 PMtall-airline-16756
04/30/2026, 8:08 PMdump_llm_request() increments self._call_idx and writes a JSON file per call with the messages and tools used.
• _on_metrics() receives LLMMetrics and logs prompt, cached, and completion tokens per call using self._call_idx.
• Correlation is possible by matching the call index in the logs to the corresponding llm_call_{idx:03d}.json file.
Recommended small changes (make analysis explicit and robust)
1. Include call_idx in the dumped JSON and in the metrics log line so correlation is explicit:
# in dump_llm_request
payload = {"call_idx": idx, "messages": messages, "tools": tool_dicts}
# in _on_metrics
logger.info(f"[LLM #{self._call_idx}] call_idx={self._call_idx} prompt={prompt} (cached={cached}) completion={completion}")
1. Write a structured per-call token log (JSONL) for easier programmatic analysis:
# append per-call metrics to a JSONL file (open in append mode)
record = {
"call_idx": self._call_idx,
"prompt": prompt, "prompt_cached": cached, "completion": completion,
"timestamp": datetime.utcnow().isoformat()
}
(self.dump_dir / "llm_token_log.jsonl").write_text(json.dumps(record, ensure_ascii=False) + "\n", append=True)
(Use your preferred file-append method.)
1. Optionally annotate each tool entry with an explicit tool_id or name in llm_call_{idx}.json so you can immediately see which functions were present for that call (you already add name in `tool_dicts`; ensure it’s always populated).
2. Verify logging and ordering:
• Ensure register() is called and logger level is INFO/DEBUG.
• If metrics can arrive out of order, include a unique request id (call_idx or UUID) in both the dumped request and the LLM request/metadata so metrics can be reliably matched.
How to analyze after collecting logs
• Parse llm_token_log.jsonl and for each call, open llm_call_{call_idx}.json to get the tool list.
• Aggregate token totals per tool name (e.g., attribute tokens to all tools present in that call or refine by instrumenting tools to report their own token deltas).
If you’d like, I can:
• Provide a ready-to-use code snippet that appends JSONL correctly (with safe file append).
• Show a short Python script to aggregate token usage by tool name from the dumped files.
Which of those would you like next?
, with interactive elementsrhythmic-breakfast-40081
04/30/2026, 8:10 PMtall-airline-16756
04/30/2026, 8:10 PMllm_call_{idx}.json. This makes it trivial to correlate tokens -> tools.
Add these changes to your class:
1) Ensure dump_llm_request writes the call index into the dumped request:
# in dump_llm_request, after computing idx and payload
payload = {"call_idx": idx, "messages": messages, "tools": tool_dicts}
out = self.dump_dir / f"llm_call_{idx:03d}.json"
out.write_text(json.dumps(payload, indent=2, default=str, ensure_ascii=False))
2) Append structured per-call metrics in _on_metrics (use atomic append):
import json
from datetime import datetime
from pathlib import Path
def _append_jsonl(path: Path, record: dict) -> None:
# atomic append: open in append mode and write one JSON line
with path.open("a", encoding="utf-8") as f:
f.write(json.dumps(record, ensure_ascii=False) + "\n")
def _on_metrics(self, ev: Any) -> None:
m = ev.metrics
if not isinstance(m, LLMMetrics):
return
prompt = m.prompt_tokens or 0
cached = getattr(m, "prompt_cached_tokens", 0) or 0
completion = m.completion_tokens or 0
self._totals["prompt"] += prompt
self._totals["cached"] += cached
self._totals["completion"] += completion
# include the same call index used when dumping the request
call_idx = self._call_idx
logger.info(
f"[LLM #{call_idx}] call_idx={call_idx} prompt={prompt} (cached={cached}, fresh={prompt - cached}) completion={completion}"
)
# write structured record for later analysis
record = {
"call_idx": call_idx,
"prompt": prompt,
"prompt_cached": cached,
"completion": completion,
"fresh": prompt - cached,
"timestamp": datetime.utcnow().isoformat() + "Z",
}
_append_jsonl(self.dump_dir / "llm_token_log.jsonl", record)
How to analyze afterwards
• For each JSONL record, open llm_call_{call_idx:03d}.json to see the tools list and map tokens to those tool names.
• Aggregate token totals per tool name (either attribute the full call tokens to all tools present, or refine by instrumenting functions to report per-tool deltas if you need per-tool precision).
If you want, I can:
• Provide a short Python script to parse llm_token_log.jsonl and aggregate tokens by tool name based on the dumped llm_call_*.json files.
• Show how to attach a UUID per request (if metrics arrive out of order) so correlation is robust.
Which would you like next?
, with interactive elements