diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 02df8ef3..ab898d5c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -962,6 +962,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.2.40" @@ -1101,6 +1110,7 @@ dependencies = [ "chrono", "clash_verge_logger", "clash_verge_service_ipc", + "compact_str", "console-subscriber", "criterion", "dashmap 6.1.0", @@ -1232,7 +1242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -1245,6 +1255,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "compact_str" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +dependencies = [ + "castaway 0.2.4", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "serde", + "static_assertions", +] + [[package]] name = "concat-idents" version = "1.1.5" @@ -3196,7 +3221,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.0", "system-configuration", "tokio", "tower-service", @@ -3648,7 +3673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" dependencies = [ "async-channel 1.9.0", - "castaway", + "castaway 0.1.2", "crossbeam-utils", "curl", "curl-sys", @@ -5644,7 +5669,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.0", "thiserror 2.0.17", "tokio", "tracing", @@ -5681,7 +5706,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.0", "tracing", "windows-sys 0.60.2", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bec1a355..32144c51 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -88,6 +88,7 @@ clash_verge_logger = { version = "0.1.0", git = "https://github.com/clash-verge- clash_verge_service_ipc = { version = "2.0.15", features = [ "client", ], git = "https://github.com/clash-verge-rev/clash-verge-service-ipc" } +compact_str = { version = "0.9.0", features = ["serde"] } # clash_verge_service_ipc = { version = "2.0.14", features = [ # "client", # ], path = "../../clash-verge-service-ipc" } diff --git a/src-tauri/src/cmd/clash.rs b/src-tauri/src/cmd/clash.rs index 511c7d01..f3ed10ac 100644 --- a/src-tauri/src/cmd/clash.rs +++ b/src-tauri/src/cmd/clash.rs @@ -6,6 +6,7 @@ use crate::{ core::{CoreManager, handle}, }; use crate::{config::*, feat, logging, utils::logging::Type, wrap_err}; +use compact_str::CompactString; use serde_yaml_ng::Mapping; /// 复制Clash环境变量 @@ -285,7 +286,7 @@ pub async fn validate_dns_config() -> CmdResult<(bool, String)> { } #[tauri::command] -pub async fn get_clash_logs() -> CmdResult> { +pub async fn get_clash_logs() -> CmdResult> { let logs = CoreManager::global() .get_clash_logs() .await diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 8af585b7..650d8ec3 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -2,7 +2,7 @@ use crate::AsyncHandler; use crate::core::logger::ClashLogger; use crate::process::CommandChildGuard; use crate::utils::init::sidecar_writer; -use crate::utils::logging::SharedWriter; +use crate::utils::logging::{SharedWriter, write_sidecar_log}; use crate::{ config::*, core::{ @@ -17,9 +17,9 @@ use crate::{ }, }; use anyhow::Result; +use compact_str::CompactString; use flexi_logger::DeferredNow; -use flexi_logger::writers::LogWriter; -use log::Record; +use log::Level; use parking_lot::Mutex; use std::collections::VecDeque; use std::{fmt, path::PathBuf, sync::Arc}; @@ -58,29 +58,6 @@ impl fmt::Display for RunningMode { use crate::config::IVerge; -fn write_sidecar_log( - writer: &dyn LogWriter, - now: &mut DeferredNow, - level: log::Level, - message: String, -) -> String { - let boxed = message.into_boxed_str(); - let leaked: &'static mut str = Box::leak(boxed); - let leaked_ptr = leaked as *mut str; - { - let _ = writer.write( - now, - &Record::builder() - .args(format_args!("{}", &*leaked)) - .level(level) - .target("sidecar") - .build(), - ); - } - // SAFETY: `leaked` originated from `Box::leak` above; reboxing frees it immediately after use. - unsafe { String::from(Box::from_raw(leaked_ptr)) } -} - impl CoreManager { /// 检查文件是否为脚本文件 fn is_script_file(&self, path: &str) -> Result { @@ -767,30 +744,35 @@ impl CoreManager { AsyncHandler::spawn(|| async move { while let Some(event) = rx.recv().await { - let w = shared_writer.lock().await; match event { tauri_plugin_shell::process::CommandEvent::Stdout(line) => { let mut now = DeferredNow::default(); - let message = String::from_utf8_lossy(&line).into_owned(); - let message = write_sidecar_log(&*w, &mut now, log::Level::Error, message); + let message = + CompactString::from(String::from_utf8_lossy(&line).into_owned()); + let w = shared_writer.lock().await; + write_sidecar_log(w, &mut now, Level::Error, &message); ClashLogger::global().append_log(message); } tauri_plugin_shell::process::CommandEvent::Stderr(line) => { let mut now = DeferredNow::default(); - let message = String::from_utf8_lossy(&line).into_owned(); - let message = write_sidecar_log(&*w, &mut now, log::Level::Error, message); + let message = + CompactString::from(String::from_utf8_lossy(&line).into_owned()); + let w = shared_writer.lock().await; + write_sidecar_log(w, &mut now, Level::Error, &message); ClashLogger::global().append_log(message); } tauri_plugin_shell::process::CommandEvent::Terminated(term) => { let mut now = DeferredNow::default(); let message = if let Some(code) = term.code { - format!("Process terminated with code: {}", code) + CompactString::from(format!("Process terminated with code: {}", code)) } else if let Some(signal) = term.signal { - format!("Process terminated by signal: {}", signal) + CompactString::from(format!("Process terminated by signal: {}", signal)) } else { - "Process terminated".to_string() + CompactString::from("Process terminated") }; - write_sidecar_log(&*w, &mut now, log::Level::Info, message); + let w = shared_writer.lock().await; + write_sidecar_log(w, &mut now, Level::Info, &message); + ClashLogger::global().clear_logs(); break; } _ => {} @@ -899,10 +881,15 @@ impl CoreManager { Ok(()) } - pub async fn get_clash_logs(&self) -> Result> { + pub async fn get_clash_logs(&self) -> Result> { logging!(info, Type::Core, "get clash logs"); let logs = match self.get_running_mode() { - RunningMode::Service => service::get_clash_logs_by_service().await?, + // TODO 服务端也完成 CompactString 迁移 + RunningMode::Service => service::get_clash_logs_by_service() + .await? + .into_iter() + .map(CompactString::from) + .collect::>(), RunningMode::Sidecar => ClashLogger::global().get_logs().clone(), _ => VecDeque::new(), }; diff --git a/src-tauri/src/core/logger.rs b/src-tauri/src/core/logger.rs index cc3c1afb..ff3d8a0e 100644 --- a/src-tauri/src/core/logger.rs +++ b/src-tauri/src/core/logger.rs @@ -1,12 +1,13 @@ use std::{collections::VecDeque, sync::Arc}; +use compact_str::CompactString; use once_cell::sync::OnceCell; use parking_lot::{RwLock, RwLockReadGuard}; const LOGS_QUEUE_LEN: usize = 100; pub struct ClashLogger { - logs: Arc>>, + logs: Arc>>, } impl ClashLogger { @@ -18,11 +19,11 @@ impl ClashLogger { }) } - pub fn get_logs(&self) -> RwLockReadGuard<'_, VecDeque> { + pub fn get_logs(&self) -> RwLockReadGuard<'_, VecDeque> { self.logs.read() } - pub fn append_log(&self, text: String) { + pub fn append_log(&self, text: CompactString) { let mut logs = self.logs.write(); if logs.len() > LOGS_QUEUE_LEN { logs.pop_front(); diff --git a/src-tauri/src/utils/logging.rs b/src-tauri/src/utils/logging.rs index dd8d8cf7..7a00afe6 100644 --- a/src-tauri/src/utils/logging.rs +++ b/src-tauri/src/utils/logging.rs @@ -1,10 +1,13 @@ +use compact_str::CompactString; use flexi_logger::writers::FileLogWriter; +use flexi_logger::writers::LogWriter; #[cfg(not(feature = "tauri-dev"))] use flexi_logger::{DeferredNow, filter::LogLineFilter}; +use log::Level; #[cfg(not(feature = "tauri-dev"))] use log::Record; use std::{fmt, sync::Arc}; -use tokio::sync::Mutex; +use tokio::sync::{Mutex, MutexGuard}; pub type SharedWriter = Arc>; @@ -134,6 +137,23 @@ macro_rules! logging_error { }; } +pub fn write_sidecar_log( + writer: MutexGuard<'_, FileLogWriter>, + now: &mut DeferredNow, + level: Level, + message: &CompactString, +) { + let args = format_args!("{}", message); + + let record = Record::builder() + .args(args) + .level(level) + .target("sidecar") + .build(); + + let _ = writer.write(now, &record); +} + #[cfg(not(feature = "tauri-dev"))] pub struct NoModuleFilter<'a>(pub &'a [&'a str]);