mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
feat: reconfig log dynamically (#5724)
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -156,7 +156,7 @@ dependencies = [
|
||||
"objc2-foundation 0.3.2",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.59.0",
|
||||
"wl-clipboard-rs",
|
||||
"x11rb",
|
||||
]
|
||||
@@ -1354,8 +1354,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clash_verge_service_ipc"
|
||||
version = "2.0.27"
|
||||
source = "git+https://github.com/clash-verge-rev/clash-verge-service-ipc#43274f2db38959090797b35416c404ee482e8744"
|
||||
version = "2.0.28"
|
||||
source = "git+https://github.com/clash-verge-rev/clash-verge-service-ipc#cac4cd880dac2488c95e0b214377fcdde4f147d0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"compact_str",
|
||||
@@ -2151,7 +2151,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2424,7 +2424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3986,7 +3986,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
||||
dependencies = [
|
||||
"hermit-abi 0.5.2",
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4792,7 +4792,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6117,7 +6117,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6732,7 +6732,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6790,7 +6790,7 @@ dependencies = [
|
||||
"security-framework 3.5.1",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8323,7 +8323,7 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix 1.1.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -11,4 +11,3 @@ flexi_logger = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
tauri-dev = []
|
||||
@@ -1,6 +1,5 @@
|
||||
use compact_str::CompactString;
|
||||
use flexi_logger::DeferredNow;
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
use flexi_logger::filter::LogLineFilter;
|
||||
use flexi_logger::writers::FileLogWriter;
|
||||
use flexi_logger::writers::LogWriter as _;
|
||||
@@ -98,15 +97,13 @@ pub fn write_sidecar_log(
|
||||
let _ = writer.write(now, &record);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
pub struct NoModuleFilter<'a>(pub &'a [&'a str]);
|
||||
pub struct NoModuleFilter<'a>(pub Vec<&'a str>);
|
||||
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
impl<'a> NoModuleFilter<'a> {
|
||||
#[inline]
|
||||
pub fn filter(&self, record: &Record) -> bool {
|
||||
if let Some(module) = record.module_path() {
|
||||
for blocked in self.0 {
|
||||
for blocked in self.0.iter() {
|
||||
if module.len() >= blocked.len() && module.as_bytes()[..blocked.len()] == blocked.as_bytes()[..] {
|
||||
return false;
|
||||
}
|
||||
@@ -116,7 +113,6 @@ impl<'a> NoModuleFilter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
impl<'a> LogLineFilter for NoModuleFilter<'a> {
|
||||
#[inline]
|
||||
fn write(
|
||||
|
||||
@@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
default = ["custom-protocol"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
verge-dev = ["clash_verge_logger/color"]
|
||||
tauri-dev = ["clash-verge-logging/tauri-dev"]
|
||||
tauri-dev = []
|
||||
tokio-trace = ["console-subscriber"]
|
||||
clippy = ["tauri/test"]
|
||||
tracing = []
|
||||
@@ -65,7 +65,12 @@ boa_engine = "0.21.0"
|
||||
once_cell = { version = "1.21.3", features = ["parking_lot"] }
|
||||
delay_timer = "0.11.6"
|
||||
percent-encoding = "2.3.2"
|
||||
reqwest = { version = "0.13.1", features = ["json", "cookies", "rustls", "form"] }
|
||||
reqwest = { version = "0.13.1", features = [
|
||||
"json",
|
||||
"cookies",
|
||||
"rustls",
|
||||
"form",
|
||||
] }
|
||||
regex = "1.12.2"
|
||||
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", features = [
|
||||
"guard",
|
||||
@@ -94,7 +99,7 @@ tauri-plugin-devtools = { version = "2.0.1" }
|
||||
tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo" }
|
||||
clash_verge_logger = { git = "https://github.com/clash-verge-rev/clash-verge-logger" }
|
||||
async-trait = "0.1.89"
|
||||
clash_verge_service_ipc = { version = "2.0.27", features = [
|
||||
clash_verge_service_ipc = { version = "2.0.28", features = [
|
||||
"client",
|
||||
], git = "https://github.com/clash-verge-rev/clash-verge-service-ipc" }
|
||||
arc-swap = "1.8.0"
|
||||
|
||||
@@ -1 +1,223 @@
|
||||
// TODO: global logger to record verge log message
|
||||
use std::{
|
||||
str::FromStr as _,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicU64, AtomicUsize, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use clash_verge_service_ipc::WriterConfig;
|
||||
use compact_str::CompactString;
|
||||
use flexi_logger::{
|
||||
Cleanup, Criterion, DeferredNow, FileSpec, LogSpecBuilder, LogSpecification, LoggerHandle,
|
||||
writers::{FileLogWriter, FileLogWriterBuilder, LogWriter as _},
|
||||
};
|
||||
use log::{Level, LevelFilter, Record};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
|
||||
use crate::{
|
||||
core::service,
|
||||
singleton,
|
||||
utils::dirs::{self, service_log_dir, sidecar_log_dir},
|
||||
};
|
||||
|
||||
pub struct Logger {
|
||||
handle: Arc<Mutex<Option<LoggerHandle>>>,
|
||||
sidecar_file_writer: Arc<RwLock<Option<FileLogWriter>>>,
|
||||
log_level: Arc<RwLock<LevelFilter>>,
|
||||
log_max_size: AtomicU64,
|
||||
log_max_count: AtomicUsize,
|
||||
}
|
||||
|
||||
impl Default for Logger {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
handle: Arc::new(Mutex::new(None)),
|
||||
sidecar_file_writer: Arc::new(RwLock::new(None)),
|
||||
log_level: Arc::new(RwLock::new(LevelFilter::Info)),
|
||||
log_max_size: AtomicU64::new(128),
|
||||
log_max_count: AtomicUsize::new(8),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
singleton!(Logger, LOGGER);
|
||||
|
||||
impl Logger {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub async fn init(&self) -> Result<()> {
|
||||
let (log_level, log_max_size, log_max_count) = {
|
||||
let verge_guard = crate::config::Config::verge().await;
|
||||
let verge = verge_guard.latest_arc();
|
||||
(
|
||||
verge.get_log_level(),
|
||||
verge.app_log_max_size.unwrap_or(128),
|
||||
verge.app_log_max_count.unwrap_or(8),
|
||||
)
|
||||
};
|
||||
let log_level = std::env::var("RUST_LOG")
|
||||
.ok()
|
||||
.and_then(|v| log::LevelFilter::from_str(&v).ok())
|
||||
.unwrap_or(log_level);
|
||||
*self.log_level.write() = log_level;
|
||||
self.log_max_size.store(log_max_size, Ordering::SeqCst);
|
||||
self.log_max_count.store(log_max_count, Ordering::SeqCst);
|
||||
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
{
|
||||
let log_spec = Self::generate_log_spec(log_level);
|
||||
let log_dir = dirs::app_logs_dir()?;
|
||||
let logger = flexi_logger::Logger::with(log_spec)
|
||||
.log_to_file(FileSpec::default().directory(log_dir).basename(""))
|
||||
.duplicate_to_stdout(log_level.into())
|
||||
.format(clash_verge_logger::console_format)
|
||||
.format_for_files(clash_verge_logger::file_format_with_level)
|
||||
.rotate(
|
||||
Criterion::Size(log_max_size * 1024),
|
||||
flexi_logger::Naming::TimestampsCustomFormat {
|
||||
current_infix: Some("latest"),
|
||||
format: "%Y-%m-%d_%H-%M-%S",
|
||||
},
|
||||
Cleanup::KeepLogFiles(log_max_count),
|
||||
);
|
||||
|
||||
let mut filter_modules = vec!["wry", "tokio_tungstenite", "tungstenite"];
|
||||
#[cfg(not(feature = "tracing"))]
|
||||
filter_modules.push("tauri");
|
||||
#[cfg(feature = "tracing")]
|
||||
filter_modules.extend(["tauri_plugin_mihomo", "kode_bridge"]);
|
||||
let logger = logger.filter(Box::new(clash_verge_logging::NoModuleFilter(filter_modules)));
|
||||
|
||||
let handle = logger.start()?;
|
||||
*self.handle.lock() = Some(handle);
|
||||
}
|
||||
|
||||
let sidecar_file_writer = self.generate_sidecar_writer()?;
|
||||
*self.sidecar_file_writer.write() = Some(sidecar_file_writer);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_log_spec(log_level: LevelFilter) -> LogSpecification {
|
||||
let mut spec = LogSpecBuilder::new();
|
||||
let log_level = std::env::var("RUST_LOG")
|
||||
.ok()
|
||||
.and_then(|v| log::LevelFilter::from_str(&v).ok())
|
||||
.unwrap_or(log_level);
|
||||
spec.default(log_level);
|
||||
#[cfg(feature = "tracing")]
|
||||
spec.module("tauri", log::LevelFilter::Debug)
|
||||
.module("wry", log::LevelFilter::Off)
|
||||
.module("tauri_plugin_mihomo", log::LevelFilter::Off);
|
||||
spec.build()
|
||||
}
|
||||
|
||||
fn generate_file_log_writer(&self) -> Result<FileLogWriterBuilder> {
|
||||
let log_dir = dirs::app_logs_dir()?;
|
||||
let log_max_size = self.log_max_size.load(Ordering::SeqCst);
|
||||
let log_max_count = self.log_max_count.load(Ordering::SeqCst);
|
||||
let flwb = FileLogWriter::builder(FileSpec::default().directory(log_dir).basename("")).rotate(
|
||||
Criterion::Size(log_max_size * 1024),
|
||||
flexi_logger::Naming::TimestampsCustomFormat {
|
||||
current_infix: Some("latest"),
|
||||
format: "%Y-%m-%d_%H-%M-%S",
|
||||
},
|
||||
Cleanup::KeepLogFiles(log_max_count),
|
||||
);
|
||||
Ok(flwb)
|
||||
}
|
||||
|
||||
/// only update app log level
|
||||
pub fn update_log_level(&self, level: LevelFilter) -> Result<()> {
|
||||
println!("refresh log level");
|
||||
*self.log_level.write() = level;
|
||||
let log_level = self.log_level.read().to_owned();
|
||||
if let Some(handle) = self.handle.lock().as_mut() {
|
||||
let log_spec = Self::generate_log_spec(log_level);
|
||||
handle.set_new_spec(log_spec);
|
||||
handle.adapt_duplication_to_stdout(log_level.into())?;
|
||||
} else {
|
||||
bail!("failed to get logger handle, make sure it init");
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// update app and mihomo core log config
|
||||
pub async fn update_log_config(&self, log_max_size: u64, log_max_count: usize) -> Result<()> {
|
||||
println!("refresh log file");
|
||||
self.log_max_size.store(log_max_size, Ordering::SeqCst);
|
||||
self.log_max_count.store(log_max_count, Ordering::SeqCst);
|
||||
if let Some(handle) = self.handle.lock().as_ref() {
|
||||
let log_file_writer = self.generate_file_log_writer()?;
|
||||
handle.reset_flw(&log_file_writer)?;
|
||||
} else {
|
||||
bail!("failed to get logger handle, make sure it init");
|
||||
};
|
||||
let sidecar_writer = self.generate_sidecar_writer()?;
|
||||
*self.sidecar_file_writer.write() = Some(sidecar_writer);
|
||||
|
||||
// update service writer config
|
||||
if service::is_service_ipc_path_exists() && service::is_service_available().await.is_ok() {
|
||||
let service_log_dir = dirs::path_to_str(&service_log_dir()?)?.into();
|
||||
clash_verge_service_ipc::update_writer(&WriterConfig {
|
||||
directory: service_log_dir,
|
||||
max_log_size: log_max_size * 1024,
|
||||
max_log_files: log_max_count,
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_sidecar_writer(&self) -> Result<FileLogWriter> {
|
||||
let sidecar_log_dir = sidecar_log_dir()?;
|
||||
let log_max_size = self.log_max_size.load(Ordering::SeqCst);
|
||||
let log_max_count = self.log_max_count.load(Ordering::SeqCst);
|
||||
Ok(FileLogWriter::builder(
|
||||
FileSpec::default()
|
||||
.directory(sidecar_log_dir)
|
||||
.basename("sidecar")
|
||||
.suppress_timestamp(),
|
||||
)
|
||||
.format(clash_verge_logger::file_format_without_level)
|
||||
.rotate(
|
||||
Criterion::Size(log_max_size * 1024),
|
||||
flexi_logger::Naming::TimestampsCustomFormat {
|
||||
current_infix: Some("latest"),
|
||||
format: "%Y-%m-%d_%H-%M-%S",
|
||||
},
|
||||
Cleanup::KeepLogFiles(log_max_count),
|
||||
)
|
||||
.try_build()?)
|
||||
}
|
||||
|
||||
pub fn writer_sidecar_log(&self, level: Level, message: &CompactString) {
|
||||
if let Some(writer) = self.sidecar_file_writer.read().as_ref() {
|
||||
let mut now = DeferredNow::default();
|
||||
let args = format_args!("{}", message);
|
||||
let record = Record::builder().args(args).level(level).target("sidecar").build();
|
||||
let _ = writer.write(&mut now, &record);
|
||||
} else {
|
||||
logging!(error, Type::System, "failed to get sidecar file log writer");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn service_writer_config(&self) -> Result<WriterConfig> {
|
||||
let service_log_dir = dirs::path_to_str(&service_log_dir()?)?.into();
|
||||
let log_max_size = self.log_max_size.load(Ordering::SeqCst);
|
||||
let log_max_count = self.log_max_count.load(Ordering::SeqCst);
|
||||
let writer_config = WriterConfig {
|
||||
directory: service_log_dir,
|
||||
max_log_size: log_max_size * 1024,
|
||||
max_log_files: log_max_count,
|
||||
};
|
||||
|
||||
Ok(writer_config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@ use super::{CoreManager, RunningMode};
|
||||
use crate::{
|
||||
AsyncHandler,
|
||||
config::{Config, IClashTemp},
|
||||
core::{handle, manager::CLASH_LOGGER, service},
|
||||
core::{handle, logger::Logger, manager::CLASH_LOGGER, service},
|
||||
logging,
|
||||
utils::{dirs, init::sidecar_writer},
|
||||
utils::dirs,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use clash_verge_logging::{SharedWriter, Type, write_sidecar_log};
|
||||
use clash_verge_logging::Type;
|
||||
use compact_str::CompactString;
|
||||
use flexi_logger::DeferredNow;
|
||||
use log::Level;
|
||||
use scopeguard::defer;
|
||||
use tauri_plugin_shell::ShellExt as _;
|
||||
@@ -60,20 +59,16 @@ impl CoreManager {
|
||||
self.set_running_child_sidecar(child);
|
||||
self.set_running_mode(RunningMode::Sidecar);
|
||||
|
||||
let shared_writer: SharedWriter = std::sync::Arc::new(tokio::sync::Mutex::new(sidecar_writer().await?));
|
||||
|
||||
AsyncHandler::spawn(|| async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
match event {
|
||||
tauri_plugin_shell::process::CommandEvent::Stdout(line)
|
||||
| tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
|
||||
let mut now = DeferredNow::default();
|
||||
let message = CompactString::from(String::from_utf8_lossy(&line).as_ref());
|
||||
write_sidecar_log(shared_writer.lock().await, &mut now, Level::Error, &message);
|
||||
Logger::global().writer_sidecar_log(Level::Error, &message);
|
||||
CLASH_LOGGER.append_log(message).await;
|
||||
}
|
||||
tauri_plugin_shell::process::CommandEvent::Terminated(term) => {
|
||||
let mut now = DeferredNow::default();
|
||||
let message = if let Some(code) = term.code {
|
||||
CompactString::from(format!("Process terminated with code: {}", code))
|
||||
} else if let Some(signal) = term.signal {
|
||||
@@ -81,7 +76,7 @@ impl CoreManager {
|
||||
} else {
|
||||
CompactString::from("Process terminated")
|
||||
};
|
||||
write_sidecar_log(shared_writer.lock().await, &mut now, Level::Info, &message);
|
||||
Logger::global().writer_sidecar_log(Level::Info, &message);
|
||||
CLASH_LOGGER.clear_logs().await;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
config::{Config, IClashTemp},
|
||||
core::tray::Tray,
|
||||
utils::{dirs, init::service_writer_config},
|
||||
core::{logger::Logger, tray::Tray},
|
||||
utils::dirs,
|
||||
};
|
||||
use anyhow::{Context as _, Result, bail};
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
@@ -313,7 +313,7 @@ pub(super) async fn start_with_existing_service(config_file: &PathBuf) -> Result
|
||||
core_ipc_path: IClashTemp::guard_external_controller_ipc(),
|
||||
config_dir: dirs::path_to_str(&dirs::app_home_dir()?)?.into(),
|
||||
},
|
||||
log_config: service_writer_config().await?,
|
||||
log_config: Logger::global().service_writer_config()?,
|
||||
};
|
||||
|
||||
let response = clash_verge_service_ipc::start_clash(&payload)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
config::{Config, IVerge},
|
||||
core::{CoreManager, handle, hotkey, sysopt, tray},
|
||||
core::{CoreManager, handle, hotkey, logger::Logger, sysopt, tray},
|
||||
module::{auto_backup::AutoBackupManager, lightweight},
|
||||
};
|
||||
use anyhow::Result;
|
||||
@@ -65,6 +65,8 @@ bitflags! {
|
||||
const SYSTRAY_CLICK_BEHAVIOR = 1 << 9;
|
||||
const LIGHT_WEIGHT = 1 << 10;
|
||||
const LANGUAGE = 1 << 11;
|
||||
const LOG_LEVEL = 1 << 12;
|
||||
const LOG_FILE = 1 << 13;
|
||||
|
||||
const GROUP_SYS_TRAY = Self::SYSTRAY_MENU.bits()
|
||||
| Self::SYSTRAY_TOOLTIP.bits()
|
||||
@@ -111,6 +113,9 @@ fn determine_update_flags(patch: &IVerge) -> UpdateFlags {
|
||||
let tray_inline_outbound_modes = patch.tray_inline_outbound_modes;
|
||||
let enable_proxy_guard = patch.enable_proxy_guard;
|
||||
let proxy_guard_duration = patch.proxy_guard_duration;
|
||||
let log_level = &patch.app_log_level;
|
||||
let log_max_size = patch.app_log_max_size;
|
||||
let log_max_count = patch.app_log_max_count;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let restart_core_needed = socks_enabled.is_some()
|
||||
@@ -182,6 +187,12 @@ fn determine_update_flags(patch: &IVerge) -> UpdateFlags {
|
||||
if tray_proxy_groups_display_mode.is_some() {
|
||||
update_flags.insert(UpdateFlags::SYSTRAY_MENU);
|
||||
}
|
||||
if log_level.is_some() {
|
||||
update_flags.insert(UpdateFlags::LOG_LEVEL);
|
||||
}
|
||||
if log_max_size.is_some() || log_max_count.is_some() {
|
||||
update_flags.insert(UpdateFlags::LOG_FILE);
|
||||
}
|
||||
if tray_inline_outbound_modes.is_some() {
|
||||
update_flags.insert(UpdateFlags::SYSTRAY_MENU);
|
||||
}
|
||||
@@ -244,6 +255,14 @@ async fn process_terminated_flags(update_flags: UpdateFlags, patch: &IVerge) ->
|
||||
lightweight::disable_auto_light_weight_mode();
|
||||
}
|
||||
}
|
||||
if update_flags.contains(UpdateFlags::LOG_LEVEL) {
|
||||
Logger::global().update_log_level(patch.get_log_level())?;
|
||||
}
|
||||
if update_flags.contains(UpdateFlags::LOG_FILE) {
|
||||
let log_max_size = patch.app_log_max_size.unwrap_or(128);
|
||||
let log_max_count = patch.app_log_max_count.unwrap_or(8);
|
||||
Logger::global().update_log_config(log_max_size, log_max_count).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ pub fn run() {
|
||||
.set(app.app_handle().clone())
|
||||
.expect("failed to set global app handle");
|
||||
|
||||
let _handle = resolve::init_work_dir_and_logger();
|
||||
resolve::init_work_dir_and_logger()?;
|
||||
|
||||
logging!(info, Type::Setup, "开始应用初始化...");
|
||||
if let Err(e) = app_init::setup_autostart(app) {
|
||||
|
||||
@@ -6,137 +6,18 @@ use crate::{
|
||||
logging,
|
||||
process::AsyncHandler,
|
||||
utils::{
|
||||
dirs::{self, PathBufExec as _, service_log_dir, sidecar_log_dir},
|
||||
dirs::{self, PathBufExec as _},
|
||||
help,
|
||||
},
|
||||
};
|
||||
use anyhow::Result;
|
||||
use chrono::{Local, TimeZone as _};
|
||||
#[cfg(all(not(feature = "tauri-dev"), not(feature = "tracing-full")))]
|
||||
use clash_verge_logging::NoModuleFilter;
|
||||
use clash_verge_logging::Type;
|
||||
use clash_verge_service_ipc::WriterConfig;
|
||||
use flexi_logger::writers::FileLogWriter;
|
||||
use flexi_logger::{Cleanup, Criterion, FileSpec};
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
use flexi_logger::{Duplicate, LogSpecBuilder, Logger, LoggerHandle};
|
||||
use std::{path::PathBuf, str::FromStr as _};
|
||||
use tauri_plugin_shell::ShellExt as _;
|
||||
use tokio::fs;
|
||||
use tokio::fs::DirEntry;
|
||||
|
||||
/// initialize this instance's log file
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
pub async fn init_logger() -> Result<LoggerHandle> {
|
||||
// TODO 提供 runtime 级别实时修改
|
||||
let (log_level, log_max_size, log_max_count) = {
|
||||
let verge_guard = Config::verge().await;
|
||||
let verge = verge_guard.data_arc();
|
||||
(
|
||||
verge.get_log_level(),
|
||||
verge.app_log_max_size.unwrap_or(128),
|
||||
verge.app_log_max_count.unwrap_or(8),
|
||||
)
|
||||
};
|
||||
|
||||
let log_dir = dirs::app_logs_dir()?;
|
||||
let mut spec = LogSpecBuilder::new();
|
||||
let level = std::env::var("RUST_LOG")
|
||||
.ok()
|
||||
.and_then(|v| log::LevelFilter::from_str(&v).ok())
|
||||
.unwrap_or(log_level);
|
||||
spec.default(level);
|
||||
#[cfg(feature = "tracing")]
|
||||
spec.module("tauri", log::LevelFilter::Debug)
|
||||
.module("wry", log::LevelFilter::Off)
|
||||
.module("tauri_plugin_mihomo", log::LevelFilter::Off);
|
||||
let spec = spec.build();
|
||||
|
||||
let logger = Logger::with(spec)
|
||||
.log_to_file(FileSpec::default().directory(log_dir).basename(""))
|
||||
.duplicate_to_stdout(Duplicate::Debug)
|
||||
.format(clash_verge_logger::console_format)
|
||||
.format_for_files(clash_verge_logger::file_format_with_level)
|
||||
.rotate(
|
||||
Criterion::Size(log_max_size * 1024),
|
||||
flexi_logger::Naming::TimestampsCustomFormat {
|
||||
current_infix: Some("latest"),
|
||||
format: "%Y-%m-%d_%H-%M-%S",
|
||||
},
|
||||
Cleanup::KeepLogFiles(log_max_count),
|
||||
);
|
||||
#[cfg(all(not(feature = "tracing"), not(feature = "tracing-full")))]
|
||||
let logger = logger.filter(Box::new(NoModuleFilter(&[
|
||||
"wry",
|
||||
"tauri",
|
||||
"tokio_tungstenite",
|
||||
"tungstenite",
|
||||
])));
|
||||
#[cfg(feature = "tracing")]
|
||||
let logger = logger.filter(Box::new(NoModuleFilter(&[
|
||||
"wry",
|
||||
"tauri_plugin_mihomo",
|
||||
"tokio_tungstenite",
|
||||
"tungstenite",
|
||||
"kode_bridge",
|
||||
])));
|
||||
|
||||
let handle = logger.start()?;
|
||||
|
||||
// TODO 全局 logger handle 控制
|
||||
// GlobalLoggerProxy::global().set_inner(handle);
|
||||
// TODO 提供前端设置等级,热更新等级
|
||||
// logger.parse_new_spec(spec)
|
||||
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
pub async fn sidecar_writer() -> Result<FileLogWriter> {
|
||||
let (log_max_size, log_max_count) = {
|
||||
let verge_guard = Config::verge().await;
|
||||
let verge = verge_guard.data_arc();
|
||||
(
|
||||
verge.app_log_max_size.unwrap_or(128),
|
||||
verge.app_log_max_count.unwrap_or(8),
|
||||
)
|
||||
};
|
||||
let sidecar_log_dir = sidecar_log_dir()?;
|
||||
Ok(FileLogWriter::builder(
|
||||
FileSpec::default()
|
||||
.directory(sidecar_log_dir)
|
||||
.basename("sidecar")
|
||||
.suppress_timestamp(),
|
||||
)
|
||||
.format(clash_verge_logger::file_format_without_level)
|
||||
.rotate(
|
||||
Criterion::Size(log_max_size * 1024),
|
||||
flexi_logger::Naming::TimestampsCustomFormat {
|
||||
current_infix: Some("latest"),
|
||||
format: "%Y-%m-%d_%H-%M-%S",
|
||||
},
|
||||
Cleanup::KeepLogFiles(log_max_count),
|
||||
)
|
||||
.try_build()?)
|
||||
}
|
||||
|
||||
pub async fn service_writer_config() -> Result<WriterConfig> {
|
||||
let (log_max_size, log_max_count) = {
|
||||
let verge_guard = Config::verge().await;
|
||||
let verge = verge_guard.data_arc();
|
||||
(
|
||||
verge.app_log_max_size.unwrap_or(128),
|
||||
verge.app_log_max_count.unwrap_or(8),
|
||||
)
|
||||
};
|
||||
let service_log_dir = dirs::path_to_str(&service_log_dir()?)?.into();
|
||||
|
||||
Ok(WriterConfig {
|
||||
directory: service_log_dir,
|
||||
max_log_size: log_max_size * 1024,
|
||||
max_log_files: log_max_count,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO flexi_logger 提供了最大保留天数,或许我们应该用内置删除log文件
|
||||
/// 删除log文件
|
||||
pub async fn delete_log() -> Result<()> {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use anyhow::Result;
|
||||
use flexi_logger::LoggerHandle;
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
core::{
|
||||
CoreManager, Timer, handle,
|
||||
hotkey::Hotkey,
|
||||
logger::Logger,
|
||||
service::{SERVICE_MANAGER, ServiceManager, is_service_ipc_path_exists},
|
||||
sysopt,
|
||||
tray::Tray,
|
||||
@@ -28,20 +28,13 @@ pub mod window_script;
|
||||
|
||||
static RESOLVE_DONE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub fn init_work_dir_and_logger() -> Option<LoggerHandle> {
|
||||
pub fn init_work_dir_and_logger() -> anyhow::Result<()> {
|
||||
AsyncHandler::block_on(async {
|
||||
init_work_config().await;
|
||||
init_resources().await;
|
||||
|
||||
#[cfg(not(feature = "tauri-dev"))]
|
||||
{
|
||||
logging!(info, Type::Setup, "Initializing logger");
|
||||
init::init_logger().await.ok()
|
||||
}
|
||||
#[cfg(feature = "tauri-dev")]
|
||||
{
|
||||
None
|
||||
}
|
||||
logging!(info, Type::Setup, "Initializing logger");
|
||||
Logger::global().init().await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user