1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
extern crate log;
extern crate time;
use std::io::{ self, BufWriter, Write };
use std::cell::{ RefCell };
use std::thread;
use std::sync::mpsc;
use log::LogMetadata;
struct ConsoleLogger {
writer: RefCell<BufWriter<io::Stdout>>,
tx: mpsc::Sender<String>,
target: String,
}
impl ConsoleLogger {
pub fn new(tx: mpsc::Sender<String>, target: String) -> ConsoleLogger {
ConsoleLogger {
writer: RefCell::new(BufWriter::new(io::stdout())), tx: tx,
target: target,
}
}
pub fn enabled(&self, target: &str) -> bool {
target.starts_with(&self.target)
}
}
impl Drop for ConsoleLogger {
fn drop(&mut self) {
let _ = self.writer.borrow_mut().flush();
}
}
unsafe impl Sync for ConsoleLogger {}
impl log::Log for ConsoleLogger {
fn enabled(&self, metadata: &LogMetadata) -> bool {
self.enabled(metadata.target())
}
fn log(&self, record: &log::LogRecord) {
if !log::Log::enabled(self, record.metadata()) { return }
let s = format!(
"{} {:<5} [{}] {}\n",
time::strftime("%Y-%m-%d %H:%M:%S", &time::now()).unwrap(),
record.level().to_string(),
record.location().module_path(),
record.args());
let _ = self.tx.send(s);
}
}
pub fn init(spec: &str) {
let (tx, rx) = mpsc::channel();
let _log_thread = thread::spawn(move || {
let mut io = io::stdout();
loop {
let res : String = rx.recv().unwrap();
let _ = io.write(res.as_bytes());
}
});
let mut parts = spec.split("=");
let target = if let Some(target) = parts.next() {
target
} else {
println!("invalid log-spec, disabling log");
return;
};
let log_level = parts.next().unwrap_or("INFO");
let logger = ConsoleLogger::new(tx, target.to_string());
log::set_logger(|max_log_level| {
let log_level = log_level.parse().unwrap();
max_log_level.set(log_level);
return Box::new(logger);
}).unwrap();
}