mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +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:
1 parent
f17a57b7d5
commit
1ee0e9a949
4 files changed
+56
No files matched your search
@@ -1548,6 +1548,7 @@ impl PluginRequestProcessor {
|
|||||||
&remote_marketplace_name,
|
&remote_marketplace_name,
|
||||||
/*plugin_id*/ None,
|
/*plugin_id*/ None,
|
||||||
error_type,
|
error_type,
|
||||||
|
/*sub_error_type*/ None,
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
remote_plugin_catalog_error_to_jsonrpc(
|
remote_plugin_catalog_error_to_jsonrpc(
|
||||||
@@ -1591,11 +1592,13 @@ impl PluginRequestProcessor {
|
|||||||
)
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
let error_type = remote_plugin_bundle_install_error_type(&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(
|
self.track_plugin_install_failed_for_remote_plugin(
|
||||||
&remote_plugin_id,
|
&remote_plugin_id,
|
||||||
&actual_remote_marketplace_name,
|
&actual_remote_marketplace_name,
|
||||||
Some(&resolved_plugin_id),
|
Some(&resolved_plugin_id),
|
||||||
error_type,
|
error_type,
|
||||||
|
sub_error_type,
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
remote_plugin_bundle_install_error_to_jsonrpc(err)
|
remote_plugin_bundle_install_error_to_jsonrpc(err)
|
||||||
@@ -1608,11 +1611,13 @@ impl PluginRequestProcessor {
|
|||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
let error_type = remote_plugin_bundle_install_error_type(&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(
|
self.track_plugin_install_failed_for_remote_plugin(
|
||||||
&remote_plugin_id,
|
&remote_plugin_id,
|
||||||
&actual_remote_marketplace_name,
|
&actual_remote_marketplace_name,
|
||||||
Some(&resolved_plugin_id),
|
Some(&resolved_plugin_id),
|
||||||
error_type,
|
error_type,
|
||||||
|
sub_error_type,
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
remote_plugin_bundle_install_error_to_jsonrpc(err)
|
remote_plugin_bundle_install_error_to_jsonrpc(err)
|
||||||
@@ -1635,6 +1640,7 @@ impl PluginRequestProcessor {
|
|||||||
&actual_remote_marketplace_name,
|
&actual_remote_marketplace_name,
|
||||||
Some(&result.plugin_id),
|
Some(&result.plugin_id),
|
||||||
error_type,
|
error_type,
|
||||||
|
/*sub_error_type*/ None,
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
remote_plugin_catalog_error_to_jsonrpc(err, "install remote plugin")
|
remote_plugin_catalog_error_to_jsonrpc(err, "install remote plugin")
|
||||||
@@ -1732,12 +1738,14 @@ impl PluginRequestProcessor {
|
|||||||
marketplace_name: &str,
|
marketplace_name: &str,
|
||||||
plugin_id: Option<&PluginId>,
|
plugin_id: Option<&PluginId>,
|
||||||
error_type: &'static str,
|
error_type: &'static str,
|
||||||
|
sub_error_type: Option<String>,
|
||||||
error_message: String,
|
error_message: String,
|
||||||
) {
|
) {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
remote_plugin_id = %remote_plugin_id,
|
remote_plugin_id = %remote_plugin_id,
|
||||||
marketplace_name = %marketplace_name,
|
marketplace_name = %marketplace_name,
|
||||||
error_type = %error_type,
|
error_type = %error_type,
|
||||||
|
sub_error_type = sub_error_type.as_deref(),
|
||||||
error = %error_message,
|
error = %error_message,
|
||||||
"remote plugin install failed"
|
"remote plugin install failed"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1283,6 +1283,7 @@ impl PluginsManager {
|
|||||||
self.track_plugin_install_failed(
|
self.track_plugin_install_failed(
|
||||||
&plugin_id,
|
&plugin_id,
|
||||||
plugin_install_error_type(&err),
|
plugin_install_error_type(&err),
|
||||||
|
plugin_install_sub_error_type(&err),
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
Err(err)
|
Err(err)
|
||||||
@@ -1345,6 +1346,7 @@ impl PluginsManager {
|
|||||||
self.track_plugin_install_failed(
|
self.track_plugin_install_failed(
|
||||||
&resolved.plugin_id,
|
&resolved.plugin_id,
|
||||||
plugin_install_error_type(&err),
|
plugin_install_error_type(&err),
|
||||||
|
plugin_install_sub_error_type(&err),
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
return Err(err);
|
return Err(err);
|
||||||
@@ -1356,6 +1358,7 @@ impl PluginsManager {
|
|||||||
self.track_plugin_install_failed(
|
self.track_plugin_install_failed(
|
||||||
&plugin_id,
|
&plugin_id,
|
||||||
plugin_install_error_type(&err),
|
plugin_install_error_type(&err),
|
||||||
|
plugin_install_sub_error_type(&err),
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
Err(err)
|
Err(err)
|
||||||
@@ -1383,6 +1386,7 @@ impl PluginsManager {
|
|||||||
self.track_plugin_install_failed(
|
self.track_plugin_install_failed(
|
||||||
&plugin_id,
|
&plugin_id,
|
||||||
marketplace_error_type(err),
|
marketplace_error_type(err),
|
||||||
|
/*sub_error_type*/ None,
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -1398,11 +1402,13 @@ impl PluginsManager {
|
|||||||
&self,
|
&self,
|
||||||
plugin_id: &PluginId,
|
plugin_id: &PluginId,
|
||||||
error_type: &'static str,
|
error_type: &'static str,
|
||||||
|
sub_error_type: Option<String>,
|
||||||
error_message: String,
|
error_message: String,
|
||||||
) {
|
) {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
plugin_id = %plugin_id.as_key(),
|
plugin_id = %plugin_id.as_key(),
|
||||||
error_type = %error_type,
|
error_type = %error_type,
|
||||||
|
sub_error_type = sub_error_type.as_deref(),
|
||||||
error = %error_message,
|
error = %error_message,
|
||||||
"plugin install failed"
|
"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 {
|
fn marketplace_error_type(err: &MarketplaceError) -> &'static str {
|
||||||
match err {
|
match err {
|
||||||
MarketplaceError::Io { .. } => "marketplace_io",
|
MarketplaceError::Io { .. } => "marketplace_io",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use crate::remote::REMOTE_GLOBAL_MARKETPLACE_NAME;
|
|||||||
use crate::store::PluginInstallResult;
|
use crate::store::PluginInstallResult;
|
||||||
use crate::store::PluginStore;
|
use crate::store::PluginStore;
|
||||||
use crate::store::PluginStoreError;
|
use crate::store::PluginStoreError;
|
||||||
|
use crate::store::error_context_sub_error_type;
|
||||||
use crate::store::validate_plugin_version_segment;
|
use crate::store::validate_plugin_version_segment;
|
||||||
use codex_login::default_client::build_reqwest_client;
|
use codex_login::default_client::build_reqwest_client;
|
||||||
use codex_plugin::PluginId;
|
use codex_plugin::PluginId;
|
||||||
@@ -132,6 +133,26 @@ impl RemotePluginBundleInstallError {
|
|||||||
fn io(context: &'static str, source: io::Error) -> Self {
|
fn io(context: &'static str, source: io::Error) -> Self {
|
||||||
Self::Io { context, source }
|
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(
|
pub fn validate_remote_plugin_bundle(
|
||||||
|
|||||||
@@ -365,6 +365,17 @@ impl PluginStoreError {
|
|||||||
fn io(context: &'static str, source: io::Error) -> Self {
|
fn io(context: &'static str, source: io::Error) -> Self {
|
||||||
Self::Io { context, source }
|
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> {
|
pub fn plugin_version_for_source(source_path: &Path) -> Result<String, PluginStoreError> {
|
||||||
|
|||||||
Reference in new issue
Block a user