use std::fmt::Arguments;
use colored::Color;
use colored::ColoredString;
use colored::Colorize;
use jiff::tz::TimeZone;
use jiff::Zoned;
use log::Level;
use crate::layout::KvDisplay;
use crate::layout::Layout;
#[derive(Default, Debug, Clone)]
pub struct TextLayout {
pub colors: LevelColor,
pub tz: Option<TimeZone>,
}
#[derive(Debug, Clone)]
pub struct LevelColor {
pub error: Color,
pub warn: Color,
pub info: Color,
pub debug: Color,
pub trace: Color,
}
impl Default for LevelColor {
fn default() -> Self {
Self {
error: Color::Red,
warn: Color::Yellow,
info: Color::Green,
debug: Color::Blue,
trace: Color::Magenta,
}
}
}
impl TextLayout {
pub(crate) fn format<F>(&self, record: &log::Record, f: &F) -> anyhow::Result<()>
where
F: Fn(Arguments) -> anyhow::Result<()>,
{
let color = match record.level() {
Level::Error => self.colors.error,
Level::Warn => self.colors.warn,
Level::Info => self.colors.info,
Level::Debug => self.colors.debug,
Level::Trace => self.colors.trace,
};
let time = match self.tz.clone() {
Some(tz) => Zoned::now().with_time_zone(tz),
None => Zoned::now(),
}
.strftime("%Y-%m-%dT%H:%M:%S.%6f%:z");
let level = ColoredString::from(record.level().to_string()).color(color);
let module = record.module_path().unwrap_or_default();
let file = record.file().unwrap_or_default();
let line = record.line().unwrap_or_default();
let message = record.args();
let kvs = KvDisplay::new(record.key_values());
f(format_args!(
"{time} {level:>5} {module}: {file}:{line} {message}{kvs}"
))
}
}
impl From<TextLayout> for Layout {
fn from(layout: TextLayout) -> Self {
Layout::Text(layout)
}
}