2020-09-28 20:38:50 +00:00
|
|
|
use ansi_term::Color;
|
|
|
|
use log::{Level, LevelFilter, Metadata, Record};
|
2020-10-27 18:00:53 +00:00
|
|
|
use once_cell::sync::OnceCell;
|
2020-09-28 20:38:50 +00:00
|
|
|
use std::{
|
|
|
|
collections::HashSet,
|
|
|
|
env,
|
|
|
|
fs::{self, File, OpenOptions},
|
|
|
|
io::Write,
|
|
|
|
path::PathBuf,
|
2020-10-27 18:00:53 +00:00
|
|
|
sync::Mutex,
|
2020-09-28 20:38:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
pub struct StarshipLogger {
|
2020-10-27 18:00:53 +00:00
|
|
|
log_file: OnceCell<Mutex<File>>,
|
|
|
|
log_file_path: PathBuf,
|
|
|
|
log_file_content: HashSet<String>,
|
2020-09-28 20:38:50 +00:00
|
|
|
log_level: Level,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StarshipLogger {
|
|
|
|
fn new() -> Self {
|
|
|
|
let log_dir = env::var_os("STARSHIP_CACHE")
|
|
|
|
.map(PathBuf::from)
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
dirs_next::home_dir()
|
|
|
|
.expect("Unable to find home directory")
|
|
|
|
.join(".cache/starship")
|
|
|
|
});
|
|
|
|
|
2020-10-14 16:13:44 +00:00
|
|
|
fs::create_dir_all(&log_dir)
|
|
|
|
.unwrap_or_else(|err| panic!("Unable to create log dir {:?}: {:?}!", log_dir, err));
|
2020-09-28 20:38:50 +00:00
|
|
|
let session_log_file = log_dir.join(format!(
|
|
|
|
"session_{}.log",
|
|
|
|
env::var("STARSHIP_SESSION_KEY").unwrap_or_default()
|
|
|
|
));
|
|
|
|
|
|
|
|
Self {
|
2020-10-27 18:00:53 +00:00
|
|
|
log_file_content: fs::read_to_string(&session_log_file)
|
|
|
|
.unwrap_or_default()
|
|
|
|
.lines()
|
|
|
|
.map(|line| line.to_string())
|
|
|
|
.collect(),
|
|
|
|
log_file: OnceCell::new(),
|
|
|
|
log_file_path: session_log_file,
|
2020-09-28 20:38:50 +00:00
|
|
|
log_level: env::var("STARSHIP_LOG")
|
|
|
|
.map(|level| match level.to_lowercase().as_str() {
|
|
|
|
"trace" => Level::Trace,
|
|
|
|
"debug" => Level::Debug,
|
|
|
|
"info" => Level::Info,
|
|
|
|
"warn" => Level::Warn,
|
|
|
|
"error" => Level::Error,
|
|
|
|
_ => Level::Warn,
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|_| Level::Warn),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl log::Log for StarshipLogger {
|
|
|
|
fn enabled(&self, metadata: &Metadata) -> bool {
|
|
|
|
metadata.level() <= self.log_level
|
|
|
|
}
|
|
|
|
|
|
|
|
fn log(&self, record: &Record) {
|
|
|
|
let to_print = format!(
|
|
|
|
"[{}] - ({}): {}",
|
|
|
|
record.level(),
|
|
|
|
record.module_path().unwrap_or_default(),
|
|
|
|
record.args()
|
|
|
|
);
|
|
|
|
|
|
|
|
if record.metadata().level() <= Level::Warn {
|
|
|
|
self.log_file
|
2020-10-27 18:00:53 +00:00
|
|
|
.get_or_try_init(|| {
|
|
|
|
let m = Mutex::new(
|
|
|
|
OpenOptions::new()
|
|
|
|
.create(true)
|
|
|
|
.append(true)
|
|
|
|
.open(&self.log_file_path)?,
|
|
|
|
);
|
|
|
|
Ok(m)
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|err: std::io::Error| {
|
|
|
|
panic!(
|
|
|
|
"Unable to open session log file {:?}: {:?}!",
|
|
|
|
self.log_file_path, err
|
|
|
|
)
|
|
|
|
})
|
2020-09-28 20:38:50 +00:00
|
|
|
.lock()
|
|
|
|
.map(|mut file| writeln!(file, "{}", to_print))
|
|
|
|
.expect("Log file writer mutex was poisoned!")
|
|
|
|
.expect("Unable to write to the log file!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.enabled(record.metadata()) && !self.log_file_content.contains(to_print.as_str()) {
|
|
|
|
eprintln!(
|
|
|
|
"[{}] - ({}): {}",
|
|
|
|
match record.level() {
|
|
|
|
Level::Trace => Color::Black.dimmed().paint(format!("{}", record.level())),
|
|
|
|
Level::Debug => Color::Black.paint(format!("{}", record.level())),
|
|
|
|
Level::Info => Color::White.paint(format!("{}", record.level())),
|
|
|
|
Level::Warn => Color::Yellow.paint(format!("{}", record.level())),
|
|
|
|
Level::Error => Color::Red.paint(format!("{}", record.level())),
|
|
|
|
},
|
|
|
|
record.module_path().unwrap_or_default(),
|
|
|
|
record.args()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flush(&self) {
|
2020-10-27 18:00:53 +00:00
|
|
|
if let Some(m) = self.log_file.get() {
|
|
|
|
m.lock()
|
|
|
|
.map(|mut writer| writer.flush())
|
|
|
|
.expect("Log file writer mutex was poisoned!")
|
|
|
|
.expect("Unable to flush the log file!");
|
|
|
|
}
|
2020-09-28 20:38:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn init() {
|
|
|
|
log::set_boxed_logger(Box::new(StarshipLogger::new())).unwrap();
|
|
|
|
log::set_max_level(LevelFilter::Trace);
|
|
|
|
}
|