cyfs_debug/log/
cyfs_log.rs

1use super::constants::*;
2use super::flexi_log::*;
3use super::log_config::*;
4use super::target::*;
5use crate::debug_config::*;
6use cyfs_base::BuckyResult;
7use cyfs_util::get_cyfs_root_path;
8
9use log::Log;
10use std::path::PathBuf;
11use std::str::FromStr;
12
13pub struct CyfsLogger {
14    config: LogConfig,
15    logger: FlexiLogger,
16}
17
18pub enum CyfsLoggerCategory {
19    Service,
20    App,
21}
22
23pub struct CyfsLoggerBuilder {
24    config: LogConfig,
25    targets: Vec<Box<dyn CyfsLogTarget>>,
26    disable_file_config: bool,
27}
28
29impl CyfsLoggerBuilder {
30    pub fn new_service(name: &str) -> Self {
31        Self::new(name, CyfsLoggerCategory::Service)
32    }
33
34    pub fn new_app(name: &str) -> Self {
35        Self::new(name, CyfsLoggerCategory::App)
36    }
37
38    pub fn new(name: &str, category: CyfsLoggerCategory) -> Self {
39        // simple_logger::SimpleLogger::default().init().unwrap();
40
41        let log_dir = Self::get_log_dir(name, &category);
42        let config = LogConfig::new(log_dir);
43        Self {
44            config,
45            targets: vec![],
46            disable_file_config: false,
47        }
48    }
49
50    pub fn directory(mut self, dir: impl Into<PathBuf>) -> Self {
51        self.config.set_log_dir(dir.into());
52        self
53    }
54
55    pub fn level(mut self, level: &str) -> Self {
56        self.config.global.set_level(level);
57        self
58    }
59
60    pub fn console(mut self, level: &str) -> Self {
61        self.config.global.set_console(level);
62        self
63    }
64
65    pub fn file(mut self, enable: bool) -> Self {
66        self.config.global.file = enable;
67        self
68    }
69
70    pub fn file_max_count(mut self, file_max_count: u32) -> Self {
71        self.config.global.set_file_max_count(file_max_count);
72        self
73    }
74
75    pub fn file_max_size(mut self, file_max_size: u64) -> Self {
76        self.config.global.set_file_max_size(file_max_size);
77        self
78    }
79
80    pub fn enable_bdt(mut self, level: Option<&str>, console_level: Option<&str>) -> Self {
81        let config =
82            Self::bdt_module(level, console_level).expect(&format!("invalid bdt log config"));
83        self.config.add_mod(config);
84
85        self
86    }
87
88    pub fn module(mut self, name: &str, level: Option<&str>, console_level: Option<&str>) -> Self {
89        let config = Self::new_module(name, name, level, console_level)
90            .expect(&format!("invalid module log config"));
91        self.config.add_mod(config);
92
93        self
94    }
95
96    pub fn target(mut self, target: Box<dyn CyfsLogTarget>) -> Self {
97        self.targets.push(target);
98        self
99    }
100
101    pub fn disable_module(mut self, list: Vec<impl Into<String>>, level: LogLevel) -> Self {
102        for name in list {
103            let name = name.into();
104            self.config.disable_module_log(&name, &level);
105        }
106        self
107    }
108
109    // do not use {cyfs}/etc/debug.toml
110    pub fn disable_file_config(mut self, disable: bool) -> Self {
111        self.disable_file_config = disable;
112        self
113    }
114
115    pub fn debug_info_flags(mut self, flags: u32) -> Self {
116        self.config.global.set_debug_info_flags(flags);
117        self
118    }
119
120    pub fn build(mut self) -> BuckyResult<CyfsLogger> {
121        self.config.disable_async_std_log();
122
123        if !self.disable_file_config {
124            if let Some(config_node) = DebugConfig::get_config("log") {
125                if let Err(e) = self.config.load(config_node) {
126                    println!("load log config error! {}", e);
127                }
128            }
129        }
130
131        let logger = FlexiLogger::new(&self.config, self.targets)?;
132
133        let ret = CyfsLogger {
134            config: self.config,
135            logger,
136        };
137
138        Ok(ret)
139    }
140
141    pub fn get_log_dir(name: &str, category: &CyfsLoggerCategory) -> PathBuf {
142        assert!(!name.is_empty());
143
144        let mut root = get_cyfs_root_path();
145        let folder = match *category {
146            CyfsLoggerCategory::Service => "log",
147            CyfsLoggerCategory::App => "log/app",
148        };
149        root.push(folder);
150
151        root.push(name);
152        root
153    }
154
155    fn new_module(
156        name: &str,
157        file_name: &str,
158        level: Option<&str>,
159        console_level: Option<&str>,
160    ) -> BuckyResult<LogModuleConfig> {
161        let mut config = LogModuleConfig::new_default(name);
162        if let Some(level) = level {
163            config.level = LogLevel::from_str(level)?;
164        }
165        if let Some(level) = console_level {
166            config.console = LogLevel::from_str(level)?;
167        }
168
169        config.file_name = Some(file_name.to_owned());
170        Ok(config)
171    }
172
173    fn bdt_module(
174        level: Option<&str>,
175        console_level: Option<&str>,
176    ) -> BuckyResult<LogModuleConfig> {
177        Self::new_module("cyfs_bdt", "bdt", level, console_level)
178    }
179}
180
181impl Into<Box<dyn Log>> for CyfsLogger {
182    fn into(self) -> Box<dyn Log> {
183        Box::new(self.logger) as Box<dyn Log>
184    }
185}
186
187impl CyfsLogger {
188    pub fn start(self) {
189        let max_level = self.logger.get_max_level();
190        println!("log max level: {}", max_level);
191        log::set_max_level(max_level.into());
192
193        let flags = self.config.global.get_debug_info_flags();
194
195        if let Err(e) = log::set_boxed_logger(self.into()) {
196            let msg = format!("call set_boxed_logger failed! {}", e);
197            println!("{}", msg);
198        }
199
200        Self::display_debug_info(flags);
201    }
202
203    pub fn display_debug_info(flags: LogDebugInfoFlags) {
204        
205        // Output environmental information to diagnose some environmental problems
206        if flags.is_args_present() {
207            for argument in std::env::args() {
208                info!("arg: {}", argument);
209            }
210        }
211
212        // info!("current exe: {:?}", std::env::current_exe());
213        info!("current dir: {:?}", std::env::current_dir());
214
215        info!("current version: {}", cyfs_base::get_version());
216
217        if flags.is_env_present() {
218            for (key, value) in std::env::vars() {
219                info!("env: {}: {}", key, value);
220            }
221        }
222    }
223
224    pub fn flush() {
225        log::logger().flush();
226    }
227}