From 221b732472859803b8d0de79793193411fb63e21 Mon Sep 17 00:00:00 2001 From: huzibaca Date: Mon, 18 Nov 2024 05:58:06 +0800 Subject: [PATCH] refactor: logger fetch logic --- src-tauri/src/cmds.rs | 7 +--- src-tauri/src/core/clash_api.rs | 3 +- src-tauri/src/core/core.rs | 18 ++-------- src-tauri/src/core/logger.rs | 36 ------------------- src-tauri/src/core/mod.rs | 1 - src-tauri/src/lib.rs | 1 - src/hooks/use-log-data.ts | 61 ++++++++++++++++++--------------- src/pages/logs.tsx | 26 +++++++------- src/services/cmds.ts | 23 ------------- 9 files changed, 50 insertions(+), 126 deletions(-) delete mode 100644 src-tauri/src/core/logger.rs diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index 5a71440f..348f19d4 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -8,7 +8,7 @@ use crate::{ret_err, wrap_err}; use anyhow::{Context, Result}; use network_interface::NetworkInterface; use serde_yaml::Mapping; -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; use sysproxy::{Autoproxy, Sysproxy}; type CmdResult = Result; use reqwest_dav::list_cmd::ListFile; @@ -216,11 +216,6 @@ pub fn get_auto_proxy() -> CmdResult { Ok(map) } -#[tauri::command] -pub fn get_clash_logs() -> CmdResult> { - Ok(logger::Logger::global().get_log()) -} - #[tauri::command] pub fn open_app_dir() -> CmdResult<()> { let app_dir = wrap_err!(dirs::app_home_dir())?; diff --git a/src-tauri/src/core/clash_api.rs b/src-tauri/src/core/clash_api.rs index 97e98e8d..3dd3b572 100644 --- a/src-tauri/src/core/clash_api.rs +++ b/src-tauri/src/core/clash_api.rs @@ -96,8 +96,7 @@ pub fn parse_log(log: String) -> String { log } -/// 缩短clash -t的错误输出 -/// 仅适配 clash p核 8-26、clash meta 1.13.1 +#[allow(dead_code)] pub fn parse_check_output(log: String) -> String { let t = log.find("time="); let m = log.find("msg="); diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 947fa56f..ae3d71d3 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -1,5 +1,5 @@ use crate::config::*; -use crate::core::{clash_api, handle, logger::Logger, service}; +use crate::core::{clash_api, handle, service}; use crate::log_err; use crate::utils::dirs; use anyhow::{bail, Result}; @@ -43,24 +43,13 @@ impl CoreManager { let test_dir = dirs::path_to_str(&test_dir)?; let app_handle = handle::Handle::global().app_handle().unwrap(); - let output = app_handle + let _ = app_handle .shell() .sidecar(clash_core)? .args(["-t", "-d", test_dir, "-f", config_path]) .output() .await?; - if !output.status.success() { - let stdout = String::from_utf8(output.stdout).unwrap_or_default(); - let error = clash_api::parse_check_output(stdout.clone()); - let error = match !error.is_empty() { - true => error, - false => stdout.clone(), - }; - Logger::global().set_log(stdout.clone()); - bail!("{error}"); - } - Ok(()) } @@ -136,9 +125,6 @@ impl CoreManager { self.check_config().await?; - // 清掉旧日志 - Logger::global().clear_log(); - match self.restart_core().await { Ok(_) => { Config::verge().apply(); diff --git a/src-tauri/src/core/logger.rs b/src-tauri/src/core/logger.rs deleted file mode 100644 index b4264153..00000000 --- a/src-tauri/src/core/logger.rs +++ /dev/null @@ -1,36 +0,0 @@ -use once_cell::sync::OnceCell; -use parking_lot::Mutex; -use std::{collections::VecDeque, sync::Arc}; - -const LOGS_QUEUE_LEN: usize = 100; - -pub struct Logger { - log_data: Arc>>, -} - -impl Logger { - pub fn global() -> &'static Logger { - static LOGGER: OnceCell = OnceCell::new(); - - LOGGER.get_or_init(|| Logger { - log_data: Arc::new(Mutex::new(VecDeque::with_capacity(LOGS_QUEUE_LEN + 10))), - }) - } - - pub fn get_log(&self) -> VecDeque { - self.log_data.lock().clone() - } - - pub fn set_log(&self, text: String) { - let mut logs = self.log_data.lock(); - if logs.len() > LOGS_QUEUE_LEN { - logs.pop_front(); - } - logs.push_back(text); - } - - pub fn clear_log(&self) { - let mut logs = self.log_data.lock(); - logs.clear(); - } -} diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index 32bb267c..098052b9 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -4,7 +4,6 @@ pub mod clash_api; mod core; pub mod handle; pub mod hotkey; -pub mod logger; pub mod service; pub mod sysopt; pub mod timer; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 59b2ea80..f6af33fd 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -88,7 +88,6 @@ pub fn run() { cmds::restart_app, // clash cmds::get_clash_info, - cmds::get_clash_logs, cmds::patch_clash_config, cmds::change_clash_core, cmds::get_runtime_config, diff --git a/src/hooks/use-log-data.ts b/src/hooks/use-log-data.ts index 98cfb5b6..13339aa2 100644 --- a/src/hooks/use-log-data.ts +++ b/src/hooks/use-log-data.ts @@ -3,46 +3,51 @@ import { useEnableLog } from "../services/states"; import { createSockette } from "../utils/websocket"; import { useClashInfo } from "./use-clash"; import dayjs from "dayjs"; -import { getClashLogs } from "../services/cmds"; const MAX_LOG_NUM = 1000; -export const useLogData = () => { +// 添加 LogLevel 类型定义 +export type LogLevel = "warning" | "info" | "debug" | "error"; + +const buildWSUrl = (server: string, secret: string, logLevel: LogLevel) => { + const baseUrl = `ws://${server}/logs`; + const params = new URLSearchParams(); + + if (secret) { + params.append("token", encodeURIComponent(secret)); + } + params.append("level", logLevel); + const queryString = params.toString(); + return queryString ? `${baseUrl}?${queryString}` : baseUrl; +}; + +export const useLogData = (logLevel: LogLevel) => { const { clashInfo } = useClashInfo(); const [enableLog] = useEnableLog(); - return useSWRSubscription( - enableLog && clashInfo ? "getClashLog" : null, + return useSWRSubscription( + enableLog && clashInfo ? ["getClashLog", logLevel] : null, (_key, { next }) => { const { server = "", secret = "" } = clashInfo!; - // populate the initial logs - getClashLogs().then( - (logs) => next(null, logs), - (err) => next(err) - ); + const s = createSockette(buildWSUrl(server, secret, logLevel), { + onmessage(event) { + const data = JSON.parse(event.data) as ILogItem; - const s = createSockette( - `ws://${server}/logs?token=${encodeURIComponent(secret)}`, - { - onmessage(event) { - const data = JSON.parse(event.data) as ILogItem; + // append new log item on socket message + next(null, (l = []) => { + const time = dayjs().format("MM-DD HH:mm:ss"); - // append new log item on socket message - next(null, (l = []) => { - const time = dayjs().format("MM-DD HH:mm:ss"); - - if (l.length >= MAX_LOG_NUM) l.shift(); - return [...l, { ...data, time }]; - }); - }, - onerror(event) { - this.close(); - next(event); - }, - } - ); + if (l.length >= MAX_LOG_NUM) l.shift(); + return [...l, { ...data, time }]; + }); + }, + onerror(event) { + this.close(); + next(event); + }, + }); return () => { s.close(); diff --git a/src/pages/logs.tsx b/src/pages/logs.tsx index 71447cef..b6310a25 100644 --- a/src/pages/logs.tsx +++ b/src/pages/logs.tsx @@ -6,7 +6,7 @@ import { PlayCircleOutlineRounded, PauseCircleOutlineRounded, } from "@mui/icons-material"; -import { useLogData } from "@/hooks/use-log-data"; +import { useLogData, LogLevel } from "@/hooks/use-log-data"; import { useEnableLog } from "@/services/states"; import { BaseEmpty, BasePage } from "@/components/base"; import LogItem from "@/components/log/log-item"; @@ -17,19 +17,19 @@ import { mutate } from "swr"; const LogPage = () => { const { t } = useTranslation(); - const { data: logData = [] } = useLogData(); const [enableLog, setEnableLog] = useEnableLog(); const theme = useTheme(); const isDark = theme.palette.mode === "dark"; - const [logState, setLogState] = useState("all"); + const [logState, setLogState] = useState("info"); const [match, setMatch] = useState(() => (_: string) => true); + const { data: logData } = useLogData(logState); const filterLogs = useMemo(() => { - return logData.filter( - (data) => - (logState === "all" ? true : data.type.includes(logState)) && - match(data.payload) - ); + return logData + ? logData.filter( + (data) => data.type.includes(logState) && match(data.payload) + ) + : []; }, [logData, logState, match]); return ( @@ -80,12 +80,12 @@ const LogPage = () => { > setLogState(e.target.value)} + onChange={(e) => setLogState(e.target.value as LogLevel)} > - ALL - INFO - WARN - ERROR + INFO + WARN + ERROR + DEBUG setMatch(() => match)} /> diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 9a416c28..09e22d03 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -6,29 +6,6 @@ export async function copyClashEnv() { return invoke("copy_clash_env"); } -export async function getClashLogs() { - const regex = /time="(.+?)"\s+level=(.+?)\s+msg="(.+?)"/; - const newRegex = /(.+?)\s+(.+?)\s+(.+)/; - const logs = await invoke("get_clash_logs"); - - return logs.reduce((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 getProfiles() { return invoke("get_profiles"); }