mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-23 20:22:12 +08:00
* refactor(log): migrate logging to tracing-estuary pipeline Swap flexi_logger + clash-verge-logger wiring for the tracing-estuary crate: buffered file sink with explicit panic/exit drains, live level switching, and tokio-trace/chrome-trace behind crate features. AsyncLogger moves in-house (VecDeque ring); file format and rotation stay unchanged. * fix(log): reset sidecar writer in place and re-pin service-ipc v2.6.7 Rebuilding the sidecar FileLogWriter on config changes leaked flexi's unstoppable flusher thread plus an fd each time; the writer is now flushed and reset in place, matching what the service crate does. get_clash_logs_by_service drops the CompactString conversion layer now that service-ipc v2.6.7 returns plain Vec<String>, and AsyncLogger is renamed LogRing to match. * refactor(log): span-based observability and log noise cleanup Instrument spans carry the structure flat lines never could: the core-start spine (mode, readiness/owner generations, pid, config file), proxy apply and clear routes with guard generations, service IPC sessions with refusal codes and outcomes, profile-switch terminal outcomes, subscription fetch strategies, core upgrades with per-proxy version probes, backup flows, timer tasks, config generation uids, and the startup setup flow; running-mode changes emit one guarded transition event each. ~90 hand-written noise lines are gone or demoted (entry+success pairs, polled getter echoes, phase brackets, window sub-steps, platform install chatter); errors keep their anyhow chain, operation name, and item id, and swallowed retry results surface per attempt.
144 lines
4.5 KiB
Rust
144 lines
4.5 KiB
Rust
use clash_verge_logging::{Type, logging};
|
|
#[cfg(target_os = "macos")]
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
#[cfg(target_os = "macos")]
|
|
const DNS_STATE_FILE: &str = ".original_dns.txt";
|
|
|
|
fn dns_state_dir() -> anyhow::Result<PathBuf> {
|
|
// The DNS scripts persist .original_dns.txt relative to their working directory.
|
|
let dir = crate::utils::dirs::app_home_dir()?;
|
|
std::fs::create_dir_all(&dir)?;
|
|
Ok(dir)
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
fn restore_dns_state_dir(resource_dir: &Path, state_dir: PathBuf) -> PathBuf {
|
|
if resource_dir.join(DNS_STATE_FILE).exists() {
|
|
resource_dir.to_path_buf()
|
|
} else {
|
|
state_dir
|
|
}
|
|
}
|
|
|
|
pub async fn set_public_dns(dns_server: String) {
|
|
use crate::{core::handle, utils::dirs};
|
|
use tauri_plugin_shell::ShellExt as _;
|
|
let app_handle = handle::Handle::app_handle();
|
|
|
|
logging!(debug, Type::Config, "try to set system dns");
|
|
let resource_dir = match dirs::app_resources_dir() {
|
|
Ok(dir) => dir,
|
|
Err(e) => {
|
|
logging!(error, Type::Config, "Failed to get resource directory: {}", e);
|
|
return;
|
|
}
|
|
};
|
|
let script = resource_dir.join("set_dns.sh");
|
|
if !script.exists() {
|
|
logging!(error, Type::Config, "set_dns.sh not found");
|
|
return;
|
|
}
|
|
let script = script.to_string_lossy().into_owned();
|
|
let state_dir = match dns_state_dir() {
|
|
Ok(dir) => dir,
|
|
Err(e) => {
|
|
logging!(error, Type::Config, "Failed to get DNS state directory: {}", e);
|
|
return;
|
|
}
|
|
};
|
|
match app_handle
|
|
.shell()
|
|
.command("bash")
|
|
.args([script, dns_server])
|
|
.current_dir(state_dir)
|
|
.status()
|
|
.await
|
|
{
|
|
Ok(status) => {
|
|
if status.success() {
|
|
logging!(info, Type::Config, "set system dns successfully");
|
|
} else {
|
|
let code = status.code().unwrap_or(-1);
|
|
logging!(error, Type::Config, "set system dns failed: {code}");
|
|
}
|
|
}
|
|
Err(err) => {
|
|
logging!(error, Type::Config, "set system dns failed: {err}");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
pub async fn restore_public_dns() {
|
|
use crate::{core::handle, utils::dirs};
|
|
use tauri_plugin_shell::ShellExt as _;
|
|
let app_handle = handle::Handle::app_handle();
|
|
logging!(debug, Type::Config, "try to unset system dns");
|
|
let resource_dir = match dirs::app_resources_dir() {
|
|
Ok(dir) => dir,
|
|
Err(e) => {
|
|
logging!(error, Type::Config, "Failed to get resource directory: {}", e);
|
|
return;
|
|
}
|
|
};
|
|
let script = resource_dir.join("unset_dns.sh");
|
|
if !script.exists() {
|
|
logging!(error, Type::Config, "unset_dns.sh not found");
|
|
return;
|
|
}
|
|
let script = script.to_string_lossy().into_owned();
|
|
let state_dir = match dns_state_dir() {
|
|
Ok(dir) => dir,
|
|
Err(e) => {
|
|
logging!(error, Type::Config, "Failed to get DNS state directory: {}", e);
|
|
return;
|
|
}
|
|
};
|
|
let state_dir = restore_dns_state_dir(&resource_dir, state_dir);
|
|
match app_handle
|
|
.shell()
|
|
.command("bash")
|
|
.args([script])
|
|
.current_dir(state_dir)
|
|
.status()
|
|
.await
|
|
{
|
|
Ok(status) => {
|
|
if status.success() {
|
|
logging!(info, Type::Config, "unset system dns successfully");
|
|
} else {
|
|
let code = status.code().unwrap_or(-1);
|
|
logging!(error, Type::Config, "unset system dns failed: {code}");
|
|
}
|
|
}
|
|
Err(err) => {
|
|
logging!(error, Type::Config, "unset system dns failed: {err}");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
#[test]
|
|
#[allow(clippy::expect_used)]
|
|
#[cfg(target_os = "macos")]
|
|
fn restore_dns_state_dir_defaults_to_app_data_but_honors_legacy_file() {
|
|
use super::restore_dns_state_dir;
|
|
|
|
let root = std::env::temp_dir().join(format!("clash-verge-dns-{}", nanoid::nanoid!()));
|
|
let resource_dir = root.join("resources");
|
|
let state_dir = root.join("app-data");
|
|
std::fs::create_dir_all(&resource_dir).expect("create test resource directory");
|
|
|
|
assert_eq!(restore_dns_state_dir(&resource_dir, state_dir.clone()), state_dir);
|
|
|
|
std::fs::write(resource_dir.join(".original_dns.txt"), "empty").expect("create legacy DNS state");
|
|
assert_eq!(restore_dns_state_dir(&resource_dir, state_dir), resource_dir);
|
|
|
|
std::fs::remove_dir_all(root).expect("remove test directory");
|
|
}
|
|
}
|