feat: file logging on client, logs command to fetch last N lines
This commit is contained in:
parent
23bbb5b603
commit
db3fa9f416
6 changed files with 130 additions and 9 deletions
59
crates/client/src/logger.rs
Normal file
59
crates/client/src/logger.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/// File logger — writes structured log lines alongside the pretty terminal output.
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
|
||||
static LOG_FILE: OnceLock<Mutex<File>> = OnceLock::new();
|
||||
static LOG_PATH: OnceLock<String> = OnceLock::new();
|
||||
|
||||
pub fn init() {
|
||||
let path = log_path();
|
||||
// Create parent dir if needed
|
||||
if let Some(parent) = std::path::Path::new(&path).parent() {
|
||||
let _ = std::fs::create_dir_all(parent);
|
||||
}
|
||||
match OpenOptions::new().create(true).append(true).open(&path) {
|
||||
Ok(f) => {
|
||||
LOG_PATH.set(path.clone()).ok();
|
||||
LOG_FILE.set(Mutex::new(f)).ok();
|
||||
write_line("INFO", "helios-remote started");
|
||||
}
|
||||
Err(e) => eprintln!("[logger] Failed to open log file {path}: {e}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn log_path() -> String {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let base = std::env::var("LOCALAPPDATA")
|
||||
.unwrap_or_else(|_| "C:\\Temp".to_string());
|
||||
format!("{base}\\helios-remote\\helios-remote.log")
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
"/tmp/helios-remote.log".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_log_path() -> String {
|
||||
LOG_PATH.get().cloned().unwrap_or_else(log_path)
|
||||
}
|
||||
|
||||
pub fn write_line(level: &str, msg: &str) {
|
||||
let now = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
|
||||
let line = format!("{now} [{level:<5}] {msg}\n");
|
||||
if let Some(mutex) = LOG_FILE.get() {
|
||||
if let Ok(mut f) = mutex.lock() {
|
||||
let _ = f.write_all(line.as_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the last `n` lines from the log file.
|
||||
pub fn tail(n: u32) -> String {
|
||||
let path = get_log_path();
|
||||
let content = std::fs::read_to_string(&path).unwrap_or_default();
|
||||
let lines: Vec<&str> = content.lines().collect();
|
||||
let start = lines.len().saturating_sub(n as usize);
|
||||
lines[start..].join("\n")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue