extlog/
loglib.rs

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};
19//use std::collections::HashMap;
20use 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}