feat!: deprecated recoding core logs from backend

This commit is contained in:
Tunglies
2026-01-06 09:09:13 +08:00
parent 60d3a1927b
commit 41fb6b640e
14 changed files with 94 additions and 240 deletions

133
Cargo.lock generated
View File

@@ -170,12 +170,6 @@ dependencies = [
"rustversion",
]
[[package]]
name = "arraydeque"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
[[package]]
name = "arrayvec"
version = "0.7.6"
@@ -1082,15 +1076,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[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.51"
@@ -1236,9 +1221,7 @@ dependencies = [
"clash-verge-logging",
"clash-verge-signal",
"clash-verge-types",
"clash_verge_logger",
"clash_verge_service_ipc",
"compact_str",
"console-subscriber",
"criterion",
"dark-light",
@@ -1315,9 +1298,9 @@ dependencies = [
name = "clash-verge-logging"
version = "0.1.0"
dependencies = [
"compact_str",
"flexi_logger",
"log",
"nu-ansi-term",
"tokio",
]
@@ -1339,26 +1322,12 @@ dependencies = [
"smartstring",
]
[[package]]
name = "clash_verge_logger"
version = "0.2.2"
source = "git+https://github.com/clash-verge-rev/clash-verge-logger#e4768e3852c4868ed86e7210df82c1178467820d"
dependencies = [
"arraydeque",
"compact_str",
"flexi_logger",
"log",
"nu-ansi-term",
"tokio",
]
[[package]]
name = "clash_verge_service_ipc"
version = "2.0.28"
source = "git+https://github.com/clash-verge-rev/clash-verge-service-ipc#384169c7371f78cd213713f0b0a115d48a1f28c3"
version = "2.0.29"
source = "git+https://github.com/clash-verge-rev/clash-verge-service-ipc?branch=refactor%2Fremove-logs-record#79245a11c90e372399e911533388e8af400a6ede"
dependencies = [
"anyhow",
"compact_str",
"kode-bridge",
"log",
"once_cell",
@@ -1436,23 +1405,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "compact_str"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rkyv",
"rustversion",
"ryu",
"serde",
"smallvec",
"static_assertions",
]
[[package]]
name = "concat-idents"
version = "1.1.5"
@@ -4568,26 +4520,6 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "munge"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c"
dependencies = [
"munge_macro",
]
[[package]]
name = "munge_macro"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.113",
]
[[package]]
name = "nanoid"
version = "0.4.0"
@@ -5987,26 +5919,6 @@ version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
[[package]]
name = "ptr_meta"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.113",
]
[[package]]
name = "publicsuffix"
version = "2.3.0"
@@ -6136,15 +6048,6 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rancor"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee"
dependencies = [
"ptr_meta",
]
[[package]]
name = "rand"
version = "0.7.3"
@@ -6395,12 +6298,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "rend"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6"
[[package]]
name = "reqwest"
version = "0.12.28"
@@ -6563,30 +6460,6 @@ dependencies = [
"portable-atomic-util",
]
[[package]]
name = "rkyv"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b2e88acca7157d83d789836a3987dafc12bc3d88a050e54b8fe9ea4aaa29d20"
dependencies = [
"munge",
"ptr_meta",
"rancor",
"rend",
"rkyv_derive",
]
[[package]]
name = "rkyv_derive"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6dffea3c91fa91a3c0fc8a061b0e27fef25c6304728038a6d6bcb1c58ba9bd"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.113",
]
[[package]]
name = "rs-snowflake"
version = "0.6.0"

View File

@@ -63,7 +63,6 @@ flexi_logger = "0.31.7"
log = "0.4.29"
smartstring = { version = "1.0.1" }
compact_str = { version = "0.9.0", features = ["serde"] }
serde = { version = "1.0.228" }
serde_json = { version = "1.0.148" }

View File

@@ -6,8 +6,9 @@ edition = "2024"
[dependencies]
log = { workspace = true }
tokio = { workspace = true }
compact_str = { workspace = true }
flexi_logger = { workspace = true }
nu-ansi-term = { version = "0.50", optional = true }
[features]
default = []
color = ["nu-ansi-term"]

View File

@@ -1,14 +1,18 @@
use compact_str::CompactString;
use std::borrow::Cow;
use std::{fmt, sync::Arc};
use std::{io::Write, thread};
use flexi_logger::DeferredNow;
use flexi_logger::filter::LogLineFilter;
use flexi_logger::writers::FileLogWriter;
use flexi_logger::writers::LogWriter as _;
use log::Level;
use log::Record;
use std::{fmt, sync::Arc};
use tokio::sync::{Mutex, MutexGuard};
use log::{LevelFilter, Record};
#[cfg(feature = "color")]
use nu_ansi_term::Color;
use tokio::sync::{RwLock, RwLockReadGuard};
pub type SharedWriter = Arc<Mutex<FileLogWriter>>;
pub type SharedWriter = Arc<RwLock<FileLogWriter>>;
#[derive(Debug, PartialEq, Eq)]
pub enum Type {
@@ -85,10 +89,10 @@ macro_rules! logging_error {
#[inline]
pub fn write_sidecar_log(
writer: MutexGuard<'_, FileLogWriter>,
writer: RwLockReadGuard<'_, FileLogWriter>,
now: &mut DeferredNow,
level: Level,
message: &CompactString,
message: &str,
) {
let args = format_args!("{}", message);
@@ -127,3 +131,66 @@ impl<'a> LogLineFilter for NoModuleFilter<'a> {
writer.write(now, record)
}
}
pub fn level_filter_to_string(log_level: &LevelFilter) -> Cow<'static, str> {
#[cfg(feature = "color")]
{
match log_level {
LevelFilter::Off => Cow::Owned(Color::Fixed(8).paint("OFF").to_string()),
LevelFilter::Error => Cow::Owned(Color::Red.paint("ERROR").to_string()),
LevelFilter::Warn => Cow::Owned(Color::Yellow.paint("WARN ").to_string()),
LevelFilter::Info => Cow::Owned(Color::Green.paint("INFO ").to_string()),
LevelFilter::Debug => Cow::Owned(Color::Blue.paint("DEBUG").to_string()),
LevelFilter::Trace => Cow::Owned(Color::Purple.paint("TRACE").to_string()),
}
}
#[cfg(not(feature = "color"))]
{
match log_level {
LevelFilter::Off => Cow::Borrowed("OFF"),
LevelFilter::Error => Cow::Borrowed("ERROR"),
LevelFilter::Warn => Cow::Borrowed("WARN "),
LevelFilter::Info => Cow::Borrowed("INFO "),
LevelFilter::Debug => Cow::Borrowed("DEBUG"),
LevelFilter::Trace => Cow::Borrowed("TRACE"),
}
}
}
pub fn console_format(w: &mut dyn Write, now: &mut DeferredNow, record: &Record) -> std::io::Result<()> {
let current_thread = thread::current();
let thread_name = current_thread.name().unwrap_or("unnamed");
let level = level_filter_to_string(&record.level().to_level_filter());
let now = now.format("%H:%M:%S%.3f");
#[cfg(feature = "color")]
let now = Color::DarkGray.paint(Cow::from(now.to_string()));
let line = record.line().map_or(0, |l| l);
let module = record.module_path().unwrap_or("<unnamed>");
let module_line = Cow::from(format!("{}:{}", module, line));
#[cfg(feature = "color")]
let module_line = Color::Purple.paint(module_line);
let thread_name = Cow::from(format!("T{{{}}}", thread_name));
#[cfg(feature = "color")]
let thread_name = Color::Cyan.paint(thread_name);
write!(w, "{} {} {} {} {}", now, level, module_line, thread_name, record.args(),)
}
pub fn file_format_with_level(w: &mut dyn Write, now: &mut DeferredNow, record: &Record) -> std::io::Result<()> {
write!(
w,
"[{}] {} {}",
now.format("%Y-%m-%d %H:%M:%S%.3f"),
record.level(),
record.args(),
)
}
pub fn file_format_without_level(w: &mut dyn Write, now: &mut DeferredNow, record: &Record) -> std::io::Result<()> {
write!(w, "[{}] {}", now.format("%Y-%m-%d %H:%M:%S%.3f"), record.args(),)
}

View File

@@ -17,7 +17,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
[features]
default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]
verge-dev = ["clash_verge_logger/color"]
verge-dev = ["clash-verge-logging/color"]
tauri-dev = []
tokio-trace = ["console-subscriber"]
clippy = ["tauri/test"]
@@ -48,7 +48,6 @@ tauri = { workspace = true, features = [
parking_lot = { workspace = true }
anyhow = { workspace = true }
tokio = { workspace = true }
compact_str = { workspace = true }
flexi_logger = { workspace = true }
log = { workspace = true }
serde = { workspace = true, features = ["derive"] }
@@ -97,11 +96,10 @@ tauri-plugin-http = "2.5.4"
console-subscriber = { version = "0.5.0", optional = true }
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.28", features = [
clash_verge_service_ipc = { version = "2.0.29", features = [
"client",
], git = "https://github.com/clash-verge-rev/clash-verge-service-ipc" }
], git = "https://github.com/clash-verge-rev/clash-verge-service-ipc", branch = "refactor/remove-logs-record" }
arc-swap = "1.8.0"
rust_iso3166 = "0.1.14"
dark-light = "2.0.0"

View File

@@ -8,7 +8,6 @@ use crate::{
core::{CoreManager, handle, validate::CoreConfigValidator},
};
use clash_verge_logging::{Type, logging, logging_error};
use compact_str::CompactString;
use serde_yaml_ng::Mapping;
use smartstring::alias::String;
use tokio::fs;
@@ -243,9 +242,3 @@ pub async fn validate_dns_config() -> CmdResult<(bool, String)> {
.await
.stringify_err()
}
#[tauri::command]
pub async fn get_clash_logs() -> CmdResult<Vec<CompactString>> {
let logs = CoreManager::global().get_clash_logs().await.unwrap_or_default();
Ok(logs)
}

View File

@@ -9,7 +9,6 @@ use std::{
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 _},
@@ -75,8 +74,8 @@ impl Logger {
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)
.format(clash_verge_logging::console_format)
.format_for_files(clash_verge_logging::file_format_with_level)
.rotate(
Criterion::Size(log_max_size * 1024),
flexi_logger::Naming::TimestampsCustomFormat {
@@ -183,7 +182,7 @@ impl Logger {
.basename("sidecar")
.suppress_timestamp(),
)
.format(clash_verge_logger::file_format_without_level)
.format(clash_verge_logging::file_format_without_level)
.rotate(
Criterion::Size(log_max_size * 1024),
flexi_logger::Naming::TimestampsCustomFormat {
@@ -195,7 +194,7 @@ impl Logger {
.try_build()?)
}
pub fn writer_sidecar_log(&self, level: Level, message: &CompactString) {
pub fn writer_sidecar_log(&self, level: Level, message: &str) {
if let Some(writer) = self.sidecar_file_writer.read().as_ref() {
let mut now = DeferredNow::default();
let args = format_args!("{}", message);

View File

@@ -2,7 +2,6 @@ use super::{CoreManager, RunningMode};
use crate::cmd::StringifyErr as _;
use crate::config::{Config, IVerge};
use crate::core::handle::Handle;
use crate::core::manager::CLASH_LOGGER;
use crate::core::service::{SERVICE_MANAGER, ServiceStatus};
use anyhow::Result;
use clash_verge_logging::{Type, logging};
@@ -24,7 +23,6 @@ impl CoreManager {
}
pub async fn stop_core(&self) -> Result<()> {
CLASH_LOGGER.clear_logs().await;
defer! {
self.after_core_process();
}

View File

@@ -4,15 +4,11 @@ mod state;
use anyhow::Result;
use arc_swap::{ArcSwap, ArcSwapOption};
use clash_verge_logger::AsyncLogger;
use once_cell::sync::Lazy;
use std::{fmt, sync::Arc, time::Instant};
use tauri_plugin_shell::process::CommandChild;
use crate::singleton;
pub(crate) static CLASH_LOGGER: Lazy<Arc<AsyncLogger>> = Lazy::new(|| Arc::new(AsyncLogger::new()));
#[derive(Debug, serde::Serialize, PartialEq, Eq)]
pub enum RunningMode {
Service,

View File

@@ -1,27 +1,20 @@
use std::borrow::Cow;
use super::{CoreManager, RunningMode};
use crate::{
AsyncHandler,
config::{Config, IClashTemp},
core::{handle, logger::Logger, manager::CLASH_LOGGER, service},
core::{handle, logger::Logger, service},
logging,
utils::dirs,
};
use anyhow::Result;
use clash_verge_logging::Type;
use compact_str::CompactString;
use log::Level;
use scopeguard::defer;
use tauri_plugin_shell::ShellExt as _;
impl CoreManager {
pub async fn get_clash_logs(&self) -> Result<Vec<CompactString>> {
match *self.get_running_mode() {
RunningMode::Service => service::get_clash_logs_by_service().await,
RunningMode::Sidecar => Ok(CLASH_LOGGER.get_logs().await),
RunningMode::NotRunning => Ok(Vec::new()),
}
}
pub(super) async fn start_core_by_sidecar(&self) -> Result<()> {
logging!(info, Type::Core, "Starting core in sidecar mode");
@@ -64,20 +57,18 @@ impl CoreManager {
match event {
tauri_plugin_shell::process::CommandEvent::Stdout(line)
| tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
let message = CompactString::from(String::from_utf8_lossy(&line).as_ref());
let message = String::from_utf8_lossy(&line);
Logger::global().writer_sidecar_log(Level::Error, &message);
CLASH_LOGGER.append_log(message).await;
}
tauri_plugin_shell::process::CommandEvent::Terminated(term) => {
let message = if let Some(code) = term.code {
CompactString::from(format!("Process terminated with code: {}", code))
Cow::Owned(format!("Process terminated with code: {}", code))
} else if let Some(signal) = term.signal {
CompactString::from(format!("Process terminated by signal: {}", signal))
Cow::Owned(format!("Process terminated by signal: {}", signal))
} else {
CompactString::from("Process terminated")
Cow::Borrowed("Process terminated")
};
Logger::global().writer_sidecar_log(Level::Info, &message);
CLASH_LOGGER.clear_logs().await;
break;
}
_ => {}

View File

@@ -6,7 +6,6 @@ use crate::{
use anyhow::{Context as _, Result, bail};
use clash_verge_logging::{Type, logging, logging_error};
use clash_verge_service_ipc::CoreConfig;
use compact_str::CompactString;
use once_cell::sync::Lazy;
use std::{
env::current_exe,
@@ -343,23 +342,6 @@ pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> {
start_with_existing_service(config_file).await
}
pub(super) async fn get_clash_logs_by_service() -> Result<Vec<CompactString>> {
logging!(info, Type::Service, "正在获取服务模式下的 Clash 日志");
let response = clash_verge_service_ipc::get_clash_logs()
.await
.context("无法连接到Clash Verge Service")?;
if response.code > 0 {
let err_msg = response.message;
logging!(error, Type::Service, "获取服务模式下的 Clash 日志失败: {}", err_msg);
bail!(err_msg);
}
logging!(info, Type::Service, "成功获取服务模式下的 Clash 日志");
Ok(response.data.unwrap_or_default())
}
/// 通过服务停止core
pub(super) async fn stop_core_by_service() -> Result<()> {
logging!(info, Type::Service, "通过服务停止核心 (IPC)");

View File

@@ -179,7 +179,6 @@ mod app_init {
cmd::check_dns_config_exists,
cmd::get_dns_config_content,
cmd::validate_dns_config,
cmd::get_clash_logs,
cmd::get_verge_config,
cmd::patch_verge_config,
cmd::test_delay,

View File

@@ -3,8 +3,6 @@ import { useEffect, useRef } from "react";
import { mutate } from "swr";
import { MihomoWebSocket, type LogLevel } from "tauri-plugin-mihomo-api";
import { getClashLogs } from "@/services/cmds";
import { useClashLog } from "./use-clash-log";
import { useMihomoWsSubscription } from "./use-mihomo-ws-subscription";
@@ -24,15 +22,6 @@ const LOG_LEVEL_FILTERS: Record<LogLevel, LogType[]> = {
const clampLogs = (logs: ILogItem[]): ILogItem[] =>
logs.length > MAX_LOG_NUM ? logs.slice(-MAX_LOG_NUM) : logs;
const filterLogsByLevel = (
logs: ILogItem[],
allowedTypes: LogType[],
): ILogItem[] => {
if (allowedTypes.length === 0) return [];
if (allowedTypes.length === DEFAULT_LOG_TYPES.length) return logs;
return logs.filter((log) => allowedTypes.includes(log.type));
};
const appendLogs = (
current: ILogItem[] | undefined,
incoming: ILogItem[],
@@ -99,10 +88,7 @@ export const useLogData = () => {
}
},
async onConnected() {
const logs = await getClashLogs();
if (isMounted()) {
next(null, clampLogs(filterLogsByLevel(logs, allowedTypes)));
}
console.debug("[use-log-data] Log WebSocket connected");
},
cleanup: clearFlushTimer,
};

View File

@@ -1,5 +1,4 @@
import { invoke } from "@tauri-apps/api/core";
import dayjs from "dayjs";
import { getProxies, getProxyProviders } from "tauri-plugin-mihomo-api";
import { showNotice } from "@/services/notice-service";
@@ -220,33 +219,6 @@ export async function calcuProxyProviders() {
);
}
export async function getClashLogs() {
const regex = /time="(.+?)"\s+level=(.+?)\s+msg="(.+?)"/;
const newRegex = /(.+?)\s+(.+?)\s+(.+)/;
const logs = await invoke<string[]>("get_clash_logs");
return logs.reduce<ILogItem[]>((acc, log) => {
const result = log.match(regex);
if (result) {
const [_, _time, type, payload] = result;
const time = dayjs(_time).format("MM-DD HH:mm:ss");
acc.push({ time, type, payload });
return acc;
}
const result2 = log.match(newRegex);
if (result2) {
const [_, time, type, payload] = result2;
acc.push({ time, type, payload });
}
return acc;
}, []);
}
export async function clearLogs() {
return invoke<void>("clear_logs");
}
export async function getVergeConfig() {
return invoke<IVergeConfig>("get_verge_config");
}