From 3e2f605e776a1cf8cb75e98213f3b765c837c4e1 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Wed, 5 Nov 2025 02:11:43 +0800 Subject: [PATCH] fix: improve error handling and logging in various modules --- src-tauri/src/cmd/profile.rs | 5 ++- src-tauri/src/config/config.rs | 10 +++--- src-tauri/src/config/profiles.rs | 4 +-- src-tauri/src/core/tray/mod.rs | 14 ++++++--- src-tauri/src/core/validate.rs | 53 ++++++++++++++++++++++---------- src-tauri/src/utils/init.rs | 12 ++++++-- 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src-tauri/src/cmd/profile.rs b/src-tauri/src/cmd/profile.rs index 4af307cb..15faa204 100644 --- a/src-tauri/src/cmd/profile.rs +++ b/src-tauri/src/cmd/profile.rs @@ -292,8 +292,7 @@ async fn restore_previous_profile(prev_profile: &String) -> CmdResult<()> { }; Config::profiles() .await - .edit_draft(|d| d.patch_config(&restore_profiles)) - .stringify_err()?; + .edit_draft(|d| d.patch_config(&restore_profiles)); Config::profiles().await.apply(); crate::process::AsyncHandler::spawn(|| async move { if let Err(e) = profiles_save_file_safe().await { @@ -412,7 +411,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { CURRENT_SWITCHING_PROFILE.store(false, Ordering::Release); return Ok(false); } - let _ = Config::profiles() + Config::profiles() .await .edit_draft(|d| d.patch_config(&profiles)); diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs index 4cdc5ac7..bf9c31b9 100644 --- a/src-tauri/src/config/config.rs +++ b/src-tauri/src/config/config.rs @@ -155,15 +155,13 @@ impl Config { }; let runtime = Config::runtime().await; - let config = runtime - .latest_arc() + let runtime_arc = runtime.latest_arc(); + let config = runtime_arc .config .as_ref() - .ok_or_else(|| anyhow!("failed to get runtime config"))? - .clone(); - drop(runtime); // 显式释放锁 + .ok_or_else(|| anyhow!("failed to get runtime config"))?; - help::save_yaml(&path, &config, Some("# Generated by Clash Verge")).await?; + help::save_yaml(&path, config, Some("# Generated by Clash Verge")).await?; Ok(path) } diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index 51dd6172..f46f3826 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -87,7 +87,7 @@ impl IProfiles { } /// 只修改current,valid和chain - pub fn patch_config(&mut self, patch: &IProfiles) -> Result<()> { + pub fn patch_config(&mut self, patch: &IProfiles) { if self.items.is_none() { self.items = Some(vec![]); } @@ -100,8 +100,6 @@ impl IProfiles { self.current = some_uid.cloned(); } } - - Ok(()) } pub fn get_current(&self) -> Option<&String> { diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index 6b91f06a..24e6913b 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -24,6 +24,8 @@ use futures::future::join_all; use parking_lot::Mutex; use smartstring::alias::String; use std::collections::HashMap; +use std::future::Future; +use std::pin::Pin; use std::sync::Arc; use std::{ sync::atomic::{AtomicBool, Ordering}, @@ -575,9 +577,6 @@ impl Tray { return; } - use std::future::Future; - use std::pin::Pin; - let fut: Pin + Send>> = match tray_event.as_str() { "system_proxy" => Box::pin(async move { feat::toggle_system_proxy().await; @@ -1226,7 +1225,14 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { }; feat::switch_proxy_node(group_name, proxy_name).await; } - _ => {} + _ => { + logging!( + debug, + Type::Tray, + "Unhandled tray menu event: {:?}", + event.id + ); + } } // We dont expected to refresh tray state here diff --git a/src-tauri/src/core/validate.rs b/src-tauri/src/core/validate.rs index 562ebd24..c22a5d04 100644 --- a/src-tauri/src/core/validate.rs +++ b/src-tauri/src/core/validate.rs @@ -275,41 +275,43 @@ impl CoreConfigValidator { logging!(info, Type::Validate, "验证目录: {}", app_dir_str); // 使用子进程运行clash验证配置 - let output = app_handle - .shell() - .sidecar(clash_core.as_str())? - .args(["-t", "-d", app_dir_str, "-f", config_path]) - .output() - .await?; + let command = app_handle.shell().sidecar(clash_core.as_str())?.args([ + "-t", + "-d", + app_dir_str, + "-f", + config_path, + ]); + let output = command.output().await?; - let stderr = std::string::String::from_utf8_lossy(&output.stderr); - let stdout = std::string::String::from_utf8_lossy(&output.stdout); + let status = &output.status; + let stderr = &output.stderr; + let stdout = &output.stdout; // 检查进程退出状态和错误输出 let error_keywords = ["FATA", "fatal", "Parse config error", "level=fatal"]; - let has_error = - !output.status.success() || error_keywords.iter().any(|&kw| stderr.contains(kw)); + let has_error = !status.success() || contains_any_keyword(stderr, &error_keywords); logging!(info, Type::Validate, "-------- 验证结果 --------"); if !stderr.is_empty() { - logging!(info, Type::Validate, "stderr输出:\n{}", stderr); + logging!(info, Type::Validate, "stderr输出:\n{:?}", stderr); } if has_error { logging!(info, Type::Validate, "发现错误,开始处理错误信息"); - let error_msg = if !stdout.is_empty() { - stdout.into() + let error_msg: String = if !stdout.is_empty() { + str::from_utf8(stdout).unwrap_or_default().into() } else if !stderr.is_empty() { - stderr.into() - } else if let Some(code) = output.status.code() { - format!("验证进程异常退出,退出码: {code}") + str::from_utf8(stderr).unwrap_or_default().into() + } else if let Some(code) = status.code() { + format!("验证进程异常退出,退出码: {code}").into() } else { "验证进程被终止".into() }; logging!(info, Type::Validate, "-------- 验证结束 --------"); - Ok((false, error_msg.into())) // 返回错误消息给调用者处理 + Ok((false, error_msg)) // 返回错误消息给调用者处理 } else { logging!(info, Type::Validate, "验证成功"); logging!(info, Type::Validate, "-------- 验证结束 --------"); @@ -342,6 +344,23 @@ fn has_ext>(path: P, ext: &str) -> bool { .unwrap_or(false) } +fn contains_any_keyword<'a>(buf: &'a [u8], keywords: &'a [&str]) -> bool { + for &kw in keywords { + let needle = kw.as_bytes(); + if needle.is_empty() { + continue; + } + let mut i = 0; + while i + needle.len() <= buf.len() { + if &buf[i..i + needle.len()] == needle { + return true; + } + i += 1; + } + } + false +} + singleton_lazy!( CoreConfigValidator, CORECONFIGVALIDATOR, diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs index ff29d937..ba6b27d9 100644 --- a/src-tauri/src/utils/init.rs +++ b/src-tauri/src/utils/init.rs @@ -1,4 +1,4 @@ -#[cfg(not(feature = "tracing"))] +// #[cfg(not(feature = "tracing"))] #[cfg(not(feature = "tauri-dev"))] use crate::utils::logging::NoModuleFilter; use crate::{ @@ -49,7 +49,9 @@ pub async fn init_logger() -> Result<()> { #[cfg(feature = "tracing")] spec.module("tauri", log::LevelFilter::Debug); #[cfg(feature = "tracing")] - spec.module("wry", log::LevelFilter::Debug); + spec.module("wry", log::LevelFilter::Off); + #[cfg(feature = "tracing")] + spec.module("tauri_plugin_mihomo", log::LevelFilter::Off); let spec = spec.build(); let logger = Logger::with(spec) @@ -67,6 +69,12 @@ pub async fn init_logger() -> Result<()> { ); #[cfg(not(feature = "tracing"))] let logger = logger.filter(Box::new(NoModuleFilter(&["wry", "tauri"]))); + #[cfg(feature = "tracing")] + let logger = logger.filter(Box::new(NoModuleFilter(&[ + "wry", + "tauri_plugin_mihomo", + "kode_bridge", + ]))); let _handle = logger.start()?;