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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use fern::Dispatch;
use std::path::Path;
use std::fs::{File, create_dir, OpenOptions};
use std::fmt::Display;
use colored::*;
use crate::{error::Error, Result};
pub use log::{Level, LevelFilter};
#[derive(Copy, Clone)]
pub struct Settings {
pub level: LevelFilter,
pub everything: bool,
}
pub fn get_log_file (path: &Path) -> Result<File> {
let now = ::chrono::Local::now().format("%Y_%m_%d__%H_%M_%S");
if path.exists() {
if !path.is_dir() {
return Err(Error::from(format!("{:?} is not a directory", path)));
}
} else {
create_dir(path).map_err(|e| Error::from(format!("could not create directory {:?}: {}", path, e)))?;
}
let mut path_buf = path.to_path_buf();
path_buf.push(&now.to_string());
path_buf.set_extension("log");
OpenOptions::new()
.create(true)
.write(true)
.open(&path_buf)
.map_err(|e| Error::from(format!("could not log to {:?}: {}", &path_buf, e)))
}
pub fn init (path: &Path, settings: Settings) {
let colors = ::fern::colors::ColoredLevelConfig::new()
.trace(Color::Blue)
.debug(Color::BrightBlue)
.info(Color::BrightGreen)
.warn(Color::BrightYellow)
.error(Color::BrightRed);
fn white <T: Display> (msg: T, colored: bool) -> String {
if colored {
format!("{}", format!("{}", msg).white())
} else {
format!("{}", msg)
}
}
macro_rules! format_msg {
($colored:expr) => {
move |out, message, record| {
out.finish(format_args!(
"{} {}:{} {}",
white(::chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), $colored),
if $colored {
format!("{}", colors.color(record.level()))
} else {
format!("{}", record.level())
},
if settings.everything {
white(format!(" {}", record.target()), $colored)
} else { "".to_owned() },
message
))
}
}
}
let mut dispatch = Dispatch::new()
.filter(move |metadata| {
settings.everything || &metadata.target()[0..9] == "torchbear"
})
.level(settings.level)
.chain(Dispatch::new()
.format( format_msg!(true) )
.chain(::std::io::stdout())
);
match ::std::fs::create_dir_all(path) {
Err(err) => error!("{}", err),
_ => match get_log_file(path) {
Ok(file) => {
dispatch = dispatch.chain(Dispatch::new()
.format( format_msg!(false) )
.chain(file)
);
},
Err(err) => error!("{}", err)
}
};
if dispatch.apply().is_err() {
panic!("A logger instance was already set");
}
}