rush_sync_server/commands/log_level/
manager.rs1use 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 {
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 &[¤t_name, ¤t_number]
21 ),
22 Self::show_help_i18n()
23 )
24 }
25
26 pub fn show_help_i18n() -> String {
28 get_command_translation("system.commands.log_level.help_text", &[])
29 }
30
31 pub fn show_help() -> String {
33 Self::show_help_i18n()
34 }
35
36 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 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 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 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 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 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}