1
0
mirror of https://github.com/Llewellynvdm/starship.git synced 2024-06-04 01:20:51 +00:00
starship/src/logger.rs
Tilmann Meyer 2233683410
feat: add error messaging (#1576)
This creates a custom logger for the log crate which logs everything to a file (/tmp/starship/session_$STARSHIP_SESSION_KEY.log) and it logs everything above Warn to stderr, but only if the log file does not contain the line that should be logged resulting in an error or warning to be only logged at the first starship invocation after opening the shell.
2020-09-28 16:38:50 -04:00

113 lines
3.6 KiB
Rust

use ansi_term::Color;
use log::{Level, LevelFilter, Metadata, Record};
use std::{
collections::HashSet,
env,
fs::{self, File, OpenOptions},
io::Write,
path::PathBuf,
sync::{Arc, Mutex},
};
pub struct StarshipLogger {
log_file: Arc<Mutex<File>>,
log_file_content: Arc<HashSet<String>>,
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")
});
fs::create_dir_all(&log_dir).expect("Unable to create log dir!");
let session_log_file = log_dir.join(format!(
"session_{}.log",
env::var("STARSHIP_SESSION_KEY").unwrap_or_default()
));
Self {
log_file_content: Arc::new(
fs::read_to_string(&session_log_file)
.unwrap_or_default()
.lines()
.map(|line| line.to_string())
.collect(),
),
log_file: Arc::new(Mutex::new(
OpenOptions::new()
.create(true)
.append(true)
.open(session_log_file)
.unwrap(),
)),
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
.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) {
self.log_file
.lock()
.map(|mut writer| writer.flush())
.expect("Log file writer mutex was poisoned!")
.expect("Unable to flush the log file!");
}
}
pub fn init() {
log::set_boxed_logger(Box::new(StarshipLogger::new())).unwrap();
log::set_max_level(LevelFilter::Trace);
}