Skip to main content

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    pub fn show_status() -> String {
11        let current = Self::get_current_level();
12        let current_name = Self::level_to_name(current);
13        let current_number = Self::level_to_number(current);
14
15        format!(
16            "{}\n{}",
17            get_command_translation(
18                "system.commands.log_level.current_status",
19                &[&current_name, &current_number]
20            ),
21            Self::show_help_i18n()
22        )
23    }
24
25    pub fn show_help_i18n() -> String {
26        get_command_translation("system.commands.log_level.help_text", &[])
27    }
28
29    pub fn show_help() -> String {
30        Self::show_help_i18n()
31    }
32
33    pub fn set_level_persistent(level_input: &str) -> Result<String> {
34        use log::LevelFilter;
35
36        let level_filter = match level_input {
37            "1" => LevelFilter::Error,
38            "2" => LevelFilter::Warn,
39            "3" => LevelFilter::Info,
40            "4" => LevelFilter::Debug,
41            "5" => LevelFilter::Trace,
42            "error" | "ERROR" => LevelFilter::Error,
43            "warn" | "WARN" | "warning" => LevelFilter::Warn,
44            "info" | "INFO" => LevelFilter::Info,
45            "debug" | "DEBUG" => LevelFilter::Debug,
46            "trace" | "TRACE" => LevelFilter::Trace,
47            _ => {
48                return Err(AppError::Validation(get_command_translation(
49                    "system.commands.log_level.invalid_level",
50                    &[level_input],
51                )));
52            }
53        };
54
55        Self::init_with_level(level_filter);
56        Ok(get_command_translation(
57            "system.commands.log_level.changed",
58            &[level_input],
59        ))
60    }
61
62    pub fn set_level_runtime(level_filter: LevelFilter) {
63        if let Ok(mut current) = CURRENT_LOG_LEVEL.lock() {
64            *current = level_filter;
65        }
66        log::set_max_level(level_filter);
67    }
68
69    pub async fn load_from_config() -> LevelFilter {
70        match crate::core::config::Config::load_with_messages(false).await {
71            Ok(config) => match Self::string_to_level_filter(&config.log_level) {
72                Ok(level) => level,
73                Err(_) => {
74                    log::warn!(
75                        "{}",
76                        get_translation(
77                            "config.validation.invalid_log_level",
78                            &[&config.log_level]
79                        )
80                    );
81                    LevelFilter::Info
82                }
83            },
84            Err(_) => LevelFilter::Info,
85        }
86    }
87
88    pub fn get_current_level() -> LevelFilter {
89        if let Ok(current) = CURRENT_LOG_LEVEL.lock() {
90            *current
91        } else {
92            log::max_level()
93        }
94    }
95
96    pub fn init_with_level(level: LevelFilter) {
97        if let Ok(mut current) = CURRENT_LOG_LEVEL.lock() {
98            *current = level;
99        }
100        log::set_max_level(level);
101    }
102
103    fn string_to_level_filter(s: &str) -> std::result::Result<LevelFilter, ()> {
104        match s.to_lowercase().as_str() {
105            "error" | "1" => Ok(LevelFilter::Error),
106            "warn" | "warning" | "2" => Ok(LevelFilter::Warn),
107            "info" | "3" => Ok(LevelFilter::Info),
108            "debug" | "4" => Ok(LevelFilter::Debug),
109            "trace" | "5" => Ok(LevelFilter::Trace),
110            "off" | "0" => Ok(LevelFilter::Off),
111            _ => Err(()),
112        }
113    }
114
115    fn level_to_name(level: LevelFilter) -> String {
116        match level {
117            LevelFilter::Error => "ERROR".to_string(),
118            LevelFilter::Warn => "WARN".to_string(),
119            LevelFilter::Info => "INFO".to_string(),
120            LevelFilter::Debug => "DEBUG".to_string(),
121            LevelFilter::Trace => "TRACE".to_string(),
122            LevelFilter::Off => "OFF".to_string(),
123        }
124    }
125
126    fn level_to_number(level: LevelFilter) -> String {
127        match level {
128            LevelFilter::Error => "1".to_string(),
129            LevelFilter::Warn => "2".to_string(),
130            LevelFilter::Info => "3".to_string(),
131            LevelFilter::Debug => "4".to_string(),
132            LevelFilter::Trace => "5".to_string(),
133            LevelFilter::Off => "0".to_string(),
134        }
135    }
136}