rush_sync_server/commands/log_level/
manager.rs

1use crate::core::prelude::*;
2use log::LevelFilter;
3use std::sync::Mutex;
4
5pub struct LogLevelManager;
6
7static CURRENT_LOG_LEVEL: Mutex<LevelFilter> = Mutex::new(LevelFilter::Info);
8
9impl LogLevelManager {
10    // ✅ STATUS DISPLAY mit i18n
11    pub fn show_status() -> String {
12        let current = Self::get_current_level();
13        let current_name = Self::level_to_name(current);
14        let current_number = Self::level_to_number(current);
15
16        format!(
17            "{}\n{}",
18            get_command_translation(
19                "system.commands.log_level.current_status",
20                &[&current_name, &current_number]
21            ),
22            Self::show_help_i18n()
23        )
24    }
25
26    // ✅ HELP TEXT mit i18n
27    pub fn show_help_i18n() -> String {
28        get_command_translation("system.commands.log_level.help_text", &[])
29    }
30
31    // ✅ Legacy method (for compatibility)
32    pub fn show_help() -> String {
33        Self::show_help_i18n()
34    }
35
36    // ✅ SET LEVEL mit i18n - FIXED RETURN TYPE
37    pub fn set_level_persistent(level_input: &str) -> std::result::Result<String, String> {
38        let level_filter = match level_input {
39            "1" => LevelFilter::Error,
40            "2" => LevelFilter::Warn,
41            "3" => LevelFilter::Info,
42            "4" => LevelFilter::Debug,
43            "5" => LevelFilter::Trace,
44            "error" | "ERROR" => LevelFilter::Error,
45            "warn" | "WARN" | "warning" => LevelFilter::Warn,
46            "info" | "INFO" => LevelFilter::Info,
47            "debug" | "DEBUG" => LevelFilter::Debug,
48            "trace" | "TRACE" => LevelFilter::Trace,
49            _ => {
50                return Err(get_command_translation(
51                    "system.commands.log_level.invalid_level",
52                    &[level_input],
53                ));
54            }
55        };
56
57        Self::set_level_runtime(level_filter);
58
59        // Async save with i18n error handling - FIXED ERROR HANDLING
60        tokio::spawn(async move {
61            if let Err(e) = Self::save_to_config(level_filter).await {
62                log::warn!(
63                    "{}",
64                    get_translation("language.service.save_failed", &[&e.to_string()])
65                );
66            }
67        });
68
69        let level_name = Self::level_to_name(level_filter);
70        let level_number = Self::level_to_number(level_filter);
71
72        Ok(get_command_translation(
73            "system.commands.log_level.changed_success",
74            &[&level_name, &level_number],
75        ))
76    }
77
78    // ✅ Unchanged core functionality
79    pub fn set_level_runtime(level_filter: LevelFilter) {
80        if let Ok(mut current) = CURRENT_LOG_LEVEL.lock() {
81            *current = level_filter;
82        }
83        log::set_max_level(level_filter);
84    }
85
86    pub async fn load_from_config() -> LevelFilter {
87        match crate::core::config::Config::load_with_messages(false).await {
88            Ok(config) => match Self::string_to_level_filter(&config.log_level) {
89                Ok(level) => level,
90                Err(_) => {
91                    log::warn!(
92                        "{}",
93                        get_translation(
94                            "config.validation.invalid_log_level",
95                            &[&config.log_level]
96                        )
97                    );
98                    LevelFilter::Info
99                }
100            },
101            Err(_) => LevelFilter::Info,
102        }
103    }
104
105    // ✅ FIXED SAVE TO CONFIG - Uses proper AppError
106    async fn save_to_config(level_filter: LevelFilter) -> Result<()> {
107        match crate::core::config::Config::load_with_messages(false).await {
108            Ok(mut config) => {
109                config.log_level = Self::level_filter_to_string(level_filter);
110                config.save().await
111            }
112            Err(e) => Err(e),
113        }
114    }
115
116    // ✅ Unchanged helper methods
117    pub fn get_current_level() -> LevelFilter {
118        if let Ok(current) = CURRENT_LOG_LEVEL.lock() {
119            *current
120        } else {
121            log::max_level()
122        }
123    }
124
125    pub fn init_with_level(level: LevelFilter) {
126        if let Ok(mut current) = CURRENT_LOG_LEVEL.lock() {
127            *current = level;
128        }
129        log::set_max_level(level);
130    }
131
132    // ✅ FIXED STRING TO LEVEL FILTER - Uses proper Result<T>
133    fn string_to_level_filter(s: &str) -> std::result::Result<LevelFilter, ()> {
134        match s.to_lowercase().as_str() {
135            "error" | "1" => Ok(LevelFilter::Error),
136            "warn" | "warning" | "2" => Ok(LevelFilter::Warn),
137            "info" | "3" => Ok(LevelFilter::Info),
138            "debug" | "4" => Ok(LevelFilter::Debug),
139            "trace" | "5" => Ok(LevelFilter::Trace),
140            "off" | "0" => Ok(LevelFilter::Off),
141            _ => Err(()),
142        }
143    }
144
145    fn level_filter_to_string(level: LevelFilter) -> String {
146        match level {
147            LevelFilter::Error => "error".to_string(),
148            LevelFilter::Warn => "warn".to_string(),
149            LevelFilter::Info => "info".to_string(),
150            LevelFilter::Debug => "debug".to_string(),
151            LevelFilter::Trace => "trace".to_string(),
152            LevelFilter::Off => "off".to_string(),
153        }
154    }
155
156    fn level_to_name(level: LevelFilter) -> String {
157        match level {
158            LevelFilter::Error => "ERROR".to_string(),
159            LevelFilter::Warn => "WARN".to_string(),
160            LevelFilter::Info => "INFO".to_string(),
161            LevelFilter::Debug => "DEBUG".to_string(),
162            LevelFilter::Trace => "TRACE".to_string(),
163            LevelFilter::Off => "OFF".to_string(),
164        }
165    }
166
167    fn level_to_number(level: LevelFilter) -> String {
168        match level {
169            LevelFilter::Error => "1".to_string(),
170            LevelFilter::Warn => "2".to_string(),
171            LevelFilter::Info => "3".to_string(),
172            LevelFilter::Debug => "4".to_string(),
173            LevelFilter::Trace => "5".to_string(),
174            LevelFilter::Off => "0".to_string(),
175        }
176    }
177}