mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[codex] add connector runtime latency metrics (#31319)
## Summary - measure successful legacy `app/list` latency with `codex.apps.installed.duration_ms`, segmented by `path=legacy` and `reload` - measure successful host-owned `codex_apps` startup and explicit refresh latency with `codex.apps.refresh.duration_ms` - add the refresh trigger to successful `codex.mcp.tools.fetch_uncached.duration_ms` samples for `codex_apps` without changing other MCP-server samples ## Why This establishes a small latency baseline for the current connector path before `ConnectorRuntimeManager`, `app/installed`, and `app/read` land. Error-rate and broader runtime-state instrumentation are intentionally deferred. This is telemetry-only and does not change connector behavior. ## Validation - `just test -p codex-mcp` (94 passed) - `just test -p codex-app-server list_apps` (13 passed) - `just fix -p codex-mcp` - `just fix -p codex-app-server` - `just fmt` - `git diff --check`
This commit is contained in:
1 parent
78df1237d1
commit
1345c16dd7
3 files changed
+68
-21
No files matched your search
@@ -82,6 +82,7 @@ pub const OPENAI_FORM_CAPABILITY: &str = "openai/form";
|
||||
pub(crate) const MCP_TOOLS_LIST_DURATION_METRIC: &str = "codex.mcp.tools.list.duration_ms";
|
||||
pub(crate) const MCP_TOOLS_FETCH_UNCACHED_DURATION_METRIC: &str =
|
||||
"codex.mcp.tools.fetch_uncached.duration_ms";
|
||||
pub(crate) const CODEX_APPS_REFRESH_DURATION_METRIC: &str = "codex.apps.refresh.duration_ms";
|
||||
pub(crate) const DEFAULT_STARTUP_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
pub(crate) const DEFAULT_TOOL_TIMEOUT: Duration = Duration::from_secs(300);
|
||||
|
||||
@@ -304,6 +305,7 @@ impl ManagedClientStartup {
|
||||
.unwrap_or_default();
|
||||
let cancel_token_for_fut = cancel_token;
|
||||
async move {
|
||||
let refresh_start = is_codex_apps_mcp_server.then(Instant::now);
|
||||
let outcome = match async {
|
||||
if let Err(error) = validate_mcp_server_name(&server_name) {
|
||||
return Err(error.into());
|
||||
@@ -349,6 +351,15 @@ impl ManagedClientStartup {
|
||||
Ok(result) => result,
|
||||
Err(CancelErr::Cancelled) => Err(StartupOutcomeError::Cancelled),
|
||||
};
|
||||
if outcome.is_ok()
|
||||
&& let Some(refresh_start) = refresh_start
|
||||
{
|
||||
emit_duration(
|
||||
CODEX_APPS_REFRESH_DURATION_METRIC,
|
||||
refresh_start.elapsed(),
|
||||
&[("path", "legacy"), ("trigger", "initial")],
|
||||
);
|
||||
}
|
||||
|
||||
startup_complete.store(true, Ordering::Release);
|
||||
outcome
|
||||
@@ -564,10 +575,12 @@ impl From<anyhow::Error> for StartupOutcomeError {
|
||||
pub(crate) async fn list_tools_for_client_uncached(
|
||||
server_name: &str,
|
||||
is_codex_apps_mcp_server: bool,
|
||||
codex_apps_refresh_trigger: &'static str,
|
||||
client: &Arc<RmcpClient>,
|
||||
timeout: Option<Duration>,
|
||||
server_instructions: Option<&str>,
|
||||
) -> Result<Vec<ToolInfo>> {
|
||||
let fetch_start = Instant::now();
|
||||
let resp = client
|
||||
.list_tools_with_connector_ids(/*params*/ None, timeout)
|
||||
.await?;
|
||||
@@ -583,6 +596,19 @@ pub(crate) async fn list_tools_for_client_uncached(
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
if is_codex_apps_mcp_server {
|
||||
emit_duration(
|
||||
MCP_TOOLS_FETCH_UNCACHED_DURATION_METRIC,
|
||||
fetch_start.elapsed(),
|
||||
&[("trigger", codex_apps_refresh_trigger)],
|
||||
);
|
||||
} else {
|
||||
emit_duration(
|
||||
MCP_TOOLS_FETCH_UNCACHED_DURATION_METRIC,
|
||||
fetch_start.elapsed(),
|
||||
&[],
|
||||
);
|
||||
}
|
||||
Ok(tools)
|
||||
}
|
||||
|
||||
@@ -820,24 +846,19 @@ async fn start_server_task(
|
||||
.and_then(|exp| exp.get(MCP_SANDBOX_STATE_META_CAPABILITY))
|
||||
.is_some();
|
||||
let list_start = Instant::now();
|
||||
let fetch_start = Instant::now();
|
||||
let fetch_ticket = codex_apps_tools_cache_context
|
||||
.as_ref()
|
||||
.map(|cache_context| cache_context.begin_fetch(CodexAppsToolsFetchSource::Startup));
|
||||
let tools = list_tools_for_client_uncached(
|
||||
&server_name,
|
||||
is_codex_apps_mcp_server,
|
||||
/*codex_apps_refresh_trigger*/ "initial",
|
||||
&client,
|
||||
startup_timeout,
|
||||
initialize_result.instructions.as_deref(),
|
||||
)
|
||||
.await
|
||||
.map_err(StartupOutcomeError::from)?;
|
||||
emit_duration(
|
||||
MCP_TOOLS_FETCH_UNCACHED_DURATION_METRIC,
|
||||
fetch_start.elapsed(),
|
||||
&[],
|
||||
);
|
||||
let server_info = mcp_server_info_from_implementation(initialize_result.server_info);
|
||||
let tools = match (codex_apps_tools_cache_context.as_ref(), fetch_ticket) {
|
||||
(Some(cache_context), Some(fetch_ticket)) => {
|
||||
|
||||
Reference in new issue
Block a user