1extern crate ansi_term;
61
62use ansi_term::Colour;
63use std::collections::HashMap;
64use std::fs::File;
65use std::io::{self, Write};
66use std::sync::{Arc, RwLock};
67use std::time::{SystemTime, UNIX_EPOCH};
68
69#[derive(PartialEq, PartialOrd, Clone, Copy)]
73pub enum Level {
74 DEBUG,
76 INFO,
78 WARN,
80 ERROR,
82 FATAL,
84 NONE,
86}
87
88pub struct Message {
92 level: Level,
94 name: String,
96 created: SystemTime,
98 msg: String,
100}
101
102
103pub trait Handler: Send + Sync {
107 fn emit(&self, message: &Message);
109}
110
111
112pub struct ConsoleHandler {}
118
119impl ConsoleHandler {
120 pub fn new() -> Arc<Box<Handler>> {
121 Arc::new(Box::new(ConsoleHandler {}))
122 }
123}
124
125
126impl Handler for ConsoleHandler {
127 fn emit(&self, message: &Message) {
128 let data = match message.level {
129 Level::DEBUG => Colour::Cyan.paint(format!("{} | {}\n", message.name, message.msg)),
130 Level::INFO => Colour::Green.paint(format!("{} | {}\n", message.name, message.msg)),
131 Level::WARN => Colour::Yellow.paint(format!("{} | {}\n", message.name, message.msg)),
132 Level::ERROR => Colour::Red.paint(format!("{} | {}\n", message.name, message.msg)),
133 Level::FATAL => Colour::Red.paint(format!("{} | {}\n", message.name, message.msg)),
134 Level::NONE => Colour::White.paint(""),
135 };
136
137 let stdout = io::stdout();
138 let mut handle = stdout.lock();
139
140 handle.write(data.to_string().as_bytes()).unwrap();
141 handle.flush().unwrap();
142 }
143}
144
145
146pub struct FileHandler {
158 out: Arc<RwLock<File>>,
159}
160
161
162impl FileHandler {
163 pub fn new(filename: &str) -> Arc<Box<Handler>> {
164 Arc::new(Box::new(FileHandler {
165 out: Arc::new(RwLock::new(File::create(filename).unwrap())),
166 }))
167 }
168}
169
170
171impl Handler for FileHandler {
172 fn emit(&self, message: &Message) {
173 let dur = message.created.duration_since(UNIX_EPOCH).unwrap();
174
175 let data = match message.level {
176 Level::DEBUG => {
177 format!(
178 "{:9}.{:0.09} | DEBUG | {:15} | {}\n",
179 dur.as_secs(),
180 dur.subsec_nanos(),
181 message.name,
182 message.msg
183 )
184 }
185 Level::INFO => {
186 format!(
187 "{:9}.{:0.09} | INFO | {:15} | {}\n",
188 dur.as_secs(),
189 dur.subsec_nanos(),
190 message.name,
191 message.msg
192 )
193 }
194 Level::WARN => {
195 format!(
196 "{:9}.{:0.09} | WARN | {:15} | {}\n",
197 dur.as_secs(),
198 dur.subsec_nanos(),
199 message.name,
200 message.msg
201 )
202 }
203 Level::ERROR => {
204 format!(
205 "{:9}.{:0.09} | ERROR | {:15} | {}\n",
206 dur.as_secs(),
207 dur.subsec_nanos(),
208 message.name,
209 message.msg
210 )
211 }
212 Level::FATAL => {
213 format!(
214 "{:9}.{:0.09} | FATAL | {:15} | {}\n",
215 dur.as_secs(),
216 dur.subsec_nanos(),
217 message.name,
218 message.msg
219 )
220 }
221 Level::NONE => "".to_string(),
222 };
223
224 let mut out = self.out.write().unwrap();
225 out.write(data.as_bytes()).unwrap();
226 out.flush().unwrap();
227 }
228}
229
230#[derive(Clone)]
236pub struct _Logger {
237 _name: String,
238 _full_name: String,
239 pub level: Level,
241 _parent: Option<Arc<_Logger>>,
242 _handlers: Arc<RwLock<Vec<Arc<Box<Handler>>>>>,
243 _children: Arc<RwLock<HashMap<String, Arc<_Logger>>>>,
244}
245
246
247impl _Logger {
248 pub fn add_handler(&self, handler: Arc<Box<Handler>>) {
252 let mut hs = self._handlers.write().unwrap();
253 hs.push(handler);
254 }
255
256 pub fn clear_handlers(&self) {
260 let mut hs = self._handlers.write().unwrap();
261 hs.clear();
262 }
263
264 pub fn name(&self) -> String {
266 self._name.clone()
267 }
268
269 pub fn full_name(&self) -> String {
271 self._full_name.clone()
272 }
273
274 pub fn log(&self, level: Level, msg: &str) {
278 if self.level <= level {
279 let message = Message {
280 level: level,
281 name: self._full_name.clone(),
282 created: SystemTime::now(),
283 msg: String::from(msg),
284 };
285
286 self.log_msg(&message);
287 }
288 }
289
290 fn log_msg(&self, message: &Message) {
291 let hs = self._handlers.read().unwrap();
292 for h in hs.iter() {
293 h.emit(&message);
294 }
295
296 if let Some(ref parent) = self._parent {
297 parent.log_msg(message);
298 }
299 }
300
301 pub fn debug(&self, fmt: &str) {
305 self.log(Level::DEBUG, fmt);
306 }
307
308 pub fn info(&self, fmt: &str) {
312 self.log(Level::INFO, fmt);
313 }
314
315 pub fn warn(&self, fmt: &str) {
319 self.log(Level::WARN, fmt);
320 }
321
322 pub fn error(&self, fmt: &str) {
326 self.log(Level::ERROR, fmt);
327 }
328
329 pub fn fatal(&self, fmt: &str) {
333 self.log(Level::FATAL, fmt);
334 }
335}
336
337pub type Logger = Arc<_Logger>;
339
340static mut ROOT: *const Logger = 0 as *const Logger;
341
342fn init() {
343 unsafe {
345 if ROOT == (0 as *const Logger) {
346 let root = Box::new(Arc::new(_Logger {
347 _name: String::new(),
348 _full_name: String::new(),
349 level: Level::DEBUG,
350 _parent: None,
351 _handlers: Arc::new(RwLock::new(Vec::new())),
352 _children: Arc::new(RwLock::new(HashMap::new())),
353 }));
354
355 ROOT = std::mem::transmute(root);
357 }
358 }
359}
360
361pub fn root() -> Logger {
365 init();
366 unsafe { (*ROOT).clone() }
367}
368
369pub fn debug(fmt: &str) {
373 init();
374
375 let result = unsafe { (*ROOT).clone() };
376
377 result.log(Level::DEBUG, fmt);
378}
379
380pub fn info(fmt: &str) {
384 init();
385
386 let result = unsafe { (*ROOT).clone() };
387
388 result.log(Level::INFO, fmt);
389}
390
391pub fn warn(fmt: &str) {
395 init();
396
397 let result = unsafe { (*ROOT).clone() };
398
399 result.log(Level::WARN, fmt);
400}
401
402pub fn error(fmt: &str) {
406 init();
407
408 let result = unsafe { (*ROOT).clone() };
409
410 result.log(Level::ERROR, fmt);
411}
412
413pub fn fatal(fmt: &str) {
417 init();
418
419 let result = unsafe { (*ROOT).clone() };
420
421 result.log(Level::FATAL, fmt);
422}
423
424pub fn get(name: &str) -> Logger {
432 init();
433
434 let path: Vec<&str> = name.split(".").collect();
435 let mut result = unsafe { (*ROOT).clone() };
436
437 for (idx, step) in path.iter().enumerate() {
438 result = {
439 let mut map = result._children.write().unwrap();
440
441 map.entry(step.to_string())
442 .or_insert_with(|| {
443 let full = path[1..idx + 1].iter().fold(
444 String::from(path[0]),
445 |a, b| format!("{}.{}", a, b),
446 );
447
448 Arc::new(_Logger {
449 _name: step.to_string(),
450 _full_name: full,
451 level: Level::DEBUG,
452 _parent: Some(result.clone()),
453 _handlers: Arc::new(RwLock::new(Vec::new())),
454 _children: Arc::new(RwLock::new(HashMap::new())),
455 })
456 })
457 .clone()
458 };
459 }
460
461 result
462}