fix(observability): demote unknown-provider list_models error (Sentry TAURI-RUST-X) (#2783)

This commit is contained in:
CodeGhost21
2026-05-28 17:43:58 +05:30
committed by GitHub
parent 629369b100
commit f7babffc66
2 changed files with 98 additions and 2 deletions
+40 -2
View File
@@ -9,10 +9,26 @@ use crate::openhuman::inference::{device, presets, sentiment, SentimentResult};
use crate::openhuman::inference::{LocalAiEmbeddingResult, LocalAiStatus};
use crate::rpc::RpcOutcome;
use serde_json::{json, Value};
use tracing::{debug, error};
use tracing::{debug, error, warn};
const LOG_PREFIX: &str = "[inference::ops]";
/// User picked a provider id (slug) that isn't registered in the cloud
/// provider list — e.g. selecting `"ollama"` as a cloud provider when it's
/// actually a local runtime. Matches the literal phrase emitted at
/// `src/openhuman/inference/provider/ops.rs:54`
/// (`"no cloud provider with id or slug '{}' found"`).
///
/// Used by [`inference_list_models`] to demote this user-config case to
/// `warn!` so it stops escalating to Sentry (TAURI-RUST-X, ~5740 events).
/// The matcher is anchored on the exact phrase so unrelated sibling
/// failures (TAURI-RUST-12 JSON parse, TAURI-RUST-2W reqwest builder,
/// TAURI-RUST-JP local ollama_admin transport) still surface as real
/// errors.
fn is_unknown_provider_user_config(err: &str) -> bool {
err.contains("no cloud provider with id or slug")
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct InferenceTestProviderModelResult {
pub reply: String,
@@ -245,7 +261,29 @@ pub async fn inference_list_models(provider_id: &str) -> Result<RpcOutcome<Value
let result = providers::ops::list_configured_models(provider_id).await;
match &result {
Ok(_) => debug!("{LOG_PREFIX} list_models:ok"),
Err(err) => error!(error = %err, "{LOG_PREFIX} list_models:error"),
Err(err) => {
if is_unknown_provider_user_config(err) {
// User selected a provider id that isn't a registered
// cloud provider (e.g. picking "ollama", a local runtime).
// Demote to `warn!` so it stays in local logs but doesn't
// escalate to Sentry. Targets TAURI-RUST-X (~5740 events).
warn!(
provider_id,
error = %err,
"{LOG_PREFIX} list_models:unknown-provider (user-config)"
);
} else {
// Real error — embed `{err}` in the format string so
// Sentry's event title carries the actionable cause
// instead of the opaque `list_models:error` shape that
// made TAURI-RUST-X untriageable.
error!(
provider_id,
error = %err,
"{LOG_PREFIX} list_models:error: {err}"
);
}
}
}
result
}
+58
View File
@@ -258,3 +258,61 @@ async fn inference_openai_oauth_disconnect_returns_removed_flag() {
assert_eq!(outcome.value["disconnected"], true);
assert_eq!(outcome.logs, vec!["openai oauth disconnected"]);
}
// ── is_unknown_provider_user_config (TAURI-RUST-X) ───────────────────────
//
// `inference_list_models` calls `providers::ops::list_configured_models`,
// which surfaces a `String` error when the user-selected provider id isn't
// registered in the cloud-provider list (e.g. picking "ollama" — a local
// runtime — as a cloud provider). The error string is emitted at
// `src/openhuman/inference/provider/ops.rs:54`. Before this fix the emit
// site at `inference/ops.rs:248` escalated every such error to `error!`,
// which sentry-tracing ships to Sentry as `"[inference::ops]
// list_models:error"` — 5740+ events with the underlying error hidden in
// a tracing field where no Sentry classifier can reach it. The helper
// gate keeps the demote anchored so unrelated failures (HTTP / JSON / IO)
// still escalate.
#[test]
fn is_unknown_provider_user_config_matches_canonical_emit_site_string() {
// Verbatim shape from `provider/ops.rs:54`:
// format!("no cloud provider with id or slug '{}' found", provider_id)
// Latest TAURI-RUST-X event (Sentry id 95) carried provider_id="ollama";
// every well-formed provider id slug must trigger the demote.
assert!(is_unknown_provider_user_config(
"no cloud provider with id or slug 'ollama' found"
));
assert!(is_unknown_provider_user_config(
"no cloud provider with id or slug 'made-up-custom-id' found"
));
assert!(is_unknown_provider_user_config(
"no cloud provider with id or slug '' found"
));
}
#[test]
fn is_unknown_provider_user_config_rejects_other_list_models_failures() {
// Defense in depth: the sibling list_models Sentry issues
// (TAURI-RUST-12 JSON parse, TAURI-RUST-2W HTTP builder, etc.) are
// real bugs that MUST still escalate to Sentry. The matcher must stay
// strictly anchored on the "no cloud provider with id or slug" phrase
// so it can't accidentally silence them.
for raw in [
// TAURI-RUST-12 (362 events) — provider/ops.rs JSON decode failure
"[providers][list_models] failed to parse JSON: error decoding response",
// TAURI-RUST-2W (100 events) — provider/ops.rs reqwest builder failure
"[providers][list_models] HTTP request failed: builder error",
// TAURI-RUST-JP (8 events) — local_ai ollama_admin transport failure
"[local_ai:ollama_admin] list_models: request send failed",
// Generic shapes from elsewhere in the call chain
"request timed out after 30s",
"permission denied accessing config",
"no cloud provider configured for slug 'openai' (role 'chat')",
"",
] {
assert!(
!is_unknown_provider_user_config(raw),
"must NOT demote real error: {raw:?}"
);
}
}