Skip to content

Commit ac336ff

Browse files
committed
feat: add GetClashLogs method
1 parent 0b78603 commit ac336ff

File tree

4 files changed

+67
-3
lines changed

4 files changed

+67
-3
lines changed

src/client/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{sync::Arc, time::Duration};
1+
use std::{collections::VecDeque, sync::Arc, time::Duration};
22

33
use anyhow::Result;
44
use kode_bridge::{ClientConfig, IpcHttpClient, pool::PoolConfig};
@@ -82,6 +82,16 @@ pub async fn start_clash(body: &ClashConfig) -> Result<Response<()>> {
8282
Ok(response)
8383
}
8484

85+
pub async fn get_clash_logs() -> Result<Response<VecDeque<String>>> {
86+
let client = connect().await?;
87+
let response = client
88+
.get(IpcCommand::GetClashLogs.as_ref())
89+
.send()
90+
.await?
91+
.json::<Response<VecDeque<String>>>()?;
92+
Ok(response)
93+
}
94+
8595
pub async fn stop_clash() -> Result<Response<()>> {
8696
let client = connect().await?;
8797
let response = client

src/core/command.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ pub enum IpcCommand {
77
GetVersion,
88
// #[strum(serialize = "/clash")]
99
// GetClash,
10+
11+
// 用于日志界面加载上一次日志内容
12+
#[strum(serialize = "/clash/logs")]
13+
GetClashLogs,
14+
1015
#[strum(serialize = "/clash/start")]
1116
StartClash,
1217
#[strum(serialize = "/clash/stop")]

src/core/manager.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ use anyhow::Result;
55
use flexi_logger::writers::LogWriter;
66
use flexi_logger::{DeferredNow, Record};
77
use once_cell::sync::Lazy;
8+
use std::collections::VecDeque;
89
use std::process::Stdio;
9-
use std::sync::Arc;
10+
use std::sync::{Arc, OnceLock};
1011
use tokio::io::AsyncBufReadExt;
12+
use tokio::sync::{RwLock, RwLockReadGuard};
1113
use tokio::{io::BufReader, process::Command};
1214
use tokio::{process::Child, sync::Mutex};
1315
use tracing::{info, warn};
@@ -36,6 +38,39 @@ impl ChildGuard {
3638
}
3739
}
3840

41+
const LOGS_QUEUE_LEN: usize = 100;
42+
43+
pub struct ClashLogger {
44+
logs: Arc<RwLock<VecDeque<String>>>,
45+
}
46+
47+
impl ClashLogger {
48+
pub fn global() -> &'static ClashLogger {
49+
static LOGGER: OnceLock<ClashLogger> = OnceLock::new();
50+
51+
LOGGER.get_or_init(|| ClashLogger {
52+
logs: Arc::new(RwLock::new(VecDeque::with_capacity(LOGS_QUEUE_LEN + 10))),
53+
})
54+
}
55+
56+
pub async fn get_logs(&self) -> RwLockReadGuard<'_, VecDeque<String>> {
57+
self.logs.read().await
58+
}
59+
60+
pub async fn append_log(&self, text: String) {
61+
let mut logs = self.logs.write().await;
62+
if logs.len() > LOGS_QUEUE_LEN {
63+
logs.pop_front();
64+
}
65+
logs.push_back(text);
66+
}
67+
68+
pub async fn clear_logs(&self) {
69+
let mut logs = self.logs.write().await;
70+
logs.clear();
71+
}
72+
}
73+
3974
pub struct CoreManager {
4075
running_child: Arc<Mutex<Option<ChildGuard>>>,
4176
running_config: Arc<Mutex<Option<ClashConfig>>>,
@@ -81,6 +116,7 @@ impl CoreManager {
81116

82117
pub async fn stop_core(&mut self) -> Result<()> {
83118
info!("Stopping core");
119+
ClashLogger::global().clear_logs().await;
84120

85121
let child_guard = self.running_child.lock().await.take();
86122
drop(child_guard);
@@ -176,6 +212,7 @@ pub async fn run_with_logging(
176212
tokio::spawn(async move {
177213
let w = shared_writer_clone.lock().await;
178214
while let Ok(Some(line)) = stdout_reader.next_line().await {
215+
ClashLogger::global().append_log(line.clone()).await;
179216
let mut now = DeferredNow::default();
180217
let arg = format_args!("{}", line);
181218
let record = Record::builder()
@@ -192,6 +229,7 @@ pub async fn run_with_logging(
192229
tokio::spawn(async move {
193230
let w = shared_writer_clone.lock().await;
194231
while let Ok(Some(line)) = stderr_reader.next_line().await {
232+
ClashLogger::global().append_log(line.clone()).await;
195233
let mut now = DeferredNow::default();
196234
let arg = format_args!("{}", line);
197235
let record = Record::builder()

src/core/server.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::state::IpcState;
2-
use crate::core::manager::CORE_MANAGER;
2+
use crate::core::manager::{CORE_MANAGER, ClashLogger};
33
use crate::core::structure::Response;
44
use crate::{ClashConfig, IpcCommand, VERSION};
55
use http::StatusCode;
@@ -200,6 +200,17 @@ fn create_ipc_router() -> Result<Router> {
200200
.build()),
201201
}
202202
})
203+
.get(IpcCommand::GetClashLogs.as_ref(), |_| async move {
204+
let json_value = Response {
205+
code: 0,
206+
message: "Success".to_string(),
207+
data: Some(ClashLogger::global().get_logs().await.clone()),
208+
};
209+
Ok(HttpResponse::builder()
210+
.status(StatusCode::OK)
211+
.json(&json_value)?
212+
.build())
213+
})
203214
.delete(IpcCommand::StopClash.as_ref(), |_| async move {
204215
match CORE_MANAGER.lock().await.stop_core().await {
205216
Ok(_) => info!("Core stopped successfully"),

0 commit comments

Comments
 (0)