From e07eaff0d32caaec47cc4b0616d1b32c086e904f Mon Sep 17 00:00:00 2001 From: jif-oai Date: Wed, 4 Mar 2026 11:25:58 +0000 Subject: [PATCH] feat: add metric for per-turn tool count and add tmp_mem flag (#13456) --- codex-rs/core/src/state/turn.rs | 1 + codex-rs/core/src/tasks/mod.rs | 27 ++++++++++++++++++++++----- codex-rs/core/src/tools/registry.rs | 8 ++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/codex-rs/core/src/state/turn.rs b/codex-rs/core/src/state/turn.rs index 9366880aca..28ae8fec65 100644 --- a/codex-rs/core/src/state/turn.rs +++ b/codex-rs/core/src/state/turn.rs @@ -74,6 +74,7 @@ pub(crate) struct TurnState { pending_user_input: HashMap>, pending_dynamic_tools: HashMap>, pending_input: Vec, + pub(crate) tool_calls: u64, pub(crate) token_usage_at_turn_start: TokenUsage, } diff --git a/codex-rs/core/src/tasks/mod.rs b/codex-rs/core/src/tasks/mod.rs index a814d36dcc..301d25b6d0 100644 --- a/codex-rs/core/src/tasks/mod.rs +++ b/codex-rs/core/src/tasks/mod.rs @@ -38,6 +38,7 @@ use codex_protocol::models::ResponseItem; use codex_protocol::protocol::RolloutItem; use codex_protocol::user_input::UserInput; +use crate::features::Feature; pub(crate) use compact::CompactTask; pub(crate) use ghost_snapshot::GhostSnapshotTask; pub(crate) use regular::RegularTask; @@ -200,11 +201,13 @@ impl Session { let mut pending_input = Vec::::new(); let mut should_clear_active_turn = false; let mut token_usage_at_turn_start = None; + let mut turn_tool_calls = 0_u64; if let Some(at) = active.as_mut() && at.remove_task(&turn_context.sub_id) { let mut ts = at.turn_state.lock().await; pending_input = ts.take_pending_input(); + turn_tool_calls = ts.tool_calls; token_usage_at_turn_start = Some(ts.token_usage_at_turn_start.clone()); should_clear_active_turn = true; } @@ -239,6 +242,20 @@ impl Session { } // Emit token usage metrics. if let Some(token_usage_at_turn_start) = token_usage_at_turn_start { + // TODO(jif): drop this + let tmp_mem = ( + "tmp_mem_enabled", + if self.enabled(Feature::MemoryTool) { + "true" + } else { + "false" + }, + ); + self.services.otel_manager.histogram( + "codex.turn.tool.call", + i64::try_from(turn_tool_calls).unwrap_or(i64::MAX), + &[tmp_mem], + ); let total_token_usage = self.total_token_usage().await.unwrap_or_default(); let turn_token_usage = crate::protocol::TokenUsage { input_tokens: (total_token_usage.input_tokens @@ -260,27 +277,27 @@ impl Session { self.services.otel_manager.histogram( "codex.turn.token_usage", turn_token_usage.total_tokens, - &[("token_type", "total")], + &[("token_type", "total"), tmp_mem], ); self.services.otel_manager.histogram( "codex.turn.token_usage", turn_token_usage.input_tokens, - &[("token_type", "input")], + &[("token_type", "input"), tmp_mem], ); self.services.otel_manager.histogram( "codex.turn.token_usage", turn_token_usage.cached_input(), - &[("token_type", "cached_input")], + &[("token_type", "cached_input"), tmp_mem], ); self.services.otel_manager.histogram( "codex.turn.token_usage", turn_token_usage.output_tokens, - &[("token_type", "output")], + &[("token_type", "output"), tmp_mem], ); self.services.otel_manager.histogram( "codex.turn.token_usage", turn_token_usage.reasoning_output_tokens, - &[("token_type", "reasoning_output")], + &[("token_type", "reasoning_output"), tmp_mem], ); } let event = EventMsg::TurnComplete(TurnCompleteEvent { diff --git a/codex-rs/core/src/tools/registry.rs b/codex-rs/core/src/tools/registry.rs index 3c021cc582..77d3c4150b 100644 --- a/codex-rs/core/src/tools/registry.rs +++ b/codex-rs/core/src/tools/registry.rs @@ -118,6 +118,14 @@ impl ToolRegistry { let mcp_server_ref = mcp_server.as_deref(); let mcp_server_origin_ref = mcp_server_origin.as_deref(); + { + let mut active = invocation.session.active_turn.lock().await; + if let Some(active_turn) = active.as_mut() { + let mut turn_state = active_turn.turn_state.lock().await; + turn_state.tool_calls = turn_state.tool_calls.saturating_add(1); + } + } + let handler = match self.handler(tool_name.as_ref()) { Some(handler) => handler, None => {