rush_sync_server/output/
logging.rs

1// ## BEGIN ##
2use crate::commands::log_level::LogLevelManager;
3use crate::core::prelude::*;
4use log::{Level, Log, Metadata, Record};
5use once_cell::sync::Lazy;
6use std::sync::{Arc, Mutex};
7
8const MAX_LOG_BUFFER: usize = 1000;
9const DRAIN_COUNT: usize = 100;
10
11static LOG_MESSAGES: Lazy<Arc<Mutex<Vec<LogMessage>>>> =
12    Lazy::new(|| Arc::new(Mutex::new(Vec::new())));
13
14#[derive(Debug, Clone)]
15pub struct LogMessage {
16    pub level: Option<Level>,
17    pub message: String,
18}
19
20impl LogMessage {
21    pub fn new<L: Into<Option<Level>>, S: Into<String>>(level: L, message: S) -> Self {
22        Self {
23            level: level.into(),
24            message: message.into(),
25        }
26    }
27
28    /// ✅ Statt ANSI → Marker (für dein parse_message_parts)
29    pub fn formatted(&self) -> String {
30        match self.level {
31            Some(level) => format!("[{}] {}", level.to_string().to_uppercase(), self.message),
32            None => self.message.clone(),
33        }
34    }
35}
36
37pub struct AppLogger;
38
39impl AppLogger {
40    pub fn log(level: Level, message: impl Into<String>) {
41        let mut logs = LOG_MESSAGES.lock().unwrap_or_else(|poisoned| {
42            log::warn!("Recovered from poisoned mutex");
43            poisoned.into_inner()
44        });
45
46        // Buffer-Größe begrenzen
47        if logs.len() >= MAX_LOG_BUFFER {
48            // Entferne die ältesten 100 Einträge
49            logs.drain(0..DRAIN_COUNT);
50
51            // Füge Warnung hinzu dass Logs gedroppt wurden
52            logs.push(LogMessage::new(
53                Some(Level::Warn),
54                format!(
55                    "[SYSTEM] Dropped {} old log messages to prevent memory overflow",
56                    DRAIN_COUNT
57                ),
58            ));
59        }
60
61        logs.push(LogMessage::new(Some(level), message));
62    }
63
64    pub fn log_plain(message: impl Into<String>) {
65        let mut logs = LOG_MESSAGES.lock().unwrap_or_else(|poisoned| {
66            log::warn!("Recovered from poisoned mutex");
67            poisoned.into_inner()
68        });
69
70        // Buffer-Größe begrenzen
71        if logs.len() >= MAX_LOG_BUFFER {
72            logs.drain(0..DRAIN_COUNT);
73        }
74
75        logs.push(LogMessage::new(None, message));
76    }
77
78    pub fn get_messages() -> Result<Vec<LogMessage>> {
79        let mut logs = LOG_MESSAGES.lock().unwrap_or_else(|poisoned| {
80            log::warn!("Recovered from poisoned mutex");
81            poisoned.into_inner()
82        });
83        let msgs = logs.clone();
84        logs.clear();
85        Ok(msgs)
86    }
87}
88
89/// ✅ Globaler Logger hookt alle log::* calls
90struct GlobalLogger;
91
92impl Log for GlobalLogger {
93    fn enabled(&self, metadata: &Metadata) -> bool {
94        metadata.level() <= Level::Trace
95    }
96
97    fn log(&self, record: &Record) {
98        // 🚨 Nachrichten werden nur bei get_messages() geleert
99        AppLogger::log(record.level(), record.args().to_string());
100    }
101
102    fn flush(&self) {}
103}
104
105pub async fn init() -> Result<()> {
106    if log::set_boxed_logger(Box::new(GlobalLogger)).is_ok() {
107        // ✅ LADE LOG-LEVEL AUS CONFIG
108        let config_level = LogLevelManager::load_from_config().await;
109        LogLevelManager::init_with_level(config_level);
110    }
111    Ok(())
112}