mirror of
https://github.com/openai/codex.git
synced 2026-08-23 13:09:46 +00:00
Log plugin install failure subtypes (#31518)
## Summary - classify plugin store and remote bundle I/O failures by privacy-safe operation context - include the normalized `sub_error_type` in structured plugin-install failure warnings - leave analytics events and schemas unchanged ## Why Top-level error types such as `store_io` collapse multiple filesystem operations, making logs harder to diagnose. The subtype identifies the failed operation without logging paths or new exception details. ## Impact Plugin-install warning logs gain an optional normalized subtype. Analytics payloads, app-server APIs, and stored data are unchanged. ## Validation - `just fmt` - `just test -p codex-core-plugins -p codex-app-server` (1,235 passed; 14 failed and 6 timed out because local `sandbox-exec` was denied, `test_stdio_server` was unavailable, or user-level skill fixtures were loaded)
This commit is contained in:
committed by
GitHub
parent
f17a57b7d5
commit
1ee0e9a949
@@ -1548,6 +1548,7 @@ impl PluginRequestProcessor {
|
||||
&remote_marketplace_name,
|
||||
/*plugin_id*/ None,
|
||||
error_type,
|
||||
/*sub_error_type*/ None,
|
||||
err.to_string(),
|
||||
);
|
||||
remote_plugin_catalog_error_to_jsonrpc(
|
||||
@@ -1591,11 +1592,13 @@ impl PluginRequestProcessor {
|
||||
)
|
||||
.map_err(|err| {
|
||||
let error_type = remote_plugin_bundle_install_error_type(&err);
|
||||
let sub_error_type = err.sub_error_type();
|
||||
self.track_plugin_install_failed_for_remote_plugin(
|
||||
&remote_plugin_id,
|
||||
&actual_remote_marketplace_name,
|
||||
Some(&resolved_plugin_id),
|
||||
error_type,
|
||||
sub_error_type,
|
||||
err.to_string(),
|
||||
);
|
||||
remote_plugin_bundle_install_error_to_jsonrpc(err)
|
||||
@@ -1608,11 +1611,13 @@ impl PluginRequestProcessor {
|
||||
.await
|
||||
.map_err(|err| {
|
||||
let error_type = remote_plugin_bundle_install_error_type(&err);
|
||||
let sub_error_type = err.sub_error_type();
|
||||
self.track_plugin_install_failed_for_remote_plugin(
|
||||
&remote_plugin_id,
|
||||
&actual_remote_marketplace_name,
|
||||
Some(&resolved_plugin_id),
|
||||
error_type,
|
||||
sub_error_type,
|
||||
err.to_string(),
|
||||
);
|
||||
remote_plugin_bundle_install_error_to_jsonrpc(err)
|
||||
@@ -1635,6 +1640,7 @@ impl PluginRequestProcessor {
|
||||
&actual_remote_marketplace_name,
|
||||
Some(&result.plugin_id),
|
||||
error_type,
|
||||
/*sub_error_type*/ None,
|
||||
err.to_string(),
|
||||
);
|
||||
remote_plugin_catalog_error_to_jsonrpc(err, "install remote plugin")
|
||||
@@ -1732,12 +1738,14 @@ impl PluginRequestProcessor {
|
||||
marketplace_name: &str,
|
||||
plugin_id: Option<&PluginId>,
|
||||
error_type: &'static str,
|
||||
sub_error_type: Option<String>,
|
||||
error_message: String,
|
||||
) {
|
||||
tracing::warn!(
|
||||
remote_plugin_id = %remote_plugin_id,
|
||||
marketplace_name = %marketplace_name,
|
||||
error_type = %error_type,
|
||||
sub_error_type = sub_error_type.as_deref(),
|
||||
error = %error_message,
|
||||
"remote plugin install failed"
|
||||
);
|
||||
|
||||
@@ -1283,6 +1283,7 @@ impl PluginsManager {
|
||||
self.track_plugin_install_failed(
|
||||
&plugin_id,
|
||||
plugin_install_error_type(&err),
|
||||
plugin_install_sub_error_type(&err),
|
||||
err.to_string(),
|
||||
);
|
||||
Err(err)
|
||||
@@ -1345,6 +1346,7 @@ impl PluginsManager {
|
||||
self.track_plugin_install_failed(
|
||||
&resolved.plugin_id,
|
||||
plugin_install_error_type(&err),
|
||||
plugin_install_sub_error_type(&err),
|
||||
err.to_string(),
|
||||
);
|
||||
return Err(err);
|
||||
@@ -1356,6 +1358,7 @@ impl PluginsManager {
|
||||
self.track_plugin_install_failed(
|
||||
&plugin_id,
|
||||
plugin_install_error_type(&err),
|
||||
plugin_install_sub_error_type(&err),
|
||||
err.to_string(),
|
||||
);
|
||||
Err(err)
|
||||
@@ -1383,6 +1386,7 @@ impl PluginsManager {
|
||||
self.track_plugin_install_failed(
|
||||
&plugin_id,
|
||||
marketplace_error_type(err),
|
||||
/*sub_error_type*/ None,
|
||||
err.to_string(),
|
||||
);
|
||||
} else {
|
||||
@@ -1398,11 +1402,13 @@ impl PluginsManager {
|
||||
&self,
|
||||
plugin_id: &PluginId,
|
||||
error_type: &'static str,
|
||||
sub_error_type: Option<String>,
|
||||
error_message: String,
|
||||
) {
|
||||
tracing::warn!(
|
||||
plugin_id = %plugin_id.as_key(),
|
||||
error_type = %error_type,
|
||||
sub_error_type = sub_error_type.as_deref(),
|
||||
error = %error_message,
|
||||
"plugin install failed"
|
||||
);
|
||||
@@ -2674,6 +2680,16 @@ fn plugin_install_error_type(err: &PluginInstallError) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn plugin_install_sub_error_type(err: &PluginInstallError) -> Option<String> {
|
||||
match err {
|
||||
PluginInstallError::Store(err) => err.sub_error_type(),
|
||||
PluginInstallError::Marketplace(_)
|
||||
| PluginInstallError::Remote(_)
|
||||
| PluginInstallError::Config(_)
|
||||
| PluginInstallError::Join(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn marketplace_error_type(err: &MarketplaceError) -> &'static str {
|
||||
match err {
|
||||
MarketplaceError::Io { .. } => "marketplace_io",
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::remote::REMOTE_GLOBAL_MARKETPLACE_NAME;
|
||||
use crate::store::PluginInstallResult;
|
||||
use crate::store::PluginStore;
|
||||
use crate::store::PluginStoreError;
|
||||
use crate::store::error_context_sub_error_type;
|
||||
use crate::store::validate_plugin_version_segment;
|
||||
use codex_login::default_client::build_reqwest_client;
|
||||
use codex_plugin::PluginId;
|
||||
@@ -132,6 +133,26 @@ impl RemotePluginBundleInstallError {
|
||||
fn io(context: &'static str, source: io::Error) -> Self {
|
||||
Self::Io { context, source }
|
||||
}
|
||||
|
||||
pub fn sub_error_type(&self) -> Option<String> {
|
||||
match self {
|
||||
Self::Io { context, .. } => Some(error_context_sub_error_type(context)),
|
||||
Self::Store(err) => err.sub_error_type(),
|
||||
Self::MissingReleaseVersion { .. }
|
||||
| Self::InvalidReleaseVersion { .. }
|
||||
| Self::MissingBundleDownloadUrl { .. }
|
||||
| Self::InvalidBundleDownloadUrl { .. }
|
||||
| Self::UnsupportedBundleDownloadUrlScheme { .. }
|
||||
| Self::InvalidPluginId { .. }
|
||||
| Self::DownloadRequest { .. }
|
||||
| Self::DownloadStatus { .. }
|
||||
| Self::DownloadBody { .. }
|
||||
| Self::DownloadTooLarge { .. }
|
||||
| Self::UnsupportedBundleDownloadFinalUrl { .. }
|
||||
| Self::ExtractedBundleTooLarge { .. }
|
||||
| Self::InvalidBundle(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_remote_plugin_bundle(
|
||||
|
||||
@@ -365,6 +365,17 @@ impl PluginStoreError {
|
||||
fn io(context: &'static str, source: io::Error) -> Self {
|
||||
Self::Io { context, source }
|
||||
}
|
||||
|
||||
pub(crate) fn sub_error_type(&self) -> Option<String> {
|
||||
match self {
|
||||
Self::Io { context, .. } => Some(error_context_sub_error_type(context)),
|
||||
Self::Invalid(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn error_context_sub_error_type(context: &str) -> String {
|
||||
context.to_ascii_lowercase().replace(' ', "_")
|
||||
}
|
||||
|
||||
pub fn plugin_version_for_source(source_path: &Path) -> Result<String, PluginStoreError> {
|
||||
|
||||
Reference in New Issue
Block a user