2022-08-09 18:44:37 +02:00
|
|
|
use log::{Level, LevelFilter, SetLoggerError};
|
2022-01-01 22:42:50 +01:00
|
|
|
use nu_protocol::ShellError;
|
2022-08-09 18:44:37 +02:00
|
|
|
use simplelog::{
|
|
|
|
format_description, Color, ColorChoice, Config, ConfigBuilder, LevelPadding, TermLogger,
|
|
|
|
TerminalMode, WriteLogger,
|
|
|
|
};
|
|
|
|
|
|
|
|
use std::{fs::File, path::Path, str::FromStr};
|
|
|
|
|
|
|
|
pub enum LogTarget {
|
|
|
|
Stdout,
|
|
|
|
Stderr,
|
|
|
|
Mixed,
|
|
|
|
File,
|
2022-01-01 22:42:50 +01:00
|
|
|
}
|
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
impl From<&str> for LogTarget {
|
|
|
|
fn from(s: &str) -> Self {
|
|
|
|
match s {
|
|
|
|
"stdout" => Self::Stdout,
|
|
|
|
"mixed" => Self::Mixed,
|
|
|
|
"file" => Self::File,
|
|
|
|
_ => Self::Stderr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-09 23:08:16 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
pub fn logger(
|
|
|
|
f: impl FnOnce(&mut ConfigBuilder) -> (LevelFilter, LogTarget),
|
|
|
|
) -> Result<(), ShellError> {
|
|
|
|
let mut builder = ConfigBuilder::new();
|
|
|
|
let (level, target) = f(&mut builder);
|
|
|
|
|
|
|
|
let config = builder.build();
|
|
|
|
let _ = match target {
|
|
|
|
LogTarget::Stdout => {
|
|
|
|
TermLogger::init(level, config, TerminalMode::Stdout, ColorChoice::Auto)
|
|
|
|
}
|
|
|
|
LogTarget::Mixed => TermLogger::init(level, config, TerminalMode::Mixed, ColorChoice::Auto),
|
|
|
|
LogTarget::File => {
|
|
|
|
let pid = std::process::id();
|
|
|
|
let mut path = std::env::temp_dir();
|
2023-01-30 02:37:54 +01:00
|
|
|
path.push(format!("nu-{pid}.log"));
|
2022-08-09 18:44:37 +02:00
|
|
|
|
|
|
|
set_write_logger(level, config, &path)
|
|
|
|
}
|
|
|
|
_ => TermLogger::init(level, config, TerminalMode::Stderr, ColorChoice::Auto),
|
|
|
|
};
|
2022-02-09 23:08:16 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
Ok(())
|
|
|
|
}
|
2022-02-09 23:08:16 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
fn set_write_logger(level: LevelFilter, config: Config, path: &Path) -> Result<(), SetLoggerError> {
|
|
|
|
// Use TermLogger instead if WriteLogger is not available
|
2023-01-24 12:23:42 +01:00
|
|
|
if let Ok(file) = File::create(path) {
|
|
|
|
WriteLogger::init(level, config, file)
|
|
|
|
} else {
|
|
|
|
let default_logger =
|
|
|
|
TermLogger::init(level, config, TerminalMode::Stderr, ColorChoice::Auto);
|
2022-02-09 23:08:16 +01:00
|
|
|
|
2023-01-24 12:23:42 +01:00
|
|
|
if default_logger.is_ok() {
|
|
|
|
log::warn!("failed to init WriteLogger, use TermLogger instead");
|
2022-08-09 18:44:37 +02:00
|
|
|
}
|
2023-01-24 12:23:42 +01:00
|
|
|
|
|
|
|
default_logger
|
2022-08-09 18:44:37 +02:00
|
|
|
}
|
2022-02-09 23:08:16 +01:00
|
|
|
}
|
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
pub fn configure(
|
|
|
|
level: &str,
|
|
|
|
target: &str,
|
|
|
|
builder: &mut ConfigBuilder,
|
|
|
|
) -> (LevelFilter, LogTarget) {
|
|
|
|
let level = match Level::from_str(level) {
|
|
|
|
Ok(level) => level,
|
|
|
|
Err(_) => Level::Warn,
|
2022-01-01 22:42:50 +01:00
|
|
|
};
|
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
// Add allowed module filter
|
|
|
|
builder.add_filter_allow_str("nu");
|
2022-01-01 22:42:50 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
// Set level padding
|
|
|
|
builder.set_level_padding(LevelPadding::Right);
|
2022-01-01 22:42:50 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
// Custom time format
|
|
|
|
builder.set_time_format_custom(format_description!(
|
|
|
|
"[year]-[month]-[day] [hour repr:12]:[minute]:[second].[subsecond digits:3] [period]"
|
|
|
|
));
|
2022-01-01 22:42:50 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
// Show module path
|
|
|
|
builder.set_target_level(LevelFilter::Error);
|
|
|
|
|
|
|
|
// Don't show thread id
|
|
|
|
builder.set_thread_level(LevelFilter::Off);
|
2022-02-09 23:08:16 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
let log_target = LogTarget::from(target);
|
2022-02-09 23:08:16 +01:00
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
// Only TermLogger supports color output
|
2022-08-10 13:52:11 +02:00
|
|
|
if matches!(
|
|
|
|
log_target,
|
|
|
|
LogTarget::Stdout | LogTarget::Stderr | LogTarget::Mixed
|
|
|
|
) {
|
|
|
|
Level::iter().for_each(|level| set_colored_level(builder, level));
|
2022-02-09 23:08:16 +01:00
|
|
|
}
|
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
(level.to_level_filter(), log_target)
|
2022-02-09 23:08:16 +01:00
|
|
|
}
|
|
|
|
|
2022-08-09 18:44:37 +02:00
|
|
|
fn set_colored_level(builder: &mut ConfigBuilder, level: Level) {
|
|
|
|
let color = match level {
|
|
|
|
Level::Trace => Color::Magenta,
|
|
|
|
Level::Debug => Color::Blue,
|
|
|
|
Level::Info => Color::Green,
|
|
|
|
Level::Warn => Color::Yellow,
|
|
|
|
Level::Error => Color::Red,
|
|
|
|
};
|
|
|
|
|
|
|
|
builder.set_level_color(level, Some(color));
|
2022-02-09 23:08:16 +01:00
|
|
|
}
|