Skip to main content

diskr/health/
logger.rs

1use anyhow::Result;
2use serde::Serialize;
3use std::path::PathBuf;
4use std::process::Command;
5
6#[derive(Debug, Clone, Serialize)]
7pub struct LogSource {
8    pub label: String,
9    pub path: Option<PathBuf>,
10    pub size_bytes: u64,
11}
12
13pub fn scan_logs() -> Vec<LogSource> {
14    let mut out = Vec::new();
15
16    if let Some(size) = journald_size() {
17        out.push(LogSource { label: "journald".into(), path: Some(PathBuf::from("/var/log/journal")), size_bytes: size });
18    }
19    for p in ["/var/log/syslog", "/var/log/syslog.1", "/var/log/kern.log"] {
20        if let Ok(meta) = std::fs::metadata(p) {
21            out.push(LogSource { label: p.to_string(), path: Some(PathBuf::from(p)), size_bytes: meta.len() });
22        }
23    }
24    if let Some(home) = dirs::home_dir() {
25        let share = home.join(".local/share");
26        if let Ok(entries) = std::fs::read_dir(&share) {
27            for e in entries.flatten() {
28                let p = e.path();
29                if p.extension().and_then(|x| x.to_str()) == Some("log") {
30                    if let Ok(meta) = e.metadata() {
31                        out.push(LogSource { label: p.display().to_string(), path: Some(p), size_bytes: meta.len() });
32                    }
33                }
34            }
35        }
36    }
37    out.sort_by(|a, b| b.size_bytes.cmp(&a.size_bytes));
38    out
39}
40
41fn journald_size() -> Option<u64> {
42    let out = Command::new("journalctl").arg("--disk-usage").output().ok()?;
43    let text = String::from_utf8_lossy(&out.stdout);
44    let mb = text.split_whitespace().find(|w| w.parse::<f64>().is_ok())?.parse::<f64>().ok()?;
45    Some((mb * 1024.0 * 1024.0) as u64)
46}
47
48pub fn vacuum_journald(keep: &str) -> Result<()> {
49    Command::new("journalctl").arg(format!("--vacuum-time={keep}")).status()?;
50    Ok(())
51}