steep-balloon-41261
02/21/2026, 8:43 AMtall-airline-16756
02/21/2026, 8:43 AMtall-airline-16756
02/21/2026, 8:43 AMreport.duration is not always populated.
Short answer
• duration is only set when both the session start and end timestamps are recorded. If the session ends abnormally or teardown completes before the end timestamp is captured, duration will be empty.
Why this happens (common causes)
• Abrupt termination: an unhandled exception, process kill, or forced shutdown can prevent the session end timestamp from being recorded.
• Early shutdown order / race condition: your shutdown callback may run before the session lifecycle finishes collecting metrics or before the MetricsCollectedEvent fires.
• Custom teardown bypass: custom shutdown logic that skips normal cleanup can prevent the end-time being written.
• Session never fully initialized: if the session never reached a “started” state (start timestamp missing), there’s nothing to pair with an end timestamp.
What to check / quick debugging steps
1. Add logs for start and end timestamps:
◦ Log the session start time when the session begins and log session end time during shutdown so you can confirm both are present.
1. Verify the metrics event:
◦ Confirm the MetricsCollectedEvent (or equivalent) fires before shutdown and that usageCollector.getSummary() contains expected values.
1. Check shutdown ordering:
◦ Ensure ctx.makeSessionReport(session) runs after the session has fully started and before any shutdown routines that remove timestamps or stop metrics collection.
1. Look for exceptions or early exits:
◦ Inspect your logs for errors or exceptions prior to shutdown which might short-circuit normal teardown.
1. Reproduce with a controlled shutdown:
◦ Instrument a normal, clean shutdown path (no forced kills) and verify duration is populated. Then compare with failing runs to identify differences.
If you’d like, I can help further — please share:
• Whether you see start and/or end timestamps in your logs.
• Any errors or stack traces around shutdown.
• Whether shutdowns that produce no duration correspond to crashes/forced kills or to graceful shutdowns.
I can then suggest targeted fixes (ordering changes, retrying metrics collection before shutdown, or adding guards to ensure end timestamps are recorded).
Sources: Agents (Python) | livekit/livekit_composite | DeepWiki | Build a multilingual voice agent that automatically switches languages | Li... | Redacting PII from agent logs and transcripts | LiveKit | How to implement call greeting retries in voice agents | LiveKittall-airline-16756
02/21/2026, 8:51 AMduration to be populated.
Short answer
• You don’t need to flip a separate flag to enable duration. It’s calculated from the session start and end timestamps, so it will only appear when both timestamps are recorded (i.e., when the session lifecycle completes normally).
Why you’re seeing usage metrics but no duration
• Component-level metrics like sttAudioDurationMs, llmPromptTokens, and ttsCharactersCount are being collected independently and can be present even if the session end timestamp is missing.
• duration is missing because the session end timestamp wasn’t captured (for example: the session didn’t emit a proper end/close event, the process crashed or was killed before cleanup, or there’s a race where your shutdown runs before lifecycle completion).
What to check next (quick checklist)
1. Confirm session start and end logs
◦ Log the exact session start time and the session end time in your code to verify whether the end timestamp is getting written.
1. Ensure proper session termination
◦ Make sure sessions call their normal end/close path (e.g., session.close() or the equivalent) and that participants leave normally.
1. Verify metrics/metrics-collected ordering
◦ Ensure MetricsCollectedEvent (or other metrics-finalization step) fires before your shutdown callback runs.
1. Look for crashes or forced kills
◦ Check for unhandled exceptions, process terminations, or container restarts that could cut off normal teardown.
1. SDK version & observability
◦ duration is part of standard session metadata. Confirm you’re on a current Agent SDK version and that observability is enabled for your project so lifecycle events are recorded.
Helpful debugging steps you can add right now
• Add explicit logging around lifecycle events:
◦ Log when the session starts, when you receive the metrics-collected event, and when your shutdown callback runs.
• Temporarily delay shutdown in a controlled run to ensure metrics collection completes, e.g. wait a few seconds after getSummary() before exiting.
• If you have separate shutdown logic, call ctx.makeSessionReport(session) only after you’ve confirmed the end timestamp exists.
If you want, share any of the following and I’ll help narrow it down:
• A short snippet showing where you call start/close for the session and where your shutdown callback runs.
• Logs that include the session start, metrics-collected, and shutdown timestamps (if present).
• Whether the cases with missing duration are graceful shutdowns or crashes/forced kills.
I can then point out any ordering changes or small code guards to ensure the end timestamp is captured before the process exits.
Sources: Agents (Python) | livekit/livekit_composite | DeepWiki | xAI Grok Voice Agent API plugin | LiveKit Documentation | Where to find your Agent Logs | LiveKittall-airline-16756
02/21/2026, 8:53 AMduration can be computed.
What you want to verify
• There are two timestamps: session start and session end. duration is computed only if both exist.
• Confirming the end timestamp means: (A) the session emitted its end/close event, and (B) that timestamp was recorded before your report is generated.
Steps to confirm the end timestamp exists
1) Log lifecycle events (start, metrics-collected, end)
• Add logs at the exact points the session starts, when metrics are finalized, and when the session ends. This shows ordering and whether the end event happened.
Example (Node-like pseudocode — adapt to your language):
ctx.on('session_start', (session) => {
<http://logger.info|logger.info>(`session_start: ${session.id} ts=${Date.now()}`);
});
ctx.on('metrics_collected', (session, metrics) => {
<http://logger.info|logger.info>(`metrics_collected: ${session.id} ts=${Date.now()} metrics=${JSON.stringify(metrics)}`);
});
ctx.on('session_end', (session) => {
<http://logger.info|logger.info>(`session_end: ${session.id} ts=${Date.now()}`);
});
2) Inspect the SessionReport fields directly before you return/exit
• Call ctx.makeSessionReport(session) and log the report object. Check for startTimestamp, endTimestamp, and duration fields (field names may vary; log the whole report).
Example:
const report = ctx.makeSessionReport(session);
<http://logger.info|logger.info>(`Report raw: ${JSON.stringify(report)}`);
<http://logger.info|logger.info>(`start: ${report.startTimestamp}, end: ${report.endTimestamp}, duration: ${report.duration}`);
3) Add defensive checks and a short delay (for race conditions)
• If the end timestamp is sometimes missing because metrics are still being finalized, add a short retry/delay before creating the report to allow final events to arrive.
Example:
// simple retry
for (let i = 0; i < 3; i++) {
const report = ctx.makeSessionReport(session);
if (report.endTimestamp) {
<http://logger.info|logger.info>('end timestamp found');
break;
}
await sleep(500); // wait 500ms then try again
}
4) Search your logs for the session ID
• If your system logs a session id at start/end, search for that id and confirm there’s a line showing the session end timestamp. If you only find start but no end, the end event wasn’t recorded.
5) Check for abrupt termination / exceptions
• If your process crashes or container is killed, the end timestamp won’t be recorded. Look for error logs, uncaught exceptions, SIGTERM/SIGKILL events, or container restarts around the missing-duration runs.
6) Verify metrics-collected event timing vs. shutdown callback
• Ensure your shutdown callback doesn’t run before the metrics-collected (or equivalent) event. Log both and verify the metrics-collected log appears before your shutdown callback runs.
If you prefer, I can help interpret your logs
• Paste a few lines showing:
◦ the session start log,
◦ any metrics_collected/usage log you already have,
◦ and the shutdown/report logs.
I’ll point out whether the end timestamp was recorded and where the ordering issue might be.
Next steps I can help with
• Show exact code to add retries or wait-for-metrics before calling ctx.makeSessionReport.
• Suggest changes to shutdown ordering so report generation runs after metrics finalize.
• Help identify crash/kill signatures in your logs if you share them.