mirror of
https://github.com/openai/codex.git
synced 2026-04-24 06:35:50 +00:00
feat: memory usage metrics (#12120)
This commit is contained in:
@@ -11,6 +11,7 @@ mod start;
|
||||
mod storage;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub(crate) mod usage;
|
||||
|
||||
/// Starts the memory startup pipeline for eligible root sessions.
|
||||
/// This is the single entrypoint that `codex` uses to trigger memory startup.
|
||||
|
||||
122
codex-rs/core/src/memories/usage.rs
Normal file
122
codex-rs/core/src/memories/usage.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
use crate::is_safe_command::is_known_safe_command;
|
||||
use crate::parse_command::parse_command;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::handlers::unified_exec::ExecCommandArgs;
|
||||
use codex_protocol::models::ShellCommandToolCallParams;
|
||||
use codex_protocol::models::ShellToolCallParams;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const MEMORIES_USAGE_METRIC: &str = "codex.memories.usage";
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MemoriesUsageKind {
|
||||
MemoryMd,
|
||||
MemorySummary,
|
||||
RawMemories,
|
||||
RolloutSummaries,
|
||||
Skills,
|
||||
}
|
||||
|
||||
impl MemoriesUsageKind {
|
||||
fn as_tag(self) -> &'static str {
|
||||
match self {
|
||||
Self::MemoryMd => "memory_md",
|
||||
Self::MemorySummary => "memory_summary",
|
||||
Self::RawMemories => "raw_memories",
|
||||
Self::RolloutSummaries => "rollout_summaries",
|
||||
Self::Skills => "skills",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn emit_metric_for_tool_read(invocation: &ToolInvocation, success: bool) {
|
||||
let kinds = memories_usage_kinds_from_invocation(invocation).await;
|
||||
if kinds.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let success = if success { "true" } else { "false" };
|
||||
for kind in kinds {
|
||||
invocation.turn.otel_manager.counter(
|
||||
MEMORIES_USAGE_METRIC,
|
||||
1,
|
||||
&[
|
||||
("kind", kind.as_tag()),
|
||||
("tool", invocation.tool_name.as_str()),
|
||||
("success", success),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async fn memories_usage_kinds_from_invocation(
|
||||
invocation: &ToolInvocation,
|
||||
) -> Vec<MemoriesUsageKind> {
|
||||
let Some((command, _)) = shell_command_for_invocation(invocation) else {
|
||||
return Vec::new();
|
||||
};
|
||||
if !is_known_safe_command(&command) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let parsed_commands = parse_command(&command);
|
||||
parsed_commands
|
||||
.into_iter()
|
||||
.filter_map(|command| match command {
|
||||
ParsedCommand::Read { path, .. } => get_memory_kind(path.display().to_string()),
|
||||
ParsedCommand::Search { path, .. } => path.and_then(get_memory_kind),
|
||||
ParsedCommand::ListFiles { .. } | ParsedCommand::Unknown { .. } => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn shell_command_for_invocation(invocation: &ToolInvocation) -> Option<(Vec<String>, PathBuf)> {
|
||||
let ToolPayload::Function { arguments } = &invocation.payload else {
|
||||
return None;
|
||||
};
|
||||
|
||||
match invocation.tool_name.as_str() {
|
||||
"shell" => serde_json::from_str::<ShellToolCallParams>(arguments)
|
||||
.ok()
|
||||
.map(|params| (params.command, invocation.turn.resolve_path(params.workdir))),
|
||||
"shell_command" => serde_json::from_str::<ShellCommandToolCallParams>(arguments)
|
||||
.ok()
|
||||
.map(|params| {
|
||||
let command = invocation
|
||||
.session
|
||||
.user_shell()
|
||||
.derive_exec_args(¶ms.command, params.login.unwrap_or(true));
|
||||
(command, invocation.turn.resolve_path(params.workdir))
|
||||
}),
|
||||
"exec_command" => serde_json::from_str::<ExecCommandArgs>(arguments)
|
||||
.ok()
|
||||
.map(|params| {
|
||||
(
|
||||
crate::tools::handlers::unified_exec::get_command(
|
||||
¶ms,
|
||||
invocation.session.user_shell(),
|
||||
),
|
||||
invocation.turn.resolve_path(params.workdir),
|
||||
)
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_memory_kind(path: String) -> Option<MemoriesUsageKind> {
|
||||
if path.contains("memories/MEMORY.md") {
|
||||
Some(MemoriesUsageKind::MemoryMd)
|
||||
} else if path.contains("memories/memory_summary.md") {
|
||||
Some(MemoriesUsageKind::MemorySummary)
|
||||
} else if path.contains("memories/raw_memories.md") {
|
||||
Some(MemoriesUsageKind::RawMemories)
|
||||
} else if path.contains("memories/rollout_summaries/") {
|
||||
Some(MemoriesUsageKind::RolloutSummaries)
|
||||
} else if path.contains("memories/skills/") {
|
||||
Some(MemoriesUsageKind::Skills)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ mod request_user_input;
|
||||
mod search_tool_bm25;
|
||||
mod shell;
|
||||
mod test_sync;
|
||||
mod unified_exec;
|
||||
pub(crate) mod unified_exec;
|
||||
mod view_image;
|
||||
|
||||
pub use plan::PLAN_TOOL;
|
||||
|
||||
@@ -26,10 +26,10 @@ use std::sync::Arc;
|
||||
pub struct UnifiedExecHandler;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ExecCommandArgs {
|
||||
pub(crate) struct ExecCommandArgs {
|
||||
cmd: String,
|
||||
#[serde(default)]
|
||||
workdir: Option<String>,
|
||||
pub(crate) workdir: Option<String>,
|
||||
#[serde(default)]
|
||||
shell: Option<String>,
|
||||
#[serde(default = "default_login")]
|
||||
@@ -238,7 +238,7 @@ impl ToolHandler for UnifiedExecHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_command(args: &ExecCommandArgs, session_shell: Arc<Shell>) -> Vec<String> {
|
||||
pub(crate) fn get_command(args: &ExecCommandArgs, session_shell: Arc<Shell>) -> Vec<String> {
|
||||
let model_shell = args.shell.as_ref().map(|shell_str| {
|
||||
let mut shell = get_shell_by_model_provided_path(&PathBuf::from(shell_str));
|
||||
shell.shell_snapshot = crate::shell::empty_shell_snapshot_receiver();
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::time::Instant;
|
||||
use crate::client_common::tools::ToolSpec;
|
||||
use crate::features::Feature;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::memories::usage::emit_metric_for_tool_read;
|
||||
use crate::protocol::SandboxPolicy;
|
||||
use crate::sandbox_tags::sandbox_tag;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
@@ -173,6 +174,7 @@ impl ToolRegistry {
|
||||
Ok((preview, success)) => (preview.clone(), *success),
|
||||
Err(err) => (err.to_string(), false),
|
||||
};
|
||||
emit_metric_for_tool_read(&invocation, success).await;
|
||||
let hook_abort_error = dispatch_after_tool_use_hook(AfterToolUseHookDispatch {
|
||||
invocation: &invocation,
|
||||
output_preview,
|
||||
|
||||
Reference in New Issue
Block a user