use std::{
fmt::{Arguments, Display, Error, Formatter},
time::Duration
};
use log::{Level, Record};
pub struct Timestamp {
minutes: u64,
seconds: u64,
millis: u32
}
impl Timestamp {
pub const fn new(minutes: u64, seconds: u64, millis: u32) -> Self {
Timestamp {
minutes,
seconds,
millis
}
}
}
impl From<Duration> for Timestamp {
fn from(duration: Duration) -> Self {
let minutes = duration.as_secs() / 60;
let seconds = duration.as_secs() % 60;
let millis = duration.subsec_millis();
Timestamp::new(minutes, seconds, millis)
}
}
impl Display for Timestamp {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(
f,
"+{:0>3}:{:0>2}.{:0>4}",
self.minutes, self.seconds, self.millis
)
}
}
pub struct LogLine<'r> {
timestamp: Timestamp,
level: Level,
target: &'r str,
args: &'r Arguments<'r>
}
impl<'r> LogLine<'r> {
pub fn new(timestamp: Timestamp, record: &'r Record<'r>) -> Self {
LogLine {
timestamp,
level: record.level(),
target: record.target(),
args: record.args()
}
}
}
impl<'r> Display for LogLine<'r> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(
f,
"[{}][{}] ({}) {}",
self.timestamp, self.level, self.target, self.args
)
}
}
pub mod ignore_list {
use log::Record;
use std::borrow::Cow;
pub type IgnoreListPatterns<'a> = Cow<'a, [Cow<'a, str>]>;
#[derive(Debug, Default)]
pub struct IgnoreList<'a> {
patterns: IgnoreListPatterns<'a>
}
impl<'a> IgnoreList<'a> {
pub const EMPTY_PATTERNS: IgnoreListPatterns<'static> = Cow::Borrowed(&[]);
pub const fn new(patterns: IgnoreListPatterns<'a>) -> Self {
IgnoreList { patterns }
}
pub fn ignore(&self, record: &Record) -> bool {
self.patterns
.iter()
.any(|p| record.target().contains(p.as_ref()))
}
}
}
#[cfg(feature = "colored_logline")]
pub mod colored_logline {
use std::fmt::{Arguments, Display, Error, Formatter};
use log::{Level, Record};
use termion::color::{self, Fg};
use super::Timestamp;
pub struct ColoredLogLine<'r> {
timestamp: Timestamp,
level: Level,
target: &'r str,
args: &'r Arguments<'r>
}
impl<'r> ColoredLogLine<'r> {
pub fn new(timestamp: Timestamp, record: &'r Record<'r>) -> Self {
ColoredLogLine {
timestamp,
level: record.level(),
target: record.target(),
args: record.args()
}
}
}
impl<'r> Display for ColoredLogLine<'r> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
#[derive(Debug)]
struct ApiDesignIsHard(Level);
impl termion::color::Color for ApiDesignIsHard {
fn write_fg(&self, f: &mut Formatter) -> Result<(), Error> {
match self.0 {
Level::Error => color::Red.write_fg(f),
Level::Warn => color::Yellow.write_fg(f),
Level::Info => color::Green.write_fg(f),
Level::Debug => color::Blue.write_fg(f),
Level::Trace => color::Magenta.write_fg(f)
}
}
fn write_bg(&self, _: &mut Formatter) -> Result<(), Error> {
unimplemented!()
}
}
write!(
f,
"[{}{}{}][{}{}{}] ({}{}{}) {}",
Fg(color::Yellow),
self.timestamp,
Fg(color::Reset),
Fg(ApiDesignIsHard(self.level)),
self.level,
Fg(color::Reset),
Fg(color::Cyan),
self.target,
Fg(color::Reset),
self.args
)
}
}
}