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
#[macro_use]
extern crate emit;
extern crate ansi_term;
extern crate chrono;

use std::io;
use std::error::Error;
use ansi_term::{Style,Colour,ANSIString};
use emit::LogLevel;
use emit::events::Event;
use emit::collectors::AcceptEvents;
use emit::templates::repl::MessageTemplateRepl;
use std::io::Write;
use chrono::Local;

pub struct AnsiTerminalCollector {}

impl AnsiTerminalCollector {
    pub fn new() -> Self {
        AnsiTerminalCollector{}
    }
}

static LEVEL_COLORS: [(Colour,Colour); 6] = [
    (Colour::White,  Colour::Red),
    (Colour::White,  Colour::Red),
    (Colour::Yellow, Colour::Black),
    (Colour::White,  Colour::Black),
    (Colour::Cyan,   Colour::Black),
    (Colour::Cyan,   Colour::Black)
];

static LEVEL_NAMES: [&'static str; 6] = [
    "OFF",
    "ERR",
    "WRN",
    "INF",
    "DBG",
    "TRA"
];

fn to_colored_level(level: LogLevel) -> ANSIString<'static> {
    let n = LEVEL_NAMES[level as usize];
    let c = LEVEL_COLORS[level as usize];
    Style::new().fg(c.0).bold().on(c.1).paint(n)
}

impl AcceptEvents for AnsiTerminalCollector {
    fn accept_events(&self, events: &[Event<'static>])-> Result<(), Box<Error>> {
        let bold = Style::new().bold();
        for event in events {
            let out = io::stdout();
            let mut to = &mut out.lock();
            let repl = MessageTemplateRepl::new(event.message_template().text());
            let content = repl.replace(event.properties());
            try!(writeln!(to, "[{} {}] {}",
                event.timestamp().with_timezone(&Local).format("%T%.3f"),
                 to_colored_level(event.level()),
                 bold.paint(content)));
        }
        
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use emit::PipelineBuilder;
    use super::AnsiTerminalCollector;

    #[test]
    fn it_works() {        
        let _flush = PipelineBuilder::new()
            .write_to(AnsiTerminalCollector::new())
            .init();

        info!("Hello, {}!", name: "Alice");
        error!("Goodbye, {}!", number: 42);
    }
}