mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Emit plugin ID on MCP tool call analytics events (#27483)
MCP tool-call items already carry the runtime-resolved plugin owner, but the analytics reducer dropped that field. Forwarding the existing value provides direct attribution without downstream server-name inference. ## Summary - emit `plugin_id` on `codex_mcp_tool_call_event` payloads - preserve `null` for MCP calls without a plugin owner - verify the serialized field through the MCP item lifecycle test ## Test - `cd codex-rs && just test -p codex-analytics` - `cd codex-rs && just fix -p codex-analytics` - `cd codex-rs && just fmt`
This commit is contained in:
1 parent
1e5b87b4d7
commit
df9dd22248
3 files changed
+37
-12
No files matched your search
@@ -3863,6 +3863,32 @@ async fn turn_event_counts_completed_tool_items() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let mcp_tool_call_item = |status, duration_ms| ThreadItem::McpToolCall {
|
||||||
|
id: "mcp-1".to_string(),
|
||||||
|
server: "server".to_string(),
|
||||||
|
tool: "search".to_string(),
|
||||||
|
status,
|
||||||
|
arguments: json!({}),
|
||||||
|
mcp_app_resource_uri: None,
|
||||||
|
plugin_id: Some("sample@test".to_string()),
|
||||||
|
result: None,
|
||||||
|
error: None,
|
||||||
|
duration_ms,
|
||||||
|
};
|
||||||
|
reducer
|
||||||
|
.ingest(
|
||||||
|
AnalyticsFact::Notification(Box::new(ServerNotification::ItemStarted(
|
||||||
|
ItemStartedNotification {
|
||||||
|
thread_id: "thread-2".to_string(),
|
||||||
|
turn_id: "turn-2".to_string(),
|
||||||
|
started_at_ms: 998,
|
||||||
|
item: mcp_tool_call_item(McpToolCallStatus::InProgress, None),
|
||||||
|
},
|
||||||
|
))),
|
||||||
|
&mut out,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
let completed_tool_items = vec![
|
let completed_tool_items = vec![
|
||||||
sample_command_execution_item(CommandExecutionStatus::Completed, Some(0), Some(1)),
|
sample_command_execution_item(CommandExecutionStatus::Completed, Some(0), Some(1)),
|
||||||
ThreadItem::FileChange {
|
ThreadItem::FileChange {
|
||||||
@@ -3870,18 +3896,7 @@ async fn turn_event_counts_completed_tool_items() {
|
|||||||
changes: Vec::new(),
|
changes: Vec::new(),
|
||||||
status: PatchApplyStatus::Completed,
|
status: PatchApplyStatus::Completed,
|
||||||
},
|
},
|
||||||
ThreadItem::McpToolCall {
|
mcp_tool_call_item(McpToolCallStatus::Completed, Some(2)),
|
||||||
id: "mcp-1".to_string(),
|
|
||||||
server: "server".to_string(),
|
|
||||||
tool: "search".to_string(),
|
|
||||||
status: McpToolCallStatus::Completed,
|
|
||||||
arguments: json!({}),
|
|
||||||
mcp_app_resource_uri: None,
|
|
||||||
plugin_id: None,
|
|
||||||
result: None,
|
|
||||||
error: None,
|
|
||||||
duration_ms: Some(2),
|
|
||||||
},
|
|
||||||
ThreadItem::DynamicToolCall {
|
ThreadItem::DynamicToolCall {
|
||||||
id: "dynamic-1".to_string(),
|
id: "dynamic-1".to_string(),
|
||||||
namespace: None,
|
namespace: None,
|
||||||
@@ -3939,6 +3954,13 @@ async fn turn_event_counts_completed_tool_items() {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mcp_tool_call_event = out
|
||||||
|
.iter()
|
||||||
|
.find(|event| matches!(event, TrackEventRequest::McpToolCall(_)))
|
||||||
|
.expect("MCP tool call event should be emitted");
|
||||||
|
let payload = serde_json::to_value(mcp_tool_call_event).expect("serialize MCP tool call event");
|
||||||
|
assert_eq!(payload["event_params"]["plugin_id"], json!("sample@test"));
|
||||||
|
|
||||||
reducer
|
reducer
|
||||||
.ingest(
|
.ingest(
|
||||||
AnalyticsFact::Notification(Box::new(sample_turn_completed_notification(
|
AnalyticsFact::Notification(Box::new(sample_turn_completed_notification(
|
||||||
|
|||||||
@@ -633,6 +633,7 @@ pub(crate) struct CodexMcpToolCallEventParams {
|
|||||||
pub(crate) mcp_server_name: String,
|
pub(crate) mcp_server_name: String,
|
||||||
pub(crate) mcp_tool_name: String,
|
pub(crate) mcp_tool_name: String,
|
||||||
pub(crate) mcp_error_present: bool,
|
pub(crate) mcp_error_present: bool,
|
||||||
|
pub(crate) plugin_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
|||||||
@@ -1751,6 +1751,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
|
|||||||
status,
|
status,
|
||||||
error,
|
error,
|
||||||
duration_ms,
|
duration_ms,
|
||||||
|
plugin_id,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let (terminal_status, failure_kind) = mcp_tool_call_outcome(status)?;
|
let (terminal_status, failure_kind) = mcp_tool_call_outcome(status)?;
|
||||||
@@ -1780,6 +1781,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
|
|||||||
mcp_server_name: server.clone(),
|
mcp_server_name: server.clone(),
|
||||||
mcp_tool_name: tool.clone(),
|
mcp_tool_name: tool.clone(),
|
||||||
mcp_error_present: error.is_some(),
|
mcp_error_present: error.is_some(),
|
||||||
|
plugin_id: plugin_id.clone(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|||||||
Reference in new issue
Block a user