mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
[codex-analytics] guardian review TTFT plumbing and emission (#17696)
## Why Guardian analytics includes time-to-first-token, but the Guardian reviewer runs as a normal Codex session and `TurnCompleteEvent` did not expose TTFT. The timing needs to flow through the standard turn-completion protocol so Guardian review analytics can consume the same value as the rest of the session machinery. ## What changed Adds optional `time_to_first_token_ms` to `TurnCompleteEvent` and populates it from `TurnTiming`. The value is carried through app-server thread history, rollout reconstruction, TUI/app-server adapters, and Guardian review session handling. Guardian review analytics now captures TTFT from the reviewer turn-complete event when available. Existing tests and fixtures are updated to set the new optional field to `None` where TTFT is not relevant. ## Verification - `cargo clippy -p codex-tui --tests -- -D warnings` - `cargo clippy -p codex-core --lib --tests -- -D warnings` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/17696). * __->__ #17696 * #17695 * #17693 * #18278 * #18953
This commit is contained in:
1 parent
37aadeaa13
commit
213b17b7a3
18 files changed
+114
-6
No files matched your search
@@ -74,6 +74,13 @@ impl TurnTimingState {
|
||||
(completed_at, duration_ms)
|
||||
}
|
||||
|
||||
pub(crate) async fn time_to_first_token_ms(&self) -> Option<i64> {
|
||||
let state = self.state.lock().await;
|
||||
state
|
||||
.time_to_first_token()
|
||||
.map(|duration| i64::try_from(duration.as_millis()).unwrap_or(i64::MAX))
|
||||
}
|
||||
|
||||
pub(crate) async fn record_ttft_for_response_event(
|
||||
&self,
|
||||
event: &ResponseEvent,
|
||||
@@ -102,14 +109,17 @@ fn now_unix_timestamp_secs() -> i64 {
|
||||
}
|
||||
|
||||
impl TurnTimingStateInner {
|
||||
fn time_to_first_token(&self) -> Option<Duration> {
|
||||
Some(self.first_token_at?.duration_since(self.started_at?))
|
||||
}
|
||||
|
||||
fn record_turn_ttft(&mut self) -> Option<Duration> {
|
||||
if self.first_token_at.is_some() {
|
||||
return None;
|
||||
}
|
||||
let started_at = self.started_at?;
|
||||
let first_token_at = Instant::now();
|
||||
self.first_token_at = Some(first_token_at);
|
||||
Some(first_token_at.duration_since(started_at))
|
||||
self.started_at?;
|
||||
self.first_token_at = Some(Instant::now());
|
||||
self.time_to_first_token()
|
||||
}
|
||||
|
||||
fn record_turn_ttfm(&mut self) -> Option<Duration> {
|
||||
|
||||
Reference in new issue
Block a user