From fb260fb33d7caabdc8df75740e30293853731401 Mon Sep 17 00:00:00 2001 From: Tunglies Date: Sat, 1 Nov 2025 20:47:01 +0800 Subject: [PATCH] Refactor logging to use a centralized logging utility across the application (#5277) - Replaced direct log calls with a new logging macro that includes a logging type for better categorization. - Updated logging in various modules including `merge.rs`, `mod.rs`, `tun.rs`, `clash.rs`, `profile.rs`, `proxy.rs`, `window.rs`, `lightweight.rs`, `guard.rs`, `autostart.rs`, `dirs.rs`, `dns.rs`, `scheme.rs`, `server.rs`, and `window_manager.rs`. - Introduced logging types such as `Core`, `Network`, `ProxyMode`, `Window`, `Lightweight`, `Service`, and `File` to enhance log clarity and filtering. --- src-tauri/src/cmd/app.rs | 11 ++- src-tauri/src/cmd/clash.rs | 2 +- src-tauri/src/cmd/network.rs | 22 ++++- src-tauri/src/cmd/profile.rs | 18 ++-- src-tauri/src/config/clash.rs | 5 +- src-tauri/src/config/profiles.rs | 20 ++-- src-tauri/src/config/verge.rs | 4 +- src-tauri/src/core/async_proxy_query.rs | 58 +++++++++--- src-tauri/src/core/backup.rs | 28 +++++- src-tauri/src/core/event_driven_proxy.rs | 58 +++++++----- src-tauri/src/core/sysopt.rs | 26 ++++-- src-tauri/src/core/tray/mod.rs | 113 +++++++++++++++++------ src-tauri/src/enhance/merge.rs | 8 +- src-tauri/src/enhance/mod.rs | 11 ++- src-tauri/src/enhance/tun.rs | 9 +- src-tauri/src/feat/clash.rs | 16 ++-- src-tauri/src/feat/profile.rs | 61 +++++++++--- src-tauri/src/feat/proxy.rs | 20 +++- src-tauri/src/feat/window.rs | 60 +++++++----- src-tauri/src/module/lightweight.rs | 6 +- src-tauri/src/process/guard.rs | 9 +- src-tauri/src/utils/autostart.rs | 20 ++-- src-tauri/src/utils/dirs.rs | 18 +++- src-tauri/src/utils/logging.rs | 2 - src-tauri/src/utils/resolve/dns.rs | 38 +++++--- src-tauri/src/utils/resolve/scheme.rs | 6 +- src-tauri/src/utils/server.rs | 8 +- src-tauri/src/utils/window_manager.rs | 26 ++++-- 28 files changed, 473 insertions(+), 210 deletions(-) diff --git a/src-tauri/src/cmd/app.rs b/src-tauri/src/cmd/app.rs index b0b9d480e..959277feb 100644 --- a/src-tauri/src/cmd/app.rs +++ b/src-tauri/src/cmd/app.rs @@ -241,7 +241,7 @@ pub async fn copy_icon_file(path: String, icon_info: IconInfo) -> CmdResult CmdResult<()> { - log::info!(target: "app", "前端UI已准备就绪"); + logging!(info, Type::Cmd, "前端UI已准备就绪"); crate::utils::resolve::ui::mark_ui_ready(); Ok(()) } @@ -249,7 +249,7 @@ pub fn notify_ui_ready() -> CmdResult<()> { /// UI加载阶段 #[tauri::command] pub fn update_ui_stage(stage: String) -> CmdResult<()> { - log::info!(target: "app", "UI加载阶段更新: {}", stage.as_str()); + logging!(info, Type::Cmd, "UI加载阶段更新: {}", stage.as_str()); use crate::utils::resolve::ui::UiReadyStage; @@ -260,7 +260,12 @@ pub fn update_ui_stage(stage: String) -> CmdResult<()> { "ResourcesLoaded" => UiReadyStage::ResourcesLoaded, "Ready" => UiReadyStage::Ready, _ => { - log::warn!(target: "app", "未知的UI加载阶段: {}", stage.as_str()); + logging!( + warn, + Type::Cmd, + "Warning: 未知的UI加载阶段: {}", + stage.as_str() + ); return Err(format!("未知的UI加载阶段: {}", stage.as_str()).into()); } }; diff --git a/src-tauri/src/cmd/clash.rs b/src-tauri/src/cmd/clash.rs index 37033f481..b6dbc1faa 100644 --- a/src-tauri/src/cmd/clash.rs +++ b/src-tauri/src/cmd/clash.rs @@ -109,7 +109,7 @@ pub async fn test_delay(url: String) -> CmdResult { let result = match feat::test_delay(url).await { Ok(delay) => delay, Err(e) => { - log::error!(target: "app", "{}", e); + logging!(error, Type::Cmd, "{}", e); 10000u32 } }; diff --git a/src-tauri/src/cmd/network.rs b/src-tauri/src/cmd/network.rs index 120bd1f02..c0dedfde6 100644 --- a/src-tauri/src/cmd/network.rs +++ b/src-tauri/src/cmd/network.rs @@ -2,13 +2,14 @@ use super::CmdResult; use crate::cmd::StringifyErr; use crate::core::{EventDrivenProxyManager, async_proxy_query::AsyncProxyQuery}; use crate::process::AsyncHandler; +use crate::{logging, utils::logging::Type}; use network_interface::NetworkInterface; use serde_yaml_ng::Mapping; /// get the system proxy #[tauri::command] pub async fn get_sys_proxy() -> CmdResult { - log::debug!(target: "app", "异步获取系统代理配置"); + logging!(debug, Type::Network, "异步获取系统代理配置"); let current = AsyncProxyQuery::get_system_proxy().await; @@ -20,14 +21,21 @@ pub async fn get_sys_proxy() -> CmdResult { ); map.insert("bypass".into(), current.bypass.into()); - log::debug!(target: "app", "返回系统代理配置: enable={}, {}:{}", current.enable, current.host, current.port); + logging!( + debug, + Type::Network, + "返回系统代理配置: enable={}, {}:{}", + current.enable, + current.host, + current.port + ); Ok(map) } /// 获取自动代理配置 #[tauri::command] pub async fn get_auto_proxy() -> CmdResult { - log::debug!(target: "app", "开始获取自动代理配置(事件驱动)"); + logging!(debug, Type::Network, "开始获取自动代理配置(事件驱动)"); let proxy_manager = EventDrivenProxyManager::global(); @@ -41,7 +49,13 @@ pub async fn get_auto_proxy() -> CmdResult { map.insert("enable".into(), current.enable.into()); map.insert("url".into(), current.url.clone().into()); - log::debug!(target: "app", "返回自动代理配置(缓存): enable={}, url={}", current.enable, current.url); + logging!( + debug, + Type::Network, + "返回自动代理配置(缓存): enable={}, url={}", + current.enable, + current.url + ); Ok(map) } diff --git a/src-tauri/src/cmd/profile.rs b/src-tauri/src/cmd/profile.rs index 8080fe125..9ab8e21a4 100644 --- a/src-tauri/src/cmd/profile.rs +++ b/src-tauri/src/cmd/profile.rs @@ -85,7 +85,7 @@ pub async fn enhance_profiles() -> CmdResult { match feat::enhance_profiles().await { Ok(_) => {} Err(e) => { - log::error!(target: "app", "{}", e); + logging!(error, Type::Cmd, "{}", e); return Err(e.to_string().into()); } } @@ -147,11 +147,11 @@ pub async fn import_profile(url: std::string::String, option: Option) pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult { match profiles_reorder_safe(&active_id, &over_id).await { Ok(_) => { - log::info!(target: "app", "重新排序配置文件"); + logging!(info, Type::Cmd, "重新排序配置文件"); Ok(()) } Err(err) => { - log::error!(target: "app", "重新排序配置文件失败: {}", err); + logging!(error, Type::Cmd, "重新排序配置文件失败: {}", err); Err(format!("重新排序配置文件失败: {}", err).into()) } } @@ -183,7 +183,7 @@ pub async fn update_profile(index: String, option: Option) -> CmdResu match feat::update_profile(&index, option.as_ref(), true, true).await { Ok(_) => Ok(()), Err(e) => { - log::error!(target: "app", "{}", e); + logging!(error, Type::Cmd, "{}", e); Err(e.to_string().into()) } } @@ -206,7 +206,7 @@ pub async fn delete_profile(index: String) -> CmdResult { handle::Handle::notify_profile_changed(index); } Err(e) => { - log::error!(target: "app", "{}", e); + logging!(error, Type::Cmd, "{}", e); return Err(e.to_string().into()); } } @@ -337,7 +337,7 @@ async fn restore_previous_profile(prev_profile: String) -> CmdResult<()> { Config::profiles().await.apply(); crate::process::AsyncHandler::spawn(|| async move { if let Err(e) = profiles_save_file_safe().await { - log::warn!(target: "app", "异步保存恢复配置文件失败: {e}"); + logging!(warn, Type::Cmd, "Warning: 异步保存恢复配置文件失败: {e}"); } }); logging!(info, Type::Cmd, "成功恢复到之前的配置"); @@ -368,15 +368,15 @@ async fn handle_success(current_sequence: u64, current_value: Option) -> handle::Handle::refresh_clash(); if let Err(e) = Tray::global().update_tooltip().await { - log::warn!(target: "app", "异步更新托盘提示失败: {e}"); + logging!(warn, Type::Cmd, "Warning: 异步更新托盘提示失败: {e}"); } if let Err(e) = Tray::global().update_menu().await { - log::warn!(target: "app", "异步更新托盘菜单失败: {e}"); + logging!(warn, Type::Cmd, "Warning: 异步更新托盘菜单失败: {e}"); } if let Err(e) = profiles_save_file_safe().await { - log::warn!(target: "app", "异步保存配置文件失败: {e}"); + logging!(warn, Type::Cmd, "Warning: 异步保存配置文件失败: {e}"); } if let Some(current) = ¤t_value { diff --git a/src-tauri/src/config/clash.rs b/src-tauri/src/config/clash.rs index ac2169338..9ca6276aa 100644 --- a/src-tauri/src/config/clash.rs +++ b/src-tauri/src/config/clash.rs @@ -1,6 +1,7 @@ use crate::config::Config; use crate::utils::dirs::{ipc_path, path_to_str}; use crate::utils::{dirs, help}; +use crate::{logging, utils::logging::Type}; use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_yaml_ng::{Mapping, Value}; @@ -40,7 +41,7 @@ impl IClashTemp { Self(Self::guard(map)) } Err(err) => { - log::error!(target: "app", "{err}"); + logging!(error, Type::Config, "{err}"); template } } @@ -330,7 +331,7 @@ impl IClashTemp { .ok() .and_then(|path| path_to_str(&path).ok().map(|s| s.into())) .unwrap_or_else(|| { - log::error!(target: "app", "Failed to get IPC path"); + logging!(error, Type::Config, "Failed to get IPC path"); crate::constants::network::DEFAULT_EXTERNAL_CONTROLLER.into() }) } diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index d8d9a003a..98886afcc 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -3,6 +3,7 @@ use crate::utils::{ dirs::{self, PathBufExec}, help, }; +use crate::{logging, utils::logging::Type}; use anyhow::{Context, Result, bail}; use serde::{Deserialize, Serialize}; use serde_yaml_ng::Mapping; @@ -67,12 +68,12 @@ impl IProfiles { profiles } Err(err) => { - log::error!(target: "app", "{err}"); + logging!(error, Type::Config, "{err}"); Self::template() } }, Err(err) => { - log::error!(target: "app", "{err}"); + logging!(error, Type::Config, "{err}"); Self::template() } } @@ -492,7 +493,7 @@ impl IProfiles { { // 检查是否为全局扩展文件 if protected_files.contains(file_name) { - log::debug!(target: "app", "保护全局扩展配置文件: {file_name}"); + logging!(debug, Type::Config, "保护全局扩展配置文件: {file_name}"); continue; } @@ -501,11 +502,15 @@ impl IProfiles { match path.to_path_buf().remove_if_exists().await { Ok(_) => { deleted_files.push(file_name.into()); - log::info!(target: "app", "已清理冗余文件: {file_name}"); + logging!(info, Type::Config, "已清理冗余文件: {file_name}"); } Err(e) => { failed_deletions.push(format!("{file_name}: {e}").into()); - log::warn!(target: "app", "清理文件失败: {file_name} - {e}"); + logging!( + warn, + Type::Config, + "Warning: 清理文件失败: {file_name} - {e}" + ); } } } @@ -518,8 +523,9 @@ impl IProfiles { failed_deletions, }; - log::info!( - target: "app", + logging!( + info, + Type::Config, "Profile 文件清理完成: 总文件数={}, 删除文件数={}, 失败数={}", result.total_files, result.deleted_files.len(), diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index 61f69ea97..1e37cee45 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -353,12 +353,12 @@ impl IVerge { config } Err(err) => { - log::error!(target: "app", "{err}"); + logging!(error, Type::Config, "{err}"); Self::template() } }, Err(err) => { - log::error!(target: "app", "{err}"); + logging!(error, Type::Config, "{err}"); Self::template() } } diff --git a/src-tauri/src/core/async_proxy_query.rs b/src-tauri/src/core/async_proxy_query.rs index 2fd8b3d8f..c9e31c672 100644 --- a/src-tauri/src/core/async_proxy_query.rs +++ b/src-tauri/src/core/async_proxy_query.rs @@ -1,5 +1,6 @@ #[cfg(target_os = "windows")] use crate::process::AsyncHandler; +use crate::{logging, utils::logging::Type}; use anyhow::Result; use serde::{Deserialize, Serialize}; use tokio::time::{Duration, timeout}; @@ -41,15 +42,21 @@ impl AsyncProxyQuery { pub async fn get_auto_proxy() -> AsyncAutoproxy { match timeout(Duration::from_secs(3), Self::get_auto_proxy_impl()).await { Ok(Ok(proxy)) => { - log::debug!(target: "app", "异步获取自动代理成功: enable={}, url={}", proxy.enable, proxy.url); + logging!( + debug, + Type::Network, + "异步获取自动代理成功: enable={}, url={}", + proxy.enable, + proxy.url + ); proxy } Ok(Err(e)) => { - log::warn!(target: "app", "异步获取自动代理失败: {e}"); + logging!(warn, Type::Network, "Warning: 异步获取自动代理失败: {e}"); AsyncAutoproxy::default() } Err(_) => { - log::warn!(target: "app", "异步获取自动代理超时"); + logging!(warn, Type::Network, "Warning: 异步获取自动代理超时"); AsyncAutoproxy::default() } } @@ -59,15 +66,22 @@ impl AsyncProxyQuery { pub async fn get_system_proxy() -> AsyncSysproxy { match timeout(Duration::from_secs(3), Self::get_system_proxy_impl()).await { Ok(Ok(proxy)) => { - log::debug!(target: "app", "异步获取系统代理成功: enable={}, {}:{}", proxy.enable, proxy.host, proxy.port); + logging!( + debug, + Type::Network, + "异步获取系统代理成功: enable={}, {}:{}", + proxy.enable, + proxy.host, + proxy.port + ); proxy } Ok(Err(e)) => { - log::warn!(target: "app", "异步获取系统代理失败: {e}"); + logging!(warn, Type::Network, "Warning: 异步获取系统代理失败: {e}"); AsyncSysproxy::default() } Err(_) => { - log::warn!(target: "app", "异步获取系统代理超时"); + logging!(warn, Type::Network, "Warning: 异步获取系统代理超时"); AsyncSysproxy::default() } } @@ -99,7 +113,7 @@ impl AsyncProxyQuery { RegOpenKeyExW(HKEY_CURRENT_USER, key_path.as_ptr(), 0, KEY_READ, &mut hkey); if result != 0 { - log::debug!(target: "app", "无法打开注册表项"); + logging!(debug, Type::Network, "无法打开注册表项"); return Ok(AsyncAutoproxy::default()); } @@ -125,7 +139,7 @@ impl AsyncProxyQuery { .position(|&x| x == 0) .unwrap_or(url_buffer.len()); pac_url = String::from_utf16_lossy(&url_buffer[..end_pos]); - log::debug!(target: "app", "从注册表读取到PAC URL: {pac_url}"); + logging!(debug, Type::Network, "从注册表读取到PAC URL: {pac_url}"); } // 2. 检查自动检测设置是否启用 @@ -150,7 +164,11 @@ impl AsyncProxyQuery { || (detect_query_result == 0 && detect_value_type == REG_DWORD && auto_detect != 0); if pac_enabled { - log::debug!(target: "app", "PAC配置启用: URL={pac_url}, AutoDetect={auto_detect}"); + logging!( + debug, + Type::Network, + "PAC配置启用: URL={pac_url}, AutoDetect={auto_detect}" + ); if pac_url.is_empty() && auto_detect != 0 { pac_url = "auto-detect".into(); @@ -161,7 +179,7 @@ impl AsyncProxyQuery { url: pac_url, }) } else { - log::debug!(target: "app", "PAC配置未启用"); + logging!(debug, Type::Network, "PAC配置未启用"); Ok(AsyncAutoproxy::default()) } } @@ -177,7 +195,11 @@ impl AsyncProxyQuery { } let stdout = String::from_utf8_lossy(&output.stdout); - log::debug!(target: "app", "scutil output: {stdout}"); + crate::logging!( + debug, + crate::utils::logging::Type::Network, + "scutil output: {stdout}" + ); let mut pac_enabled = false; let mut pac_url = String::new(); @@ -196,7 +218,11 @@ impl AsyncProxyQuery { } } - log::debug!(target: "app", "解析结果: pac_enabled={pac_enabled}, pac_url={pac_url}"); + crate::logging!( + debug, + crate::utils::logging::Type::Network, + "解析结果: pac_enabled={pac_enabled}, pac_url={pac_url}" + ); Ok(AsyncAutoproxy { enable: pac_enabled && !pac_url.is_empty(), @@ -363,7 +389,11 @@ impl AsyncProxyQuery { (proxy_server, 8080) }; - log::debug!(target: "app", "从注册表读取到代理设置: {host}:{port}, bypass: {bypass_list}"); + logging!( + debug, + Type::Network, + "从注册表读取到代理设置: {host}:{port}, bypass: {bypass_list}" + ); Ok(AsyncSysproxy { enable: true, @@ -386,7 +416,7 @@ impl AsyncProxyQuery { } let stdout = String::from_utf8_lossy(&output.stdout); - log::debug!(target: "app", "scutil proxy output: {stdout}"); + logging!(debug, Type::Network, "scutil proxy output: {stdout}"); let mut http_enabled = false; let mut http_host = String::new(); diff --git a/src-tauri/src/core/backup.rs b/src-tauri/src/core/backup.rs index 345d1f059..167fbdd13 100644 --- a/src-tauri/src/core/backup.rs +++ b/src-tauri/src/core/backup.rs @@ -1,4 +1,9 @@ -use crate::{config::Config, process::AsyncHandler, utils::dirs}; +use crate::{ + config::Config, + logging, + process::AsyncHandler, + utils::{dirs, logging::Type}, +}; use anyhow::Error; use once_cell::sync::OnceCell; use parking_lot::Mutex; @@ -137,9 +142,14 @@ impl WebDavClient { .is_err() { match client.mkcol(dirs::BACKUP_DIR).await { - Ok(_) => log::info!("Successfully created backup directory"), + Ok(_) => logging!(info, Type::Backup, "Successfully created backup directory"), Err(e) => { - log::warn!("Failed to create backup directory: {}", e); + logging!( + warn, + Type::Backup, + "Warning: Failed to create backup directory: {}", + e + ); // 清除缓存,强制下次重新尝试 self.reset(); return Err(anyhow::Error::msg(format!( @@ -180,7 +190,11 @@ impl WebDavClient { match upload_result { Err(_) => { - log::warn!("Upload timed out, retrying once"); + logging!( + warn, + Type::Backup, + "Warning: Upload timed out, retrying once" + ); tokio::time::sleep(Duration::from_millis(500)).await; timeout( Duration::from_secs(TIMEOUT_UPLOAD), @@ -191,7 +205,11 @@ impl WebDavClient { } Ok(Err(e)) => { - log::warn!("Upload failed, retrying once: {e}"); + logging!( + warn, + Type::Backup, + "Warning: Upload failed, retrying once: {e}" + ); tokio::time::sleep(Duration::from_millis(500)).await; timeout( Duration::from_secs(TIMEOUT_UPLOAD), diff --git a/src-tauri/src/core/event_driven_proxy.rs b/src-tauri/src/core/event_driven_proxy.rs index dd0928c76..18a6f1559 100644 --- a/src-tauri/src/core/event_driven_proxy.rs +++ b/src-tauri/src/core/event_driven_proxy.rs @@ -7,6 +7,7 @@ use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use crate::config::{Config, IVerge}; use crate::core::{async_proxy_query::AsyncProxyQuery, handle}; use crate::process::AsyncHandler; +use crate::{logging, utils::logging::Type}; use once_cell::sync::Lazy; use smartstring::alias::String; use sysproxy::{Autoproxy, Sysproxy}; @@ -104,14 +105,14 @@ impl EventDrivenProxyManager { let query = QueryRequest { response_tx: tx }; if self.query_sender.send(query).is_err() { - log::error!(target: "app", "发送查询请求失败,返回缓存数据"); + logging!(error, Type::Network, "发送查询请求失败,返回缓存数据"); return self.get_auto_proxy_cached().await; } match timeout(Duration::from_secs(5), rx).await { Ok(Ok(result)) => result, _ => { - log::warn!(target: "app", "查询超时,返回缓存数据"); + logging!(warn, Type::Network, "Warning: 查询超时,返回缓存数据"); self.get_auto_proxy_cached().await } } @@ -134,7 +135,7 @@ impl EventDrivenProxyManager { fn send_event(&self, event: ProxyEvent) { if let Err(e) = self.event_sender.send(event) { - log::error!(target: "app", "发送代理事件失败: {e}"); + logging!(error, Type::Network, "发送代理事件失败: {e}"); } } @@ -143,7 +144,7 @@ impl EventDrivenProxyManager { event_rx: mpsc::UnboundedReceiver, query_rx: mpsc::UnboundedReceiver, ) { - log::info!(target: "app", "事件驱动代理管理器启动"); + logging!(info, Type::Network, "事件驱动代理管理器启动"); // 将 mpsc 接收器包装成 Stream,避免每次循环创建 future let mut event_stream = UnboundedReceiverStream::new(event_rx); @@ -158,7 +159,7 @@ impl EventDrivenProxyManager { loop { tokio::select! { Some(event) = event_stream.next() => { - log::debug!(target: "app", "处理代理事件: {event:?}"); + logging!(debug, Type::Network, "处理代理事件: {event:?}"); let event_clone = event.clone(); // 保存一份副本用于后续检查 Self::handle_event(&state, event).await; @@ -179,13 +180,13 @@ impl EventDrivenProxyManager { // 定时检查代理设置 let config = Self::get_proxy_config().await; if config.guard_enabled && config.sys_enabled { - log::debug!(target: "app", "定时检查代理设置"); + logging!(debug, Type::Network, "定时检查代理设置"); Self::check_and_restore_proxy(&state).await; } } else => { // 两个通道都关闭时退出 - log::info!(target: "app", "事件或查询通道关闭,代理管理器停止"); + logging!(info, Type::Network, "事件或查询通道关闭,代理管理器停止"); break; } } @@ -201,7 +202,7 @@ impl EventDrivenProxyManager { Self::initialize_proxy_state(state).await; } ProxyEvent::AppStopping => { - log::info!(target: "app", "清理代理状态"); + logging!(info, Type::Network, "清理代理状态"); Self::update_state_timestamp(state, |s| { s.sys_enabled = false; s.pac_enabled = false; @@ -224,7 +225,7 @@ impl EventDrivenProxyManager { } async fn initialize_proxy_state(state: &Arc>) { - log::info!(target: "app", "初始化代理状态"); + logging!(info, Type::Network, "初始化代理状态"); let config = Self::get_proxy_config().await; let auto_proxy = Self::get_auto_proxy_with_timeout().await; @@ -239,11 +240,17 @@ impl EventDrivenProxyManager { }) .await; - log::info!(target: "app", "代理状态初始化完成: sys={}, pac={}", config.sys_enabled, config.pac_enabled); + logging!( + info, + Type::Network, + "代理状态初始化完成: sys={}, pac={}", + config.sys_enabled, + config.pac_enabled + ); } async fn update_proxy_config(state: &Arc>) { - log::debug!(target: "app", "更新代理配置"); + logging!(debug, Type::Network, "更新代理配置"); let config = Self::get_proxy_config().await; @@ -260,7 +267,7 @@ impl EventDrivenProxyManager { async fn check_and_restore_proxy(state: &Arc>) { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过系统代理守卫检查"); + logging!(debug, Type::Network, "应用正在退出,跳过系统代理守卫检查"); return; } let (sys_enabled, pac_enabled) = { @@ -272,7 +279,7 @@ impl EventDrivenProxyManager { return; } - log::debug!(target: "app", "检查代理状态"); + logging!(debug, Type::Network, "检查代理状态"); if pac_enabled { Self::check_and_restore_pac_proxy(state).await; @@ -283,7 +290,7 @@ impl EventDrivenProxyManager { async fn check_and_restore_pac_proxy(state: &Arc>) { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过PAC代理恢复检查"); + logging!(debug, Type::Network, "应用正在退出,跳过PAC代理恢复检查"); return; } @@ -296,9 +303,9 @@ impl EventDrivenProxyManager { .await; if !current.enable || current.url != expected.url { - log::info!(target: "app", "PAC代理设置异常,正在恢复..."); + logging!(info, Type::Network, "PAC代理设置异常,正在恢复..."); if let Err(e) = Self::restore_pac_proxy(&expected.url).await { - log::error!(target: "app", "恢复PAC代理失败: {}", e); + logging!(error, Type::Network, "恢复PAC代理失败: {}", e); } sleep(Duration::from_millis(500)).await; @@ -314,7 +321,7 @@ impl EventDrivenProxyManager { async fn check_and_restore_sys_proxy(state: &Arc>) { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过系统代理恢复检查"); + logging!(debug, Type::Network, "应用正在退出,跳过系统代理恢复检查"); return; } @@ -327,9 +334,9 @@ impl EventDrivenProxyManager { .await; if !current.enable || current.host != expected.host || current.port != expected.port { - log::info!(target: "app", "系统代理设置异常,正在恢复..."); + logging!(info, Type::Network, "系统代理设置异常,正在恢复..."); if let Err(e) = Self::restore_sys_proxy(&expected).await { - log::error!(target: "app", "恢复系统代理失败: {}", e); + logging!(error, Type::Network, "恢复系统代理失败: {}", e); } sleep(Duration::from_millis(500)).await; @@ -457,7 +464,7 @@ impl EventDrivenProxyManager { #[cfg(target_os = "windows")] async fn restore_pac_proxy(expected_url: &str) -> Result<(), anyhow::Error> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过PAC代理恢复"); + logging!(debug, Type::Network, "应用正在退出,跳过PAC代理恢复"); return Ok(()); } Self::execute_sysproxy_command(&["pac", expected_url]).await @@ -481,7 +488,7 @@ impl EventDrivenProxyManager { #[cfg(target_os = "windows")] async fn restore_sys_proxy(expected: &Sysproxy) -> Result<(), anyhow::Error> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过系统代理恢复"); + logging!(debug, Type::Network, "应用正在退出,跳过系统代理恢复"); return Ok(()); } let address = format!("{}:{}", expected.host, expected.port); @@ -502,8 +509,9 @@ impl EventDrivenProxyManager { #[cfg(target_os = "windows")] async fn execute_sysproxy_command(args: &[&str]) -> Result<(), anyhow::Error> { if handle::Handle::global().is_exiting() { - log::debug!( - target: "app", + logging!( + debug, + Type::Network, "应用正在退出,取消调用 sysproxy.exe,参数: {:?}", args ); @@ -518,14 +526,14 @@ impl EventDrivenProxyManager { let binary_path = match dirs::service_path() { Ok(path) => path, Err(e) => { - log::error!(target: "app", "获取服务路径失败: {e}"); + logging!(error, Type::Network, "获取服务路径失败: {e}"); return Err(e); } }; let sysproxy_exe = binary_path.with_file_name("sysproxy.exe"); if !sysproxy_exe.exists() { - log::error!(target: "app", "sysproxy.exe 不存在"); + logging!(error, Type::Network, "sysproxy.exe 不存在"); } anyhow::ensure!(sysproxy_exe.exists(), "sysproxy.exe does not exist"); diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs index 77e561f15..d73d9a912 100644 --- a/src-tauri/src/core/sysopt.rs +++ b/src-tauri/src/core/sysopt.rs @@ -99,7 +99,7 @@ impl Sysopt { let proxy_manager = EventDrivenProxyManager::global(); proxy_manager.notify_app_started(); - log::info!(target: "app", "已启用事件驱动代理守卫"); + logging!(info, Type::Core, "已启用事件驱动代理守卫"); Ok(()) } @@ -224,14 +224,22 @@ impl Sysopt { let mut sysproxy: Sysproxy = match Sysproxy::get_system_proxy() { Ok(sp) => sp, Err(e) => { - log::warn!(target: "app", "重置代理时获取系统代理配置失败: {e}, 使用默认配置"); + logging!( + warn, + Type::Core, + "Warning: 重置代理时获取系统代理配置失败: {e}, 使用默认配置" + ); Sysproxy::default() } }; let mut autoproxy = match Autoproxy::get_auto_proxy() { Ok(ap) => ap, Err(e) => { - log::warn!(target: "app", "重置代理时获取自动代理配置失败: {e}, 使用默认配置"); + logging!( + warn, + Type::Core, + "Warning: 重置代理时获取自动代理配置失败: {e}, 使用默认配置" + ); Autoproxy::default() } }; @@ -265,14 +273,14 @@ impl Sysopt { { if is_enable { if let Err(e) = startup_shortcut::create_shortcut().await { - log::error!(target: "app", "创建启动快捷方式失败: {e}"); + logging!(error, Type::Setup, "创建启动快捷方式失败: {e}"); // 如果快捷方式创建失败,回退到原来的方法 self.try_original_autostart_method(is_enable); } else { return Ok(()); } } else if let Err(e) = startup_shortcut::remove_shortcut().await { - log::error!(target: "app", "删除启动快捷方式失败: {e}"); + logging!(error, Type::Setup, "删除启动快捷方式失败: {e}"); self.try_original_autostart_method(is_enable); } else { return Ok(()); @@ -307,11 +315,11 @@ impl Sysopt { { match startup_shortcut::is_shortcut_enabled() { Ok(enabled) => { - log::info!(target: "app", "快捷方式自启动状态: {enabled}"); + logging!(info, Type::System, "快捷方式自启动状态: {enabled}"); return Ok(enabled); } Err(e) => { - log::error!(target: "app", "检查快捷方式失败,尝试原来的方法: {e}"); + logging!(error, Type::System, "检查快捷方式失败,尝试原来的方法: {e}"); } } } @@ -322,11 +330,11 @@ impl Sysopt { match autostart_manager.is_enabled() { Ok(status) => { - log::info!(target: "app", "Auto launch status: {status}"); + logging!(info, Type::System, "Auto launch status: {status}"); Ok(status) } Err(e) => { - log::error!(target: "app", "Failed to get auto launch status: {e}"); + logging!(error, Type::System, "Failed to get auto launch status: {e}"); Err(anyhow::anyhow!("Failed to get auto launch status: {}", e)) } } diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index fe657d116..8261c98a0 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -62,8 +62,12 @@ fn should_handle_tray_click() -> bool { *last_click = now; true } else { - log::debug!(target: "app", "托盘点击被防抖机制忽略,距离上次点击 {:?}ms", - now.duration_since(*last_click).as_millis()); + logging!( + debug, + Type::Tray, + "托盘点击被防抖机制忽略,距离上次点击 {}ms", + now.duration_since(*last_click).as_millis() + ); false } } @@ -207,7 +211,7 @@ singleton_lazy!(Tray, TRAY, Tray::default); impl Tray { pub async fn init(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘初始化"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘初始化"); return Ok(()); } @@ -215,11 +219,15 @@ impl Tray { match self.create_tray_from_handle(app_handle).await { Ok(_) => { - log::info!(target: "app", "System tray created successfully"); + logging!(info, Type::Tray, "System tray created successfully"); } Err(e) => { // Don't return error, let application continue running without tray - log::warn!(target: "app", "System tray creation failed: {}, Application will continue running without tray icon", e); + logging!( + warn, + Type::Tray, + "System tray creation failed: {e}, Application will continue running without tray icon", + ); } } // TODO: 初始化时,暂时使用此方法更新系统托盘菜单,有效避免代理节点菜单空白 @@ -230,7 +238,7 @@ impl Tray { /// 更新托盘点击行为 pub async fn update_click_behavior(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘点击行为更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘点击行为更新"); return Ok(()); } @@ -250,7 +258,7 @@ impl Tray { /// 更新托盘菜单 pub async fn update_menu(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘菜单更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘菜单更新"); return Ok(()); } // 调整最小更新间隔,确保状态及时刷新 @@ -332,11 +340,15 @@ impl Tray { ) .await?, )); - log::debug!(target: "app", "托盘菜单更新成功"); + logging!(debug, Type::Tray, "托盘菜单更新成功"); Ok(()) } None => { - log::warn!(target: "app", "更新托盘菜单失败: 托盘不存在"); + logging!( + warn, + Type::Tray, + "Failed to update tray menu: tray not found" + ); Ok(()) } } @@ -346,7 +358,7 @@ impl Tray { #[cfg(target_os = "macos")] pub async fn update_icon(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘图标更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘图标更新"); return Ok(()); } @@ -355,7 +367,11 @@ impl Tray { let tray = match app_handle.tray_by_id("main") { Some(tray) => tray, None => { - log::warn!(target: "app", "更新托盘图标失败: 托盘不存在"); + logging!( + warn, + Type::Tray, + "Failed to update tray icon: tray not found" + ); return Ok(()); } }; @@ -385,7 +401,7 @@ impl Tray { #[cfg(not(target_os = "macos"))] pub async fn update_icon(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘图标更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘图标更新"); return Ok(()); } @@ -394,7 +410,11 @@ impl Tray { let tray = match app_handle.tray_by_id("main") { Some(tray) => tray, None => { - log::warn!(target: "app", "更新托盘图标失败: 托盘不存在"); + logging!( + warn, + Type::Tray, + "Failed to update tray icon: tray not found" + ); return Ok(()); } }; @@ -417,7 +437,7 @@ impl Tray { /// 更新托盘显示状态的函数 pub async fn update_tray_display(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘显示状态更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘显示状态更新"); return Ok(()); } @@ -435,7 +455,7 @@ impl Tray { /// 更新托盘提示 pub async fn update_tooltip(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘提示更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘提示更新"); return Ok(()); } @@ -491,7 +511,11 @@ impl Tray { if let Some(tray) = app_handle.tray_by_id("main") { let _ = tray.set_tooltip(Some(&tooltip)); } else { - log::warn!(target: "app", "更新托盘提示失败: 托盘不存在"); + logging!( + warn, + Type::Tray, + "Failed to update tray tooltip: tray not found" + ); } Ok(()) @@ -499,7 +523,7 @@ impl Tray { pub async fn update_part(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘局部更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘局部更新"); return Ok(()); } // self.update_menu().await?; @@ -512,11 +536,11 @@ impl Tray { pub async fn create_tray_from_handle(&self, app_handle: &AppHandle) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘创建"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘创建"); return Ok(()); } - log::info!(target: "app", "正在从AppHandle创建系统托盘"); + logging!(info, Type::Tray, "正在从AppHandle创建系统托盘"); // 获取图标 let icon_bytes = TrayState::get_common_tray_icon().await.1; @@ -562,7 +586,7 @@ impl Tray { AsyncHandler::spawn(|| async move { let tray_event = { Config::verge().await.latest_ref().tray_event.clone() }; let tray_event: String = tray_event.unwrap_or_else(|| "main_window".into()); - log::debug!(target: "app", "tray event: {tray_event:?}"); + logging!(debug, Type::Tray, "tray event: {tray_event:?}"); if let TrayIconEvent::Click { button: MouseButton::Left, @@ -597,14 +621,13 @@ impl Tray { }); }); tray.on_menu_event(on_menu_event); - log::info!(target: "app", "系统托盘创建成功"); Ok(()) } // 托盘统一的状态更新函数 pub async fn update_all_states(&self) -> Result<()> { if handle::Handle::global().is_exiting() { - log::debug!(target: "app", "应用正在退出,跳过托盘状态更新"); + logging!(debug, Type::Tray, "应用正在退出,跳过托盘状态更新"); return Ok(()); } @@ -731,7 +754,9 @@ fn create_subcreate_proxy_menu_item( is_selected, None::<&str>, ) - .map_err(|e| log::warn!(target: "app", "创建代理菜单项失败: {}", e)) + .map_err(|e| { + logging!(warn, Type::Tray, "Failed to create proxy menu item: {}", e) + }) .ok() }) .collect(); @@ -773,7 +798,12 @@ fn create_subcreate_proxy_menu_item( let insertion_index = submenus.len(); submenus.push((group_name.into(), insertion_index, submenu)); } else { - log::warn!(target: "app", "创建代理组子菜单失败: {}", group_name); + logging!( + warn, + Type::Tray, + "Failed to create proxy group submenu: {}", + group_name + ); } } } @@ -1166,7 +1196,7 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { feat::change_clash_mode(mode.into()).await; } MenuIds::DASHBOARD => { - log::info!(target: "app", "托盘菜单点击: 打开窗口"); + logging!(info, Type::Tray, "托盘菜单点击: 打开窗口"); if !should_handle_tray_click() { return; @@ -1183,7 +1213,11 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { } MenuIds::CLOSE_ALL_CONNECTIONS => { if let Err(err) = handle::Handle::mihomo().await.close_all_connections().await { - log::error!(target: "app", "Failed to close all connections from tray: {err}"); + logging!( + error, + Type::Tray, + "Failed to close all connections from tray: {err}" + ); } } MenuIds::COPY_ENV => feat::copy_clash_env().await, @@ -1236,12 +1270,25 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { .await { Ok(_) => { - log::info!(target: "app", "切换代理成功: {} -> {}", group_name, proxy_name); + logging!( + info, + Type::Tray, + "切换代理成功: {} -> {}", + group_name, + proxy_name + ); let _ = handle::Handle::app_handle() .emit("verge://refresh-proxy-config", ()); } Err(e) => { - log::error!(target: "app", "切换代理失败: {} -> {}, 错误: {:?}", group_name, proxy_name, e); + logging!( + error, + Type::Tray, + "切换代理失败: {} -> {}, 错误: {:?}", + group_name, + proxy_name, + e + ); // Fallback to IPC update if (handle::Handle::mihomo() @@ -1250,7 +1297,13 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { .await) .is_ok() { - log::info!(target: "app", "代理切换回退成功: {} -> {}", group_name, proxy_name); + logging!( + info, + Type::Tray, + "代理切换回退成功: {} -> {}", + group_name, + proxy_name + ); let app_handle = handle::Handle::app_handle(); let _ = app_handle.emit("verge://force-refresh-proxies", ()); @@ -1264,7 +1317,7 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { // Ensure tray state update is awaited and properly handled if let Err(e) = Tray::global().update_all_states().await { - log::warn!(target: "app", "更新托盘状态失败: {e}"); + logging!(warn, Type::Tray, "Failed to update tray state: {e}"); } }); } diff --git a/src-tauri/src/enhance/merge.rs b/src-tauri/src/enhance/merge.rs index 0210851d3..3d0e4bf92 100644 --- a/src-tauri/src/enhance/merge.rs +++ b/src-tauri/src/enhance/merge.rs @@ -1,3 +1,5 @@ +use crate::{logging, utils::logging::Type}; + use super::use_lowercase; use serde_yaml_ng::{self, Mapping, Value}; @@ -19,7 +21,11 @@ pub fn use_merge(merge: Mapping, config: Mapping) -> Mapping { deep_merge(&mut config, &Value::from(merge)); config.as_mapping().cloned().unwrap_or_else(|| { - log::error!("Failed to convert merged config to mapping, using empty mapping"); + logging!( + error, + Type::Core, + "Failed to convert merged config to mapping, using empty mapping" + ); Mapping::new() }) } diff --git a/src-tauri/src/enhance/mod.rs b/src-tauri/src/enhance/mod.rs index 05f2191bd..1deb49e57 100644 --- a/src-tauri/src/enhance/mod.rs +++ b/src-tauri/src/enhance/mod.rs @@ -8,6 +8,7 @@ mod tun; use self::{chain::*, field::*, merge::*, script::*, seq::*, tun::*}; use crate::utils::dirs; use crate::{config::Config, utils::tmpl}; +use crate::{logging, utils::logging::Type}; use serde_yaml_ng::Mapping; use smartstring::alias::String; use std::collections::{HashMap, HashSet}; @@ -422,14 +423,14 @@ fn apply_builtin_scripts( .filter(|(s, _)| s.is_support(clash_core.as_ref())) .map(|(_, c)| c) .for_each(|item| { - log::debug!(target: "app", "run builtin script {}", item.uid); + logging!(debug, Type::Core, "run builtin script {}", item.uid); if let ChainType::Script(script) = item.data { match use_script(script, config.to_owned(), "".into()) { Ok((res_config, _)) => { config = res_config; } Err(err) => { - log::error!(target: "app", "builtin script error `{err}`"); + logging!(error, Type::Core, "builtin script error `{err}`"); } } } @@ -451,17 +452,17 @@ async fn apply_dns_settings(mut config: Mapping, enable_dns_settings: bool) -> M && hosts_value.is_mapping() { config.insert("hosts".into(), hosts_value.clone()); - log::info!(target: "app", "apply hosts configuration"); + logging!(info, Type::Core, "apply hosts configuration"); } if let Some(dns_value) = dns_config.get("dns") { if let Some(dns_mapping) = dns_value.as_mapping() { config.insert("dns".into(), dns_mapping.clone().into()); - log::info!(target: "app", "apply dns_config.yaml (dns section)"); + logging!(info, Type::Core, "apply dns_config.yaml (dns section)"); } } else { config.insert("dns".into(), dns_config.into()); - log::info!(target: "app", "apply dns_config.yaml"); + logging!(info, Type::Core, "apply dns_config.yaml"); } } } diff --git a/src-tauri/src/enhance/tun.rs b/src-tauri/src/enhance/tun.rs index 92c8f0181..a09051fac 100644 --- a/src-tauri/src/enhance/tun.rs +++ b/src-tauri/src/enhance/tun.rs @@ -2,6 +2,8 @@ use serde_yaml_ng::{Mapping, Value}; #[cfg(target_os = "macos")] use crate::process::AsyncHandler; +#[cfg(target_os = "linux")] +use crate::{logging, utils::logging::Type}; macro_rules! revise { ($map: expr, $key: expr, $val: expr) => { @@ -42,9 +44,10 @@ pub fn use_tun(mut config: Mapping, enable: bool) -> Mapping { if should_override { revise!(tun_val, "stack", "mixed"); - log::warn!( - target: "app", - "gVisor TUN stack detected on Linux; falling back to 'mixed' for compatibility" + logging!( + warn, + Type::Network, + "Warning: gVisor TUN stack detected on Linux; falling back to 'mixed' for compatibility" ); } } diff --git a/src-tauri/src/feat/clash.rs b/src-tauri/src/feat/clash.rs index b4143a268..cf031d785 100644 --- a/src-tauri/src/feat/clash.rs +++ b/src-tauri/src/feat/clash.rs @@ -1,7 +1,7 @@ use crate::{ config::Config, core::{CoreManager, handle, tray}, - logging_error, + logging, logging_error, process::AsyncHandler, utils::{self, logging::Type, resolve}, }; @@ -17,7 +17,7 @@ pub async fn restart_clash_core() { } Err(err) => { handle::Handle::notice_message("set_config::error", format!("{err}")); - log::error!(target:"app", "{err}"); + logging!(error, Type::Core, "{err}"); } } } @@ -30,7 +30,7 @@ pub async fn restart_app() { "restart_app::error", format!("Failed to cleanup resources: {err}"), ); - log::error!(target:"app", "Restart failed during cleanup: {err}"); + logging!(error, Type::Core, "Restart failed during cleanup: {err}"); return; } @@ -50,7 +50,7 @@ fn after_change_clash_mode() { } } Err(err) => { - log::error!(target: "app", "Failed to get connections: {err}"); + logging!(error, Type::Core, "Failed to get connections: {err}"); } } }); @@ -64,7 +64,7 @@ pub async fn change_clash_mode(mode: String) { let json_value = serde_json::json!({ "mode": mode }); - log::debug!(target: "app", "change clash mode to {mode}"); + logging!(debug, Type::Core, "change clash mode to {mode}"); match handle::Handle::mihomo() .await .patch_base_config(&json_value) @@ -91,7 +91,7 @@ pub async fn change_clash_mode(mode: String) { after_change_clash_mode(); } } - Err(err) => log::error!(target: "app", "{err}"), + Err(err) => logging!(error, Type::Core, "{err}"), } } @@ -123,7 +123,7 @@ pub async fn test_delay(url: String) -> anyhow::Result { match response { Ok(response) => { - log::trace!(target: "app", "test_delay response: {response:#?}"); + logging!(trace, Type::Network, "test_delay response: {response:#?}"); if response.status().is_success() { Ok(start.elapsed().as_millis() as u32) } else { @@ -131,7 +131,7 @@ pub async fn test_delay(url: String) -> anyhow::Result { } } Err(err) => { - log::trace!(target: "app", "test_delay error: {err:#?}"); + logging!(trace, Type::Network, "test_delay error: {err:#?}"); Err(err) } } diff --git a/src-tauri/src/feat/profile.rs b/src-tauri/src/feat/profile.rs index 4ebd4d068..273022a5e 100644 --- a/src-tauri/src/feat/profile.rs +++ b/src-tauri/src/feat/profile.rs @@ -18,7 +18,7 @@ pub async fn toggle_proxy_profile(profile_index: String) { } } Err(err) => { - log::error!(target: "app", "{err}"); + logging!(error, Type::Tray, "{err}"); } } } @@ -33,10 +33,18 @@ async fn should_update_profile( let is_remote = item.itype.as_ref().is_some_and(|s| s == "remote"); if !is_remote { - log::info!(target: "app", "[订阅更新] {uid} 不是远程订阅,跳过更新"); + logging!( + info, + Type::Config, + "[订阅更新] {uid} 不是远程订阅,跳过更新" + ); Ok(None) } else if item.url.is_none() { - log::warn!(target: "app", "[订阅更新] {uid} 缺少URL,无法更新"); + logging!( + warn, + Type::Config, + "Warning: [订阅更新] {uid} 缺少URL,无法更新" + ); bail!("failed to get the profile item url"); } else if !ignore_auto_update && !item @@ -45,13 +53,22 @@ async fn should_update_profile( .and_then(|o| o.allow_auto_update) .unwrap_or(true) { - log::info!(target: "app", "[订阅更新] {} 禁止自动更新,跳过更新", uid); + logging!( + info, + Type::Config, + "[订阅更新] {} 禁止自动更新,跳过更新", + uid + ); Ok(None) } else { - log::info!(target: "app", + logging!( + info, + Type::Config, "[订阅更新] {} 是远程订阅,URL: {}", uid, - item.url.clone().ok_or_else(|| anyhow::anyhow!("Profile URL is None"))? + item.url + .clone() + .ok_or_else(|| anyhow::anyhow!("Profile URL is None"))? ); Ok(Some(( item.url @@ -68,20 +85,28 @@ async fn perform_profile_update( opt: Option<&PrfOption>, option: Option<&PrfOption>, ) -> Result { - log::info!(target: "app", "[订阅更新] 开始下载新的订阅内容"); + logging!(info, Type::Config, "[订阅更新] 开始下载新的订阅内容"); let merged_opt = PrfOption::merge(opt, option); match PrfItem::from_url(url, None, None, merged_opt.as_ref()).await { Ok(mut item) => { - log::info!(target: "app", "[订阅更新] 更新订阅配置成功"); + logging!(info, Type::Config, "[订阅更新] 更新订阅配置成功"); let profiles = Config::profiles().await; profiles_draft_update_item_safe(uid, &mut item).await?; let is_current = Some(uid.clone()) == profiles.latest_ref().get_current(); - log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}"); + logging!( + info, + Type::Config, + "[订阅更新] 是否为当前使用的订阅: {is_current}" + ); Ok(is_current) } Err(err) => { - log::warn!(target: "app", "[订阅更新] 正常更新失败: {err},尝试使用Clash代理更新"); + logging!( + warn, + Type::Config, + "Warning: [订阅更新] 正常更新失败: {err},尝试使用Clash代理更新" + ); handle::Handle::notice_message("update_retry_with_clash", uid.clone()); let original_with_proxy = merged_opt.as_ref().and_then(|o| o.with_proxy); @@ -93,7 +118,7 @@ async fn perform_profile_update( match PrfItem::from_url(url, None, None, Some(&fallback_opt)).await { Ok(mut item) => { - log::info!(target: "app", "[订阅更新] 使用Clash代理更新成功"); + logging!(info, Type::Config, "[订阅更新] 使用Clash代理更新成功"); if let Some(option) = item.option.as_mut() { option.with_proxy = original_with_proxy; @@ -107,11 +132,19 @@ async fn perform_profile_update( handle::Handle::notice_message("update_with_clash_proxy", profile_name); let is_current = Some(uid.clone()) == profiles.latest_ref().get_current(); - log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}"); + logging!( + info, + Type::Config, + "[订阅更新] 是否为当前使用的订阅: {is_current}" + ); Ok(is_current) } Err(retry_err) => { - log::error!(target: "app", "[订阅更新] 使用Clash代理更新仍然失败: {retry_err}"); + logging!( + error, + Type::Config, + "[订阅更新] 使用Clash代理更新仍然失败: {retry_err}" + ); handle::Handle::notice_message( "update_failed_even_with_clash", format!("{retry_err}"), @@ -149,7 +182,7 @@ pub async fn update_profile( Err(err) => { logging!(error, Type::Config, "[订阅更新] 更新失败: {}", err); handle::Handle::notice_message("update_failed", format!("{err}")); - log::error!(target: "app", "{err}"); + logging!(error, Type::Config, "{err}"); } } } diff --git a/src-tauri/src/feat/proxy.rs b/src-tauri/src/feat/proxy.rs index 67d94efb3..731cec20a 100644 --- a/src-tauri/src/feat/proxy.rs +++ b/src-tauri/src/feat/proxy.rs @@ -1,6 +1,8 @@ use crate::{ config::{Config, IVerge}, core::handle, + logging, + utils::logging::Type, }; use std::env; use tauri_plugin_clipboard_manager::ClipboardExt; @@ -16,7 +18,11 @@ pub async fn toggle_system_proxy() { && auto_close_connection && let Err(err) = handle::Handle::mihomo().await.close_all_connections().await { - log::error!(target: "app", "Failed to close all connections: {err}"); + logging!( + error, + Type::ProxyMode, + "Failed to close all connections: {err}" + ); } let patch_result = super::patch_verge( @@ -30,7 +36,7 @@ pub async fn toggle_system_proxy() { match patch_result { Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), + Err(err) => logging!(error, Type::ProxyMode, "{err}"), } } @@ -49,7 +55,7 @@ pub async fn toggle_tun_mode(not_save_file: Option) { .await { Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), + Err(err) => logging!(error, Type::ProxyMode, "{err}"), } } @@ -104,12 +110,16 @@ pub async fn copy_clash_env() { } "fish" => format!("set -x http_proxy {http_proxy}; set -x https_proxy {http_proxy}"), _ => { - log::error!(target: "app", "copy_clash_env: Invalid env type! {env_type}"); + logging!( + error, + Type::ProxyMode, + "copy_clash_env: Invalid env type! {env_type}" + ); return; } }; if cliboard.write_text(export_text).is_err() { - log::error!(target: "app", "Failed to write to clipboard"); + logging!(error, Type::ProxyMode, "Failed to write to clipboard"); } } diff --git a/src-tauri/src/feat/window.rs b/src-tauri/src/feat/window.rs index 246179e52..a23a41f2d 100644 --- a/src-tauri/src/feat/window.rs +++ b/src-tauri/src/feat/window.rs @@ -14,7 +14,7 @@ pub async fn open_or_close_dashboard() { async fn open_or_close_dashboard_internal() { let _ = lightweight::exit_lightweight_mode().await; let result = WindowManager::toggle_main_window().await; - log::info!(target: "app", "Window toggle result: {result:?}"); + logging!(info, Type::Window, "Window toggle result: {result:?}"); } pub async fn quit() { @@ -71,16 +71,20 @@ pub async fn clean_async() -> bool { .await { Ok(Ok(_)) => { - log::info!(target: "app", "TUN模式已禁用"); + logging!(info, Type::Window, "TUN模式已禁用"); true } Ok(Err(e)) => { - log::warn!(target: "app", "禁用TUN模式失败: {e}"); + logging!(warn, Type::Window, "Warning: 禁用TUN模式失败: {e}"); // 超时不阻塞退出 true } Err(_) => { - log::warn!(target: "app", "禁用TUN模式超时(可能系统正在关机),继续退出流程"); + logging!( + warn, + Type::Window, + "Warning: 禁用TUN模式超时(可能系统正在关机),继续退出流程" + ); true } } @@ -101,7 +105,7 @@ pub async fn clean_async() -> bool { .unwrap_or(false); if !sys_proxy_enabled { - log::info!(target: "app", "系统代理未启用,跳过重置"); + logging!(info, Type::Window, "系统代理未启用,跳过重置"); return true; } @@ -110,19 +114,23 @@ pub async fn clean_async() -> bool { if is_shutting_down { // sysproxy-rs 操作注册表(避免.exe的dll错误) - log::info!(target: "app", "检测到正在关机,syspro-rs操作注册表关闭系统代理"); + logging!( + info, + Type::Window, + "检测到正在关机,syspro-rs操作注册表关闭系统代理" + ); match Sysproxy::get_system_proxy() { Ok(mut sysproxy) => { sysproxy.enable = false; if let Err(e) = sysproxy.set_system_proxy() { - log::warn!(target: "app", "关机时关闭系统代理失败: {e}"); + logging!(warn, Type::Window, "Warning: 关机时关闭系统代理失败: {e}"); } else { - log::info!(target: "app", "系统代理已关闭(通过注册表)"); + logging!(info, Type::Window, "系统代理已关闭(通过注册表)"); } } Err(e) => { - log::warn!(target: "app", "关机时获取代理设置失败: {e}"); + logging!(warn, Type::Window, "Warning: 关机时获取代理设置失败: {e}"); } } @@ -136,7 +144,7 @@ pub async fn clean_async() -> bool { } // 正常退出:使用 sysproxy.exe 重置代理 - log::info!(target: "app", "sysproxy.exe重置系统代理"); + logging!(info, Type::Window, "sysproxy.exe重置系统代理"); match timeout( Duration::from_secs(2), @@ -145,15 +153,19 @@ pub async fn clean_async() -> bool { .await { Ok(Ok(_)) => { - log::info!(target: "app", "系统代理已重置"); + logging!(info, Type::Window, "系统代理已重置"); true } Ok(Err(e)) => { - log::warn!(target: "app", "重置系统代理失败: {e}"); + logging!(warn, Type::Window, "Warning: 重置系统代理失败: {e}"); true } Err(_) => { - log::warn!(target: "app", "重置系统代理超时,继续退出流程"); + logging!( + warn, + Type::Window, + "Warning: 重置系统代理超时,继续退出流程" + ); true } } @@ -169,11 +181,11 @@ pub async fn clean_async() -> bool { .unwrap_or(false); if !sys_proxy_enabled { - log::info!(target: "app", "系统代理未启用,跳过重置"); + logging!(info, Type::Window, "系统代理未启用,跳过重置"); return true; } - log::info!(target: "app", "开始重置系统代理..."); + logging!(info, Type::Window, "开始重置系统代理..."); match timeout( Duration::from_millis(1500), @@ -182,15 +194,15 @@ pub async fn clean_async() -> bool { .await { Ok(Ok(_)) => { - log::info!(target: "app", "系统代理已重置"); + logging!(info, Type::Window, "系统代理已重置"); true } Ok(Err(e)) => { - log::warn!(target: "app", "重置系统代理失败: {e}"); + logging!(warn, Type::Window, "Warning: 重置系统代理失败: {e}"); true } Err(_) => { - log::warn!(target: "app", "重置系统代理超时,继续退出"); + logging!(warn, Type::Window, "Warning: 重置系统代理超时,继续退出"); true } } @@ -206,11 +218,15 @@ pub async fn clean_async() -> bool { match timeout(stop_timeout, CoreManager::global().stop_core()).await { Ok(_) => { - log::info!(target: "app", "core已停止"); + logging!(info, Type::Window, "core已停止"); true } Err(_) => { - log::warn!(target: "app", "停止core超时(可能系统正在关机),继续退出"); + logging!( + warn, + Type::Window, + "Warning: 停止core超时(可能系统正在关机),继续退出" + ); true } } @@ -226,11 +242,11 @@ pub async fn clean_async() -> bool { .await { Ok(_) => { - log::info!(target: "app", "DNS设置已恢复"); + logging!(info, Type::Window, "DNS设置已恢复"); true } Err(_) => { - log::warn!(target: "app", "恢复DNS设置超时"); + logging!(warn, Type::Window, "Warning: 恢复DNS设置超时"); false } } diff --git a/src-tauri/src/module/lightweight.rs b/src-tauri/src/module/lightweight.rs index 2252cb656..d5c3900e1 100644 --- a/src-tauri/src/module/lightweight.rs +++ b/src-tauri/src/module/lightweight.rs @@ -168,7 +168,11 @@ fn setup_window_close_listener() { let handler_id = window.listen("tauri://close-requested", move |_event| { std::mem::drop(AsyncHandler::spawn(|| async { if let Err(e) = setup_light_weight_timer().await { - log::warn!("Failed to setup light weight timer: {e}"); + logging!( + warn, + Type::Lightweight, + "Warning: Failed to setup light weight timer: {e}" + ); } })); logging!(info, Type::Lightweight, "监听到关闭请求,开始轻量模式计时"); diff --git a/src-tauri/src/process/guard.rs b/src-tauri/src/process/guard.rs index e4a48909d..a776094fc 100644 --- a/src-tauri/src/process/guard.rs +++ b/src-tauri/src/process/guard.rs @@ -1,13 +1,20 @@ use anyhow::Result; use tauri_plugin_shell::process::CommandChild; +use crate::{logging, utils::logging::Type}; + #[derive(Debug)] pub struct CommandChildGuard(Option); impl Drop for CommandChildGuard { fn drop(&mut self) { if let Err(err) = self.kill() { - log::error!(target: "app", "Failed to kill child process: {}", err); + logging!( + error, + Type::Service, + "Failed to kill child process: {}", + err + ); } } } diff --git a/src-tauri/src/utils/autostart.rs b/src-tauri/src/utils/autostart.rs index 06d360ed4..b4dc4965a 100644 --- a/src-tauri/src/utils/autostart.rs +++ b/src-tauri/src/utils/autostart.rs @@ -1,7 +1,7 @@ #[cfg(target_os = "windows")] +use crate::{logging, utils::logging::Type}; +#[cfg(target_os = "windows")] use anyhow::{Result, anyhow}; -#[cfg(target_os = "windows")] -use log::info; #[cfg(target_os = "windows")] use std::{os::windows::process::CommandExt, path::Path, path::PathBuf}; @@ -49,15 +49,15 @@ pub async fn create_shortcut() -> Result<()> { .remove_if_exists() .await .inspect(|_| { - info!(target: "app", "成功移除旧启动快捷方式"); + logging!(info, Type::Setup, "成功移除旧启动快捷方式"); }) .inspect_err(|err| { - log::error!(target: "app", "移除旧启动快捷方式失败: {err}"); + logging!(error, Type::Setup, "移除旧启动快捷方式失败: {err}"); }); // 如果新快捷方式已存在,直接返回成功 if new_shortcut_path.exists() { - info!(target: "app", "启动快捷方式已存在"); + logging!(info, Type::Setup, "启动快捷方式已存在"); return Ok(()); } @@ -83,7 +83,7 @@ pub async fn create_shortcut() -> Result<()> { return Err(anyhow!("创建快捷方式失败: {}", error_msg)); } - info!(target: "app", "成功创建启动快捷方式"); + logging!(info, Type::Setup, "成功创建启动快捷方式"); Ok(()) } @@ -102,22 +102,22 @@ pub async fn remove_shortcut() -> Result<()> { .remove_if_exists() .await .inspect(|_| { - info!(target: "app", "成功删除旧启动快捷方式"); + logging!(info, Type::Setup, "成功删除旧启动快捷方式"); removed_any = true; }) .inspect_err(|err| { - log::error!(target: "app", "删除旧启动快捷方式失败: {err}"); + logging!(error, Type::Setup, "删除旧启动快捷方式失败: {err}"); }); let _ = new_shortcut_path .remove_if_exists() .await .inspect(|_| { - info!(target: "app", "成功删除启动快捷方式"); + logging!(info, Type::Setup, "成功删除启动快捷方式"); removed_any = true; }) .inspect_err(|err| { - log::error!(target: "app", "删除启动快捷方式失败: {err}"); + logging!(error, Type::Setup, "删除启动快捷方式失败: {err}"); }); Ok(()) diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs index cfae29fe5..b16d3d8ec 100644 --- a/src-tauri/src/utils/dirs.rs +++ b/src-tauri/src/utils/dirs.rs @@ -62,7 +62,11 @@ pub fn app_home_dir() -> Result { match app_handle.path().data_dir() { Ok(dir) => Ok(dir.join(APP_ID)), Err(e) => { - log::error!(target: "app", "Failed to get the app home directory: {e}"); + logging!( + error, + Type::File, + "Failed to get the app home directory: {e}" + ); Err(anyhow::anyhow!("Failed to get the app homedirectory")) } } @@ -76,7 +80,11 @@ pub fn app_resources_dir() -> Result { match app_handle.path().resource_dir() { Ok(dir) => Ok(dir.join("resources")), Err(e) => { - log::error!(target: "app", "Failed to get the resource directory: {e}"); + logging!( + error, + Type::File, + "Failed to get the resource directory: {e}" + ); Err(anyhow::anyhow!("Failed to get the resource directory")) } } @@ -229,7 +237,11 @@ pub fn ensure_mihomo_safe_dir() -> Option { if home_config.exists() || fs::create_dir_all(&home_config).is_ok() { Some(home_config) } else { - log::error!(target: "app", "Failed to create safe directory: {home_config:?}"); + logging!( + error, + Type::File, + "Failed to create safe directory: {home_config:?}" + ); None } }) diff --git a/src-tauri/src/utils/logging.rs b/src-tauri/src/utils/logging.rs index e623b0992..a73b18eba 100644 --- a/src-tauri/src/utils/logging.rs +++ b/src-tauri/src/utils/logging.rs @@ -29,7 +29,6 @@ pub enum Type { Lightweight, Network, ProxyMode, - // Cache, Validate, ClashVergeRev, } @@ -53,7 +52,6 @@ impl fmt::Display for Type { Type::Lightweight => write!(f, "[Lightweight]"), Type::Network => write!(f, "[Network]"), Type::ProxyMode => write!(f, "[ProxMode]"), - // Type::Cache => write!(f, "[Cache]"), Type::Validate => write!(f, "[Validate]"), Type::ClashVergeRev => write!(f, "[ClashVergeRev]"), } diff --git a/src-tauri/src/utils/resolve/dns.rs b/src-tauri/src/utils/resolve/dns.rs index 4b710bdc7..e225f0c80 100644 --- a/src-tauri/src/utils/resolve/dns.rs +++ b/src-tauri/src/utils/resolve/dns.rs @@ -1,20 +1,27 @@ #[cfg(target_os = "macos")] +use crate::{logging, utils::logging::Type}; pub async fn set_public_dns(dns_server: String) { - use crate::{core::handle, utils::dirs}; + use crate::utils::logging::Type; + use crate::{core::handle, logging, utils::dirs}; use tauri_plugin_shell::ShellExt; let app_handle = handle::Handle::app_handle(); - log::info!(target: "app", "try to set system dns"); + logging!(info, Type::Config, "try to set system dns"); let resource_dir = match dirs::app_resources_dir() { Ok(dir) => dir, Err(e) => { - log::error!(target: "app", "Failed to get resource directory: {}", e); + logging!( + error, + Type::Config, + "Failed to get resource directory: {}", + e + ); return; } }; let script = resource_dir.join("set_dns.sh"); if !script.exists() { - log::error!(target: "app", "set_dns.sh not found"); + logging!(error, Type::Config, "set_dns.sh not found"); return; } let script = script.to_string_lossy().into_owned(); @@ -28,14 +35,14 @@ pub async fn set_public_dns(dns_server: String) { { Ok(status) => { if status.success() { - log::info!(target: "app", "set system dns successfully"); + logging!(info, Type::Config, "set system dns successfully"); } else { let code = status.code().unwrap_or(-1); - log::error!(target: "app", "set system dns failed: {code}"); + logging!(error, Type::Config, "set system dns failed: {code}"); } } Err(err) => { - log::error!(target: "app", "set system dns failed: {err}"); + logging!(error, Type::Config, "set system dns failed: {err}"); } } } @@ -45,17 +52,22 @@ pub async fn restore_public_dns() { use crate::{core::handle, utils::dirs}; use tauri_plugin_shell::ShellExt; let app_handle = handle::Handle::app_handle(); - log::info!(target: "app", "try to unset system dns"); + logging!(info, Type::Config, "try to unset system dns"); let resource_dir = match dirs::app_resources_dir() { Ok(dir) => dir, Err(e) => { - log::error!(target: "app", "Failed to get resource directory: {}", e); + logging!( + error, + Type::Config, + "Failed to get resource directory: {}", + e + ); return; } }; let script = resource_dir.join("unset_dns.sh"); if !script.exists() { - log::error!(target: "app", "unset_dns.sh not found"); + logging!(error, Type::Config, "unset_dns.sh not found"); return; } let script = script.to_string_lossy().into_owned(); @@ -69,14 +81,14 @@ pub async fn restore_public_dns() { { Ok(status) => { if status.success() { - log::info!(target: "app", "unset system dns successfully"); + logging!(info, Type::Config, "unset system dns successfully"); } else { let code = status.code().unwrap_or(-1); - log::error!(target: "app", "unset system dns failed: {code}"); + logging!(error, Type::Config, "unset system dns failed: {code}"); } } Err(err) => { - log::error!(target: "app", "unset system dns failed: {err}"); + logging!(error, Type::Config, "unset system dns failed: {err}"); } } } diff --git a/src-tauri/src/utils/resolve/scheme.rs b/src-tauri/src/utils/resolve/scheme.rs index 487969a39..04659ab3a 100644 --- a/src-tauri/src/utils/resolve/scheme.rs +++ b/src-tauri/src/utils/resolve/scheme.rs @@ -11,7 +11,7 @@ use crate::{ }; pub(super) async fn resolve_scheme(param: &str) -> Result<()> { - log::info!(target:"app", "received deep link: {param}"); + logging!(info, Type::Config, "received deep link: {param}"); let param_str = if param.starts_with("[") && param.len() > 4 { param @@ -50,8 +50,8 @@ pub(super) async fn resolve_scheme(param: &str) -> Result<()> { match url_param { Some(ref url) => { - log::info!(target:"app", "decoded subscription url: {url}"); - match PrfItem::from_url(url, name, None, None).await { + logging!(info, Type::Config, "decoded subscription url: {url}"); + match PrfItem::from_url(url.as_ref(), name, None, None).await { Ok(mut item) => { let uid = match item.uid.clone() { Some(uid) => uid, diff --git a/src-tauri/src/utils/server.rs b/src-tauri/src/utils/server.rs index 12985c2ac..c5062a8c2 100644 --- a/src-tauri/src/utils/server.rs +++ b/src-tauri/src/utils/server.rs @@ -51,7 +51,11 @@ pub async fn check_singleton() -> Result<()> { .send() .await?; } - log::error!("failed to setup singleton listen server"); + logging!( + error, + Type::Window, + "failed to setup singleton listen server" + ); bail!("app exists"); } Ok(()) @@ -129,7 +133,7 @@ pub fn embed_server() { } pub fn shutdown_embedded_server() { - log::info!("shutting down embedded server"); + logging!(info, Type::Window, "shutting down embedded server"); if let Some(sender) = SHUTDOWN_SENDER.get() && let Some(sender) = sender.lock().take() { diff --git a/src-tauri/src/utils/window_manager.rs b/src-tauri/src/utils/window_manager.rs index 463f8c39d..2d5b7a1b7 100644 --- a/src-tauri/src/utils/window_manager.rs +++ b/src-tauri/src/utils/window_manager.rs @@ -58,7 +58,11 @@ fn get_window_operation_debounce() -> &'static Mutex { fn should_handle_window_operation() -> bool { if WINDOW_OPERATION_IN_PROGRESS.load(Ordering::Acquire) { - log::warn!(target: "app", "[防抖] 窗口操作已在进行中,跳过重复调用"); + logging!( + warn, + Type::Window, + "Warning: [防抖] 窗口操作已在进行中,跳过重复调用" + ); return false; } @@ -67,17 +71,27 @@ fn should_handle_window_operation() -> bool { let now = Instant::now(); let elapsed = now.duration_since(*last_operation); - log::debug!(target: "app", "[防抖] 检查窗口操作间隔: {}ms (需要>={}ms)", - elapsed.as_millis(), WINDOW_OPERATION_DEBOUNCE_MS); + logging!( + debug, + Type::Window, + "[防抖] 检查窗口操作间隔: {}ms (需要>={}ms)", + elapsed.as_millis(), + WINDOW_OPERATION_DEBOUNCE_MS + ); if elapsed >= Duration::from_millis(WINDOW_OPERATION_DEBOUNCE_MS) { *last_operation = now; WINDOW_OPERATION_IN_PROGRESS.store(true, Ordering::Release); - log::info!(target: "app", "[防抖] 窗口操作被允许执行"); + logging!(info, Type::Window, "[防抖] 窗口操作被允许执行"); true } else { - log::warn!(target: "app", "[防抖] 窗口操作被防抖机制忽略,距离上次操作 {}ms < {}ms", - elapsed.as_millis(), WINDOW_OPERATION_DEBOUNCE_MS); + logging!( + warn, + Type::Window, + "Warning: [防抖] 窗口操作被防抖机制忽略,距离上次操作 {}ms < {}ms", + elapsed.as_millis(), + WINDOW_OPERATION_DEBOUNCE_MS + ); false } }