mirror of
https://github.com/openai/codex.git
synced 2026-04-30 11:21:34 +03:00
Add MCP server context to otel tool_result logs (#12267)
Summary - capture the origin for each configured MCP server and expose it via the connection manager - plumb MCP server name/origin into tool logging and emit codex.tool_result events with those fields - add unit coverage for origin parsing and extend OTEL tests to assert empty MCP fields for non-MCP tools - currently not logging full urls or url paths to prevent logging potentially sensitive data Testing - Not run (not requested)
This commit is contained in:
@@ -32,6 +32,64 @@ use tracing_test::traced_test;
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_test::internal::MockWriter;
|
||||
|
||||
fn extract_log_field(line: &str, key: &str) -> Option<String> {
|
||||
let quoted_prefix = format!("{key}=\"");
|
||||
if let Some(start) = line.find("ed_prefix) {
|
||||
let value_start = start + quoted_prefix.len();
|
||||
if let Some(end_rel) = line[value_start..].find('"') {
|
||||
return Some(line[value_start..value_start + end_rel].to_string());
|
||||
}
|
||||
}
|
||||
|
||||
let bare_prefix = format!("{key}=");
|
||||
for token in line.split_whitespace() {
|
||||
let trimmed = token.trim_end_matches(',');
|
||||
if let Some(value) = trimmed.strip_prefix(&bare_prefix) {
|
||||
return Some(value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn assert_empty_mcp_tool_fields(line: &str) -> Result<(), String> {
|
||||
let mcp_server = extract_log_field(line, "mcp_server")
|
||||
.ok_or_else(|| "missing mcp_server field".to_string())?;
|
||||
if !mcp_server.is_empty() {
|
||||
return Err(format!("expected empty mcp_server, got {mcp_server}"));
|
||||
}
|
||||
|
||||
let mcp_server_origin = extract_log_field(line, "mcp_server_origin")
|
||||
.ok_or_else(|| "missing mcp_server_origin field".to_string())?;
|
||||
if !mcp_server_origin.is_empty() {
|
||||
return Err(format!(
|
||||
"expected empty mcp_server_origin, got {mcp_server_origin}"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_log_field_handles_empty_bare_values() {
|
||||
let line = "event.name=\"codex.tool_result\" mcp_server= mcp_server_origin=";
|
||||
assert_eq!(extract_log_field(line, "mcp_server"), Some(String::new()));
|
||||
assert_eq!(
|
||||
extract_log_field(line, "mcp_server_origin"),
|
||||
Some(String::new())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_log_field_does_not_confuse_similar_keys() {
|
||||
let line = "event.name=\"codex.tool_result\" mcp_server_origin=stdio";
|
||||
assert_eq!(extract_log_field(line, "mcp_server"), None);
|
||||
assert_eq!(
|
||||
extract_log_field(line, "mcp_server_origin"),
|
||||
Some("stdio".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[traced_test]
|
||||
async fn responses_api_emits_api_request_event() {
|
||||
@@ -687,6 +745,7 @@ async fn handle_response_item_records_tool_result_for_custom_tool_call() {
|
||||
if !line.contains("success=false") {
|
||||
return Err("missing success field".to_string());
|
||||
}
|
||||
assert_empty_mcp_tool_fields(line)?;
|
||||
|
||||
Ok(())
|
||||
});
|
||||
@@ -756,6 +815,7 @@ async fn handle_response_item_records_tool_result_for_function_call() {
|
||||
if !line.contains("success=false") {
|
||||
return Err("missing success field".to_string());
|
||||
}
|
||||
assert_empty_mcp_tool_fields(line)?;
|
||||
|
||||
Ok(())
|
||||
});
|
||||
@@ -828,6 +888,7 @@ async fn handle_response_item_records_tool_result_for_local_shell_missing_ids()
|
||||
if !line.contains("success=false") {
|
||||
return Err("missing success field".to_string());
|
||||
}
|
||||
assert_empty_mcp_tool_fields(line)?;
|
||||
|
||||
Ok(())
|
||||
});
|
||||
@@ -899,6 +960,7 @@ async fn handle_response_item_records_tool_result_for_local_shell_call() {
|
||||
if !line.contains("success=false") {
|
||||
return Err("missing success field".to_string());
|
||||
}
|
||||
assert_empty_mcp_tool_fields(line)?;
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user