1
2
3#[cfg(target_os = "windows")]
4use crate::loglib_windows::{win_output_debug};
5use log::{LevelFilter};
6use log::{error, info, trace,warn,debug};
7use log4rs::append::console::{ConsoleAppender, Target};
8use log4rs::append::file::FileAppender;
9use log4rs::config::{Appender, Config, Root,RootBuilder,ConfigBuilder};
10use log4rs::encode::pattern::PatternEncoder;
11use log4rs::filter::threshold::ThresholdFilter;
12use log4rs::append::rolling_file::RollingFileAppender;
13use log4rs::append::rolling_file::policy::compound::CompoundPolicy;
14use log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger;
15use log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller;
16use std::error::Error;
17use std::boxed::Box;
18use chrono::{Local,Datelike,Timelike};
19use lazy_static::lazy_static;
21
22use std::sync::{Mutex,Arc};
23
24
25
26const DEFAULT_MSG_FMT :&str = "{m}";
27
28lazy_static! {
29 static ref LOGGER_LEVEL :Arc<Mutex<i64>> = Arc::new(Mutex::new(0 as i64));
30}
31
32fn get_logger_level() -> i64 {
33 let scb = LOGGER_LEVEL.lock().unwrap();
34 let retv :i64;
35 retv = *scb;
36 return retv;
37}
38
39fn set_logger_level(nv :i64) -> i64 {
40 let mut scb = LOGGER_LEVEL.lock().unwrap();
41 let retv :i64;
42
43 retv = *scb;
44 *scb = nv;
45 return retv;
46}
47
48fn parse_log_var(s :&str) -> (String,u64,u32) {
49 let sarr :Vec<&str> = s.split(",").collect();
50 let fname :String;
51 let mut fsize :u64 = 0;
52 let mut times :u32 = 0;
53 if sarr.len() > 1 {
54 fname = format!("{}",sarr[0]);
55 let bss :String = format!("{}",sarr[1]);
56 let bs2 = &bss;
57 let bs = bs2.as_bytes();
58 let mut number :String = "".to_string();
59 let mut unit :String = "".to_string();
60 let mut n :usize = bs.len();
61 match bs2.find(|c :char| !c.is_digit(10)) {
62 Some(vn) => {n = vn},
63 None => {},
64 }
65 let mut idx :usize = 0 ;
66 while idx < n {
67 number.push(bs[idx] as char);
68 idx += 1;
69 }
70
71 while idx < bs.len() {
72 unit.push(bs[idx] as char);
73 idx += 1;
74 }
75
76
77 match number.parse::<u64>() {
78 Ok(n) => {fsize = n},
79 Err(_e) => {},
80 }
81 if unit == "b" || unit == "B" {
82 fsize = fsize;
83 } else if unit == "k" || unit == "K" {
84 fsize *= 1024;
85 } else if unit == "m" || unit == "M" {
86 fsize *= 1024 * 1024;
87 } else if unit == "g" || unit == "G" {
88 fsize *= 1024 * 1024 * 1024;
89 } else if unit == "t" || unit == "T" {
90 fsize *= 1024 * 1024 * 1024 * 1024;
91 }
92
93 if sarr.len() > 2 {
94 let tstr:String = format!("{}",sarr[2]);
95 match tstr.parse::<u32>() {
96 Ok(n) => {times = n},
97 Err(_e) => {},
98 }
99 }
100
101 } else {
102 fname = format!("{}",s);
103 }
104 return (fname,fsize,times);
105}
106
107pub struct ExtLogVar {
108 pub lognostderr : bool,
109 pub logfiles :Vec<String>,
110 pub logapps :Vec<String>,
111 pub logverbose :i64,
112}
113
114impl Default for ExtLogVar {
115 fn default() -> Self {
116 Self {
117 lognostderr : false,
118 logfiles : Vec::new(),
119 logapps : Vec::new(),
120 logverbose : 0,
121 }
122 }
123}
124
125
126pub fn ext_init_log(ns :&ExtLogVar) -> Result<(),Box<dyn Error>> {
127 let level :LevelFilter;
128 let mut rbuiler :RootBuilder;
129 let mut cbuild :ConfigBuilder;
130 let mut sarr :Vec<String>;
131 let retv :i64;
132 let nostderr :bool;
133 let stderr =ConsoleAppender::builder().encoder(Box::new(PatternEncoder::new(DEFAULT_MSG_FMT))).target(Target::Stderr).build();
134
135 retv = ns.logverbose;
136
137 if retv >= 4 {
138 level = log::LevelFilter::Trace;
139 } else if retv >= 3 {
140 level = log::LevelFilter::Debug;
141 } else if retv >= 2 {
142 level = log::LevelFilter::Info;
143 } else if retv >= 1 {
144 level = log::LevelFilter::Warn;
145 } else {
146 level = log::LevelFilter::Error;
147 }
148
149 set_logger_level(retv);
150
151 cbuild = Config::builder();
152 rbuiler = Root::builder();
153 nostderr = ns.lognostderr;
154
155
156 if !nostderr {
157 cbuild = cbuild.appender(
158 Appender::builder()
159 .filter(Box::new(ThresholdFilter::new(level)))
160 .build("stderr", Box::new(stderr)),
161 );
162 rbuiler = rbuiler.appender("stderr");
163 }
164
165
166 sarr = ns.logfiles.clone();
167 for wf in sarr.iter() {
168 let (fname,fsize,times) = parse_log_var(wf);
169 if fsize == 0 {
170 let logfile = FileAppender::builder().append(false).encoder(Box::new(PatternEncoder::new(DEFAULT_MSG_FMT))).build(&fname)?;
171 cbuild = cbuild.appender(Appender::builder().build(&fname, Box::new(logfile)));
172 rbuiler = rbuiler.appender(&fname);
173 } else {
174 let fpattern = format!("{}.{{}}",fname);
175 let mut tfiles :u32 = 1;
176 if times > 0 {
177 tfiles = times;
178 }
179 let logfile = RollingFileAppender::builder().append(false).encoder(Box::new(PatternEncoder::new(DEFAULT_MSG_FMT))).build(&fname,
180 Box::new(CompoundPolicy::new(
181 Box::new(SizeTrigger::new(fsize)),
182 Box::new(FixedWindowRoller::builder().build(&fpattern,tfiles).unwrap())
183 )))?;
184 cbuild = cbuild.appender(Appender::builder().build(&fname, Box::new(logfile)));
185 rbuiler = rbuiler.appender(&fname);
186 }
187 }
188
189
190 sarr = ns.logapps.clone();
191 for wf in sarr.iter() {
192 let (fname,fsize,times) = parse_log_var(wf);
193 if fsize == 0 {
194 let logfile = FileAppender::builder().append(true).encoder(Box::new(PatternEncoder::new(DEFAULT_MSG_FMT))).build(wf)?;
195 cbuild = cbuild.appender(Appender::builder().build(wf, Box::new(logfile)));
196 rbuiler = rbuiler.appender(wf);
197 } else {
198 let fpattern = format!("{}.{{}}",fname);
199 let mut tfiles :u32 = 1;
200 if times > 0 {
201 tfiles = times;
202 }
203 let logfile = RollingFileAppender::builder().append(true).encoder(Box::new(PatternEncoder::new(DEFAULT_MSG_FMT))).build(&fname,
204 Box::new(CompoundPolicy::new(
205 Box::new(SizeTrigger::new(fsize)),
206 Box::new(FixedWindowRoller::builder().build(&fpattern,tfiles).unwrap())
207 )))?;
208 cbuild = cbuild.appender(Appender::builder().build(&fname, Box::new(logfile)));
209 rbuiler = rbuiler.appender(&fname);
210 }
211 }
212
213
214 let config = cbuild.build(rbuiler.build(level))?;
215 let _ = log4rs::init_config(config)?;
216
217 Ok(())
218}
219
220
221
222pub fn log_get_timestamp() -> String {
223 let now = Local::now();
224 return format!("{}/{}/{} {}:{}:{}",now.year(),now.month(),now.day(),now.hour(),now.minute(),now.second());
225}
226
227#[cfg(target_os = "windows")]
228fn log_output_function_inner(level :i64, outs :&str) {
229 if level <= get_logger_level() {
230 if level == 0 {
231 error!("{}",outs);
232 } else if level == 1 {
233 warn!("{}",outs);
234 } else if level == 2 {
235 info!("{}",outs);
236 } else if level == 3 {
237 debug!("{}",outs);
238 } else if level >= 4 {
239 trace!("{}",outs);
240 }
241 win_output_debug(outs);
242 }
243 return;
244}
245
246#[cfg(not(target_os = "windows"))]
247fn log_output_function_inner(level :i64, outs :&str) {
248 if level <= get_logger_level() {
249 if level == 0 {
250 error!("{}",outs);
251 } else if level == 1 {
252 warn!("{}",outs);
253 } else if level == 2 {
254 info!("{}",outs);
255 } else if level == 3 {
256 debug!("{}",outs);
257 } else if level >= 4 {
258 trace!("{}",outs);
259 }
260 }
261 return;
262}
263
264
265pub fn log_output_function(level :i64, outs :&str) {
266 return log_output_function_inner(level,outs);
267}
268
269#[macro_export]
270macro_rules! format_str_log {
271 ($info:tt,$iv:expr,$($arg:tt)+) => {
272 let mut c :String= format!("[{}:{}]",file!(),line!());
273 c.push_str(&format!("{} ",$info));
274 c.push_str(&log_get_timestamp());
275 c.push_str(": ");
276 c.push_str(&(format!($($arg)+)[..]));
277 c.push_str("\n");
278 log_output_function($iv, &c);
279 }
280}
281
282#[macro_export]
283macro_rules! debug_error {
284 ($($arg:tt)+) => {
285 format_str_log!("<ERROR>",0,$($arg)+);
286 }
287}
288
289#[macro_export]
290macro_rules! debug_warn {
291 ($($arg:tt)+) => {
292 format_str_log!("<WARN>",1,$($arg)+);
293 }
294}
295
296
297#[macro_export]
298macro_rules! debug_info {
299 ($($arg:tt)+) => {
300 format_str_log!("<INFO>",2,$($arg)+);
301 }
302}
303
304#[macro_export]
305macro_rules! debug_debug {
306 ($($arg:tt)+) => {
307 format_str_log!("<DEBUG>",3,$($arg)+);
308 }
309}
310
311
312#[macro_export]
313macro_rules! debug_trace {
314 ($($arg:tt)+) => {
315 format_str_log!("<TRACE>",4,$($arg)+);
316 }
317}
318
319#[macro_export]
320macro_rules! format_buffer_log {
321 ($buf:expr,$len:expr,$info:tt,$iv:expr,$($arg:tt)+) => {
322 let mut c :String = format!("[{}:{}]",file!(),line!());
323 c.push_str(&format!("{} ",$info));
324 c.push_str(&log_get_timestamp());
325 c.push_str(": ");
326 c.push_str(&(format!($($arg)+)[..]));
327 let _ptr :*const u8 = $buf as *const u8;
328 let mut _ci :usize;
329 let _totallen: usize = $len as usize;
330 let mut _lasti :usize = 0;
331 let mut _nb :u8;
332 c.push_str(&format!(" buffer [{:?}][{}]",_ptr,_totallen));
333 _ci = 0;
334 while _ci < _totallen {
335 if (_ci % 16) == 0 {
336 if _ci > 0 {
337 c.push_str(" ");
338 while _lasti < _ci {
339 unsafe{
340 _nb = *_ptr.offset(_lasti as isize);
341 }
342
343 if _nb >= 0x20 && _nb <= 0x7e {
344 c.push(_nb as char);
345 } else {
346 c.push_str(".");
347 }
348 _lasti += 1;
349 }
350 }
351 c.push_str(&format!("\n0x{:08x}:", _ci));
352 }
353 unsafe {_nb = *_ptr.offset(_ci as isize);}
354 c.push_str(&format!(" 0x{:02x}",_nb));
355 _ci += 1;
356 }
357
358 if _lasti < _ci {
359 while (_ci % 16) != 0 {
360 c.push_str(" ");
361 _ci += 1;
362 }
363
364 c.push_str(" ");
365
366 while _lasti < _totallen {
367 unsafe {_nb = *_ptr.offset(_lasti as isize);}
368 if _nb >= 0x20 && _nb <= 0x7e {
369 c.push(_nb as char);
370 } else {
371 c.push_str(".");
372 }
373 _lasti += 1;
374 }
375 }
376 c.push_str("\n");
377 log_output_function($iv,&c);
378 }
379}
380
381#[macro_export]
382macro_rules! debug_buffer_error {
383 ($buf:expr,$len:expr,$($arg:tt)+) => {
384 format_buffer_log!($buf,$len,"<ERROR>",0,$($arg)+);
385 }
386}
387
388#[macro_export]
389macro_rules! debug_buffer_warn {
390 ($buf:expr,$len:expr,$($arg:tt)+) => {
391 format_buffer_log!($buf,$len,"<WARN>",1,$($arg)+);
392 }
393}
394
395#[macro_export]
396macro_rules! debug_buffer_info {
397 ($buf:expr,$len:expr,$($arg:tt)+) => {
398 format_buffer_log!($buf,$len,"<INFO>",2,$($arg)+);
399 }
400}
401
402#[macro_export]
403macro_rules! debug_buffer_debug {
404 ($buf:expr,$len:expr,$($arg:tt)+) => {
405 format_buffer_log!($buf,$len,"<DEBUG>",3,$($arg)+);
406 }
407}
408
409#[macro_export]
410macro_rules! debug_buffer_trace {
411 ($buf:expr,$len:expr,$($arg:tt)+) => {
412 format_buffer_log!($buf,$len,"<TRACE>",4,$($arg)+);
413 }
414}