use crate::DeferredNow;
use log::Record;
use std::thread;
#[cfg(feature = "colors")]
use yansi::{Color, Paint, Style};
pub fn default_format(
w: &mut dyn std::io::Write,
_now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
write!(
w,
"{} [{}] {}",
record.level(),
record.module_path().unwrap_or("<unnamed>"),
record.args()
)
}
#[allow(clippy::doc_markdown)]
#[cfg(feature = "colors")]
pub fn colored_default_format(
w: &mut dyn std::io::Write,
_now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
let level = record.level();
write!(
w,
"{} [{}] {}",
style(level, level),
record.module_path().unwrap_or("<unnamed>"),
style(level, record.args())
)
}
pub fn opt_format(
w: &mut dyn std::io::Write,
now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
write!(
w,
"[{}] {} [{}:{}] {}",
now.now().format("%Y-%m-%d %H:%M:%S%.6f %:z"),
record.level(),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
&record.args()
)
}
#[cfg(feature = "colors")]
pub fn colored_opt_format(
w: &mut dyn std::io::Write,
now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
let level = record.level();
write!(
w,
"[{}] {} [{}:{}] {}",
style(level, now.now().format("%Y-%m-%d %H:%M:%S%.6f %:z")),
style(level, level),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
style(level, &record.args())
)
}
pub fn detailed_format(
w: &mut dyn std::io::Write,
now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
write!(
w,
"[{}] {} [{}] {}:{}: {}",
now.now().format("%Y-%m-%d %H:%M:%S%.6f %:z"),
record.level(),
record.module_path().unwrap_or("<unnamed>"),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
&record.args()
)
}
#[cfg(feature = "colors")]
pub fn colored_detailed_format(
w: &mut dyn std::io::Write,
now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
let level = record.level();
write!(
w,
"[{}] {} [{}] {}:{}: {}",
style(level, now.now().format("%Y-%m-%d %H:%M:%S%.6f %:z")),
style(level, record.level()),
record.module_path().unwrap_or("<unnamed>"),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
style(level, &record.args())
)
}
pub fn with_thread(
w: &mut dyn std::io::Write,
now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
write!(
w,
"[{}] T[{:?}] {} [{}:{}] {}",
now.now().format("%Y-%m-%d %H:%M:%S%.6f %:z"),
thread::current().name().unwrap_or("<unnamed>"),
record.level(),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
&record.args()
)
}
#[cfg(feature = "colors")]
pub fn colored_with_thread(
w: &mut dyn std::io::Write,
now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
let level = record.level();
write!(
w,
"[{}] T[{:?}] {} [{}:{}] {}",
style(level, now.now().format("%Y-%m-%d %H:%M:%S%.6f %:z")),
style(level, thread::current().name().unwrap_or("<unnamed>")),
style(level, level),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
style(level, &record.args())
)
}
#[cfg(feature = "colors")]
pub fn style<T>(level: log::Level, item: T) -> Paint<T> {
match level {
log::Level::Error => Paint::new(item).with_style(PALETTE.error),
log::Level::Warn => Paint::new(item).with_style(PALETTE.warn),
log::Level::Info => Paint::new(item).with_style(PALETTE.info),
log::Level::Debug => Paint::new(item).with_style(PALETTE.debug),
log::Level::Trace => Paint::new(item).with_style(PALETTE.trace),
}
}
#[cfg(feature = "colors")]
lazy_static::lazy_static! {
static ref PALETTE: Palette = {
match std::env::var("FLEXI_LOGGER_PALETTE") {
Ok(palette) => Palette::parse(&palette).unwrap_or_else(|_| Palette::default()),
Err(..) => Palette::default(),
}
};
}
#[cfg(feature = "colors")]
struct Palette {
pub error: Style,
pub warn: Style,
pub info: Style,
pub debug: Style,
pub trace: Style,
}
#[cfg(feature = "colors")]
impl Palette {
fn default() -> Palette {
Palette {
error: Style::new(Color::Fixed(196)).bold(),
warn: Style::new(Color::Fixed(208)).bold(),
info: Style::new(Color::Unset),
debug: Style::new(Color::Fixed(7)),
trace: Style::new(Color::Fixed(8)),
}
}
fn parse(palette: &str) -> Result<Palette, std::num::ParseIntError> {
let mut items = palette.split(';');
Ok(Palette {
error: parse_style(items.next().unwrap_or("196").trim())?,
warn: parse_style(items.next().unwrap_or("208").trim())?,
info: parse_style(items.next().unwrap_or("-").trim())?,
debug: parse_style(items.next().unwrap_or("7").trim())?,
trace: parse_style(items.next().unwrap_or("8").trim())?,
})
}
}
#[cfg(feature = "colors")]
fn parse_style(input: &str) -> Result<Style, std::num::ParseIntError> {
Ok(if input == "-" {
Style::new(Color::Unset)
} else {
Style::new(Color::Fixed(input.parse()?))
})
}