1use crate::log::Log;
2use crate::sink::Sink;
3use async_trait::async_trait;
4use colored::*;
5use lazy_static::lazy_static;
6
7struct Color(u8, u8, u8);
8
9lazy_static! {
10 static ref ERROR: Color = Color(255, 38, 0);
11 static ref VERBOSE: Color = Color(255, 255, 255);
12 static ref INFO: Color = Color(5, 215, 2);
13 static ref WARNING: Color = Color(215, 95, 2);
14 static ref DEBUG: Color = Color(95, 175, 255);
15}
16
17macro_rules! error {
18 ($s:expr) => {
19 println!("{}", $s.truecolor(ERROR.0, ERROR.1, ERROR.2))
20 };
21}
22
23macro_rules! warn {
24 ($s:expr) => {
25 println!("{}", $s.truecolor(WARNING.0, WARNING.1, WARNING.2))
26 };
27}
28
29macro_rules! info {
30 ($s:expr) => {
31 println!("{}", $s.truecolor(INFO.0, INFO.1, INFO.2))
32 };
33}
34
35macro_rules! debug {
36 ($s:expr) => {
37 println!("{}", $s.truecolor(DEBUG.0, DEBUG.1, DEBUG.2))
38 };
39}
40
41macro_rules! verbose {
42 ($s:expr) => {
43 println!("{}", $s.truecolor(VERBOSE.0, VERBOSE.1, VERBOSE.2))
44 };
45}
46
47pub(crate) struct TerminalSink {
48 color: bool,
49 tag_width: usize,
50}
51
52impl TerminalSink {
53 #[allow(dead_code)]
54 pub(crate) fn new(color: String, tag_width: usize) -> Self {
55 Self {
56 color: color == "always" || color == "auto",
57 tag_width,
58 }
59 }
60
61 fn terminal_print(&self, level: &str, s: String) {
62 if self.color {
63 match level {
64 "V" => verbose!(s),
65 "D" => debug!(s),
66 "I" => info!(s),
67 "W" => warn!(s),
68 "E" => error!(s),
69 "F" => error!(s),
70 _ => verbose!(s),
71 };
72 }
73 }
74}
75
76#[async_trait]
77impl Sink for TerminalSink {
78 async fn write(&self, log: Log) {
79 let mut tag = log.tag;
80 if tag.len() > self.tag_width {
81 tag.truncate(self.tag_width);
82 }
83 let message = &log.message.split('\n').collect::<Vec<&str>>();
84 for (i, s) in message.iter().enumerate() {
85 let s = if i == 0 {
86 format!(
87 "{:11} {:>5} {:<5} {:width$} {:^3} {}",
88 log.time,
89 log.pid,
90 log.tid,
91 tag,
92 log.level.on_truecolor(88, 88, 88),
93 s,
94 width = self.tag_width
95 )
96 } else {
97 format!(
98 "{:12} {:>5} {:<5} {:width$} {:^3} {}",
99 "",
100 "",
101 "",
102 " ",
103 log.level.on_truecolor(88, 88, 88),
104 s,
105 width = self.tag_width
106 )
107 };
108 if self.color {
109 self.terminal_print(log.level.as_str(), s);
110 } else {
111 println!("{}", s);
112 }
113 }
114 }
115}