cyfs_debug/log/
cyfs_log.rs1use 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 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 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 if flags.is_args_present() {
207 for argument in std::env::args() {
208 info!("arg: {}", argument);
209 }
210 }
211
212 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}